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_pata *pata =
1029 &ccb->cts.xport_specific.ata;
1031 if (pata->valid & CTS_ATA_VALID_MODE)
1032 speed = ata_mode2speed(pata->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_pata *pata =
1076 &ccb->cts.xport_specific.ata;
1079 if (pata->valid & CTS_ATA_VALID_MODE)
1080 printf("%s, ", ata_mode2string(pata->mode));
1081 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1082 printf("ATAPI %dbytes, ", pata->atapi);
1083 if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1084 printf("PIO %dbytes", pata->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_FC) {
2895 struct ccb_trans_settings_fc *fc =
2896 &cts->xport_specific.fc;
2898 if (fc->valid & CTS_FC_VALID_WWNN)
2899 fprintf(stdout, "%sWWNN: 0x%llx", pathstr,
2900 (long long) fc->wwnn);
2901 if (fc->valid & CTS_FC_VALID_WWPN)
2902 fprintf(stdout, "%sWWPN: 0x%llx", pathstr,
2903 (long long) fc->wwpn);
2904 if (fc->valid & CTS_FC_VALID_PORT)
2905 fprintf(stdout, "%sPortID: 0x%x", pathstr, fc->port);
2906 if (fc->valid & CTS_FC_VALID_SPEED)
2907 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2908 pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
2910 if (cts->transport == XPORT_SAS) {
2911 struct ccb_trans_settings_sas *sas =
2912 &cts->xport_specific.sas;
2914 if (sas->valid & CTS_SAS_VALID_SPEED)
2915 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2916 pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
2918 if (cts->transport == XPORT_ATA) {
2919 struct ccb_trans_settings_pata *pata =
2920 &cts->xport_specific.ata;
2922 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
2923 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2924 ata_mode2string(pata->mode));
2926 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2927 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2930 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2931 fprintf(stdout, "%sPIO transaction length: %d\n",
2932 pathstr, pata->bytecount);
2935 if (cts->transport == XPORT_SATA) {
2936 struct ccb_trans_settings_sata *sata =
2937 &cts->xport_specific.sata;
2939 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2940 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2943 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2944 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2945 ata_mode2string(sata->mode));
2947 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2948 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2951 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2952 fprintf(stdout, "%sPIO transaction length: %d\n",
2953 pathstr, sata->bytecount);
2955 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2956 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2959 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2960 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2963 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2964 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2968 if (cts->protocol == PROTO_ATA) {
2969 struct ccb_trans_settings_ata *ata=
2970 &cts->proto_specific.ata;
2972 if (ata->valid & CTS_ATA_VALID_TQ) {
2973 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
2974 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
2975 "enabled" : "disabled");
2978 if (cts->protocol == PROTO_SCSI) {
2979 struct ccb_trans_settings_scsi *scsi=
2980 &cts->proto_specific.scsi;
2982 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2983 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
2984 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2985 "enabled" : "disabled");
2992 * Get a path inquiry CCB for the specified device.
2995 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
3000 ccb = cam_getccb(device);
3002 warnx("get_cpi: couldn't allocate CCB");
3005 bzero(&(&ccb->ccb_h)[1],
3006 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3007 ccb->ccb_h.func_code = XPT_PATH_INQ;
3008 if (cam_send_ccb(device, ccb) < 0) {
3009 warn("get_cpi: error sending Path Inquiry CCB");
3010 if (arglist & CAM_ARG_VERBOSE)
3011 cam_error_print(device, ccb, CAM_ESF_ALL,
3012 CAM_EPF_ALL, stderr);
3014 goto get_cpi_bailout;
3016 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3017 if (arglist & CAM_ARG_VERBOSE)
3018 cam_error_print(device, ccb, CAM_ESF_ALL,
3019 CAM_EPF_ALL, stderr);
3021 goto get_cpi_bailout;
3023 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
3031 * Get a get device CCB for the specified device.
3034 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
3039 ccb = cam_getccb(device);
3041 warnx("get_cgd: couldn't allocate CCB");
3044 bzero(&(&ccb->ccb_h)[1],
3045 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3046 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
3047 if (cam_send_ccb(device, ccb) < 0) {
3048 warn("get_cgd: error sending Path Inquiry CCB");
3049 if (arglist & CAM_ARG_VERBOSE)
3050 cam_error_print(device, ccb, CAM_ESF_ALL,
3051 CAM_EPF_ALL, stderr);
3053 goto get_cgd_bailout;
3055 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3056 if (arglist & CAM_ARG_VERBOSE)
3057 cam_error_print(device, ccb, CAM_ESF_ALL,
3058 CAM_EPF_ALL, stderr);
3060 goto get_cgd_bailout;
3062 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3070 cpi_print(struct ccb_pathinq *cpi)
3072 char adapter_str[1024];
3075 snprintf(adapter_str, sizeof(adapter_str),
3076 "%s%d:", cpi->dev_name, cpi->unit_number);
3078 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3081 for (i = 1; i < 0xff; i = i << 1) {
3084 if ((i & cpi->hba_inquiry) == 0)
3087 fprintf(stdout, "%s supports ", adapter_str);
3091 str = "MDP message";
3094 str = "32 bit wide SCSI";
3097 str = "16 bit wide SCSI";
3100 str = "SDTR message";
3103 str = "linked CDBs";
3106 str = "tag queue messages";
3109 str = "soft reset alternative";
3112 str = "SATA Port Multiplier";
3115 str = "unknown PI bit set";
3118 fprintf(stdout, "%s\n", str);
3121 for (i = 1; i < 0xff; i = i << 1) {
3124 if ((i & cpi->hba_misc) == 0)
3127 fprintf(stdout, "%s ", adapter_str);
3131 str = "bus scans from high ID to low ID";
3134 str = "removable devices not included in scan";
3136 case PIM_NOINITIATOR:
3137 str = "initiator role not supported";
3139 case PIM_NOBUSRESET:
3140 str = "user has disabled initial BUS RESET or"
3141 " controller is in target/mixed mode";
3144 str = "do not send 6-byte commands";
3147 str = "scan bus sequentially";
3150 str = "unknown PIM bit set";
3153 fprintf(stdout, "%s\n", str);
3156 for (i = 1; i < 0xff; i = i << 1) {
3159 if ((i & cpi->target_sprt) == 0)
3162 fprintf(stdout, "%s supports ", adapter_str);
3165 str = "target mode processor mode";
3168 str = "target mode phase cog. mode";
3170 case PIT_DISCONNECT:
3171 str = "disconnects in target mode";
3174 str = "terminate I/O message in target mode";
3177 str = "group 6 commands in target mode";
3180 str = "group 7 commands in target mode";
3183 str = "unknown PIT bit set";
3187 fprintf(stdout, "%s\n", str);
3189 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3191 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3193 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3195 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3196 adapter_str, cpi->hpath_id);
3197 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3199 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3200 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3201 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
3202 adapter_str, cpi->hba_vendor);
3203 fprintf(stdout, "%s HBA device ID: 0x%04x\n",
3204 adapter_str, cpi->hba_device);
3205 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
3206 adapter_str, cpi->hba_subvendor);
3207 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
3208 adapter_str, cpi->hba_subdevice);
3209 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3210 fprintf(stdout, "%s base transfer speed: ", adapter_str);
3211 if (cpi->base_transfer_speed > 1000)
3212 fprintf(stdout, "%d.%03dMB/sec\n",
3213 cpi->base_transfer_speed / 1000,
3214 cpi->base_transfer_speed % 1000);
3216 fprintf(stdout, "%dKB/sec\n",
3217 (cpi->base_transfer_speed % 1000) * 1000);
3218 fprintf(stdout, "%s maximum transfer size: %u bytes\n",
3219 adapter_str, cpi->maxio);
3223 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3224 struct ccb_trans_settings *cts)
3230 ccb = cam_getccb(device);
3233 warnx("get_print_cts: error allocating ccb");
3237 bzero(&(&ccb->ccb_h)[1],
3238 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3240 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3242 if (user_settings == 0)
3243 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3245 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3247 if (cam_send_ccb(device, ccb) < 0) {
3248 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3249 if (arglist & CAM_ARG_VERBOSE)
3250 cam_error_print(device, ccb, CAM_ESF_ALL,
3251 CAM_EPF_ALL, stderr);
3253 goto get_print_cts_bailout;
3256 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3257 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3258 if (arglist & CAM_ARG_VERBOSE)
3259 cam_error_print(device, ccb, CAM_ESF_ALL,
3260 CAM_EPF_ALL, stderr);
3262 goto get_print_cts_bailout;
3266 cts_print(device, &ccb->cts);
3269 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3271 get_print_cts_bailout:
3279 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3280 int argc, char **argv, char *combinedopt)
3284 int user_settings = 0;
3286 int disc_enable = -1, tag_enable = -1;
3289 double syncrate = -1;
3292 int change_settings = 0, send_tur = 0;
3293 struct ccb_pathinq cpi;
3295 ccb = cam_getccb(device);
3297 warnx("ratecontrol: error allocating ccb");
3300 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3309 if (strncasecmp(optarg, "enable", 6) == 0)
3311 else if (strncasecmp(optarg, "disable", 7) == 0)
3314 warnx("-D argument \"%s\" is unknown", optarg);
3316 goto ratecontrol_bailout;
3318 change_settings = 1;
3321 mode = ata_string2mode(optarg);
3323 warnx("unknown mode '%s'", optarg);
3325 goto ratecontrol_bailout;
3327 change_settings = 1;
3330 offset = strtol(optarg, NULL, 0);
3332 warnx("offset value %d is < 0", offset);
3334 goto ratecontrol_bailout;
3336 change_settings = 1;
3342 syncrate = atof(optarg);
3344 warnx("sync rate %f is < 0", syncrate);
3346 goto ratecontrol_bailout;
3348 change_settings = 1;
3351 if (strncasecmp(optarg, "enable", 6) == 0)
3353 else if (strncasecmp(optarg, "disable", 7) == 0)
3356 warnx("-T argument \"%s\" is unknown", optarg);
3358 goto ratecontrol_bailout;
3360 change_settings = 1;
3366 bus_width = strtol(optarg, NULL, 0);
3367 if (bus_width < 0) {
3368 warnx("bus width %d is < 0", bus_width);
3370 goto ratecontrol_bailout;
3372 change_settings = 1;
3378 bzero(&(&ccb->ccb_h)[1],
3379 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3381 * Grab path inquiry information, so we can determine whether
3382 * or not the initiator is capable of the things that the user
3385 ccb->ccb_h.func_code = XPT_PATH_INQ;
3386 if (cam_send_ccb(device, ccb) < 0) {
3387 perror("error sending XPT_PATH_INQ CCB");
3388 if (arglist & CAM_ARG_VERBOSE) {
3389 cam_error_print(device, ccb, CAM_ESF_ALL,
3390 CAM_EPF_ALL, stderr);
3393 goto ratecontrol_bailout;
3395 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3396 warnx("XPT_PATH_INQ CCB failed");
3397 if (arglist & CAM_ARG_VERBOSE) {
3398 cam_error_print(device, ccb, CAM_ESF_ALL,
3399 CAM_EPF_ALL, stderr);
3402 goto ratecontrol_bailout;
3404 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3405 bzero(&(&ccb->ccb_h)[1],
3406 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3408 fprintf(stdout, "%s parameters:\n",
3409 user_settings ? "User" : "Current");
3411 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3413 goto ratecontrol_bailout;
3415 if (arglist & CAM_ARG_VERBOSE)
3418 if (change_settings) {
3419 int didsettings = 0;
3420 struct ccb_trans_settings_spi *spi = NULL;
3421 struct ccb_trans_settings_pata *pata = NULL;
3422 struct ccb_trans_settings_sata *sata = NULL;
3423 struct ccb_trans_settings_ata *ata = NULL;
3424 struct ccb_trans_settings_scsi *scsi = NULL;
3426 if (ccb->cts.transport == XPORT_SPI)
3427 spi = &ccb->cts.xport_specific.spi;
3428 if (ccb->cts.transport == XPORT_ATA)
3429 pata = &ccb->cts.xport_specific.ata;
3430 if (ccb->cts.transport == XPORT_SATA)
3431 sata = &ccb->cts.xport_specific.sata;
3432 if (ccb->cts.protocol == PROTO_ATA)
3433 ata = &ccb->cts.proto_specific.ata;
3434 if (ccb->cts.protocol == PROTO_SCSI)
3435 scsi = &ccb->cts.proto_specific.scsi;
3436 ccb->cts.xport_specific.valid = 0;
3437 ccb->cts.proto_specific.valid = 0;
3438 if (spi && disc_enable != -1) {
3439 spi->valid |= CTS_SPI_VALID_DISC;
3440 if (disc_enable == 0)
3441 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3443 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3446 if (tag_enable != -1) {
3447 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3448 warnx("HBA does not support tagged queueing, "
3449 "so you cannot modify tag settings");
3451 goto ratecontrol_bailout;
3454 ata->valid |= CTS_SCSI_VALID_TQ;
3455 if (tag_enable == 0)
3456 ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
3458 ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
3461 scsi->valid |= CTS_SCSI_VALID_TQ;
3462 if (tag_enable == 0)
3463 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3465 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3469 if (spi && offset != -1) {
3470 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3471 warnx("HBA is not capable of changing offset");
3473 goto ratecontrol_bailout;
3475 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3476 spi->sync_offset = offset;
3479 if (spi && syncrate != -1) {
3480 int prelim_sync_period;
3482 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3483 warnx("HBA is not capable of changing "
3486 goto ratecontrol_bailout;
3488 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3490 * The sync rate the user gives us is in MHz.
3491 * We need to translate it into KHz for this
3496 * Next, we calculate a "preliminary" sync period
3497 * in tenths of a nanosecond.
3500 prelim_sync_period = 0;
3502 prelim_sync_period = 10000000 / syncrate;
3504 scsi_calc_syncparam(prelim_sync_period);
3507 if (sata && syncrate != -1) {
3508 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3509 warnx("HBA is not capable of changing "
3512 goto ratecontrol_bailout;
3514 if (!user_settings) {
3515 warnx("You can modify only user rate "
3516 "settings for SATA");
3518 goto ratecontrol_bailout;
3520 sata->revision = ata_speed2revision(syncrate * 100);
3521 if (sata->revision < 0) {
3522 warnx("Invalid rate %f", syncrate);
3524 goto ratecontrol_bailout;
3526 sata->valid |= CTS_SATA_VALID_REVISION;
3529 if ((pata || sata) && mode != -1) {
3530 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3531 warnx("HBA is not capable of changing "
3534 goto ratecontrol_bailout;
3536 if (!user_settings) {
3537 warnx("You can modify only user mode "
3538 "settings for ATA/SATA");
3540 goto ratecontrol_bailout;
3544 pata->valid |= CTS_ATA_VALID_MODE;
3547 sata->valid |= CTS_SATA_VALID_MODE;
3552 * The bus_width argument goes like this:
3556 * Therefore, if you shift the number of bits given on the
3557 * command line right by 4, you should get the correct
3560 if (spi && bus_width != -1) {
3562 * We might as well validate things here with a
3563 * decipherable error message, rather than what
3564 * will probably be an indecipherable error message
3565 * by the time it gets back to us.
3567 if ((bus_width == 16)
3568 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3569 warnx("HBA does not support 16 bit bus width");
3571 goto ratecontrol_bailout;
3572 } else if ((bus_width == 32)
3573 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3574 warnx("HBA does not support 32 bit bus width");
3576 goto ratecontrol_bailout;
3577 } else if ((bus_width != 8)
3578 && (bus_width != 16)
3579 && (bus_width != 32)) {
3580 warnx("Invalid bus width %d", bus_width);
3582 goto ratecontrol_bailout;
3584 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3585 spi->bus_width = bus_width >> 4;
3588 if (didsettings == 0) {
3589 goto ratecontrol_bailout;
3591 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3592 if (cam_send_ccb(device, ccb) < 0) {
3593 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3594 if (arglist & CAM_ARG_VERBOSE) {
3595 cam_error_print(device, ccb, CAM_ESF_ALL,
3596 CAM_EPF_ALL, stderr);
3599 goto ratecontrol_bailout;
3601 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3602 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3603 if (arglist & CAM_ARG_VERBOSE) {
3604 cam_error_print(device, ccb, CAM_ESF_ALL,
3605 CAM_EPF_ALL, stderr);
3608 goto ratecontrol_bailout;
3612 retval = testunitready(device, retry_count, timeout,
3613 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3615 * If the TUR didn't succeed, just bail.
3619 fprintf(stderr, "Test Unit Ready failed\n");
3620 goto ratecontrol_bailout;
3623 if ((change_settings || send_tur) && !quiet &&
3624 (ccb->cts.transport == XPORT_ATA ||
3625 ccb->cts.transport == XPORT_SATA || send_tur)) {
3626 fprintf(stdout, "New parameters:\n");
3627 retval = get_print_cts(device, user_settings, 0, NULL);
3630 ratecontrol_bailout:
3636 scsiformat(struct cam_device *device, int argc, char **argv,
3637 char *combinedopt, int retry_count, int timeout)
3641 int ycount = 0, quiet = 0;
3642 int error = 0, response = 0, retval = 0;
3643 int use_timeout = 10800 * 1000;
3645 struct format_defect_list_header fh;
3646 u_int8_t *data_ptr = NULL;
3647 u_int32_t dxfer_len = 0;
3649 int num_warnings = 0;
3652 ccb = cam_getccb(device);
3655 warnx("scsiformat: error allocating ccb");
3659 bzero(&(&ccb->ccb_h)[1],
3660 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3662 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3683 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3684 "following device:\n");
3686 error = scsidoinquiry(device, argc, argv, combinedopt,
3687 retry_count, timeout);
3690 warnx("scsiformat: error sending inquiry");
3691 goto scsiformat_bailout;
3700 fprintf(stdout, "Are you SURE you want to do "
3703 if (fgets(str, sizeof(str), stdin) != NULL) {
3705 if (strncasecmp(str, "yes", 3) == 0)
3707 else if (strncasecmp(str, "no", 2) == 0)
3710 fprintf(stdout, "Please answer"
3711 " \"yes\" or \"no\"\n");
3714 } while (response == 0);
3716 if (response == -1) {
3718 goto scsiformat_bailout;
3723 use_timeout = timeout;
3726 fprintf(stdout, "Current format timeout is %d seconds\n",
3727 use_timeout / 1000);
3731 * If the user hasn't disabled questions and didn't specify a
3732 * timeout on the command line, ask them if they want the current
3736 && (timeout == 0)) {
3738 int new_timeout = 0;
3740 fprintf(stdout, "Enter new timeout in seconds or press\n"
3741 "return to keep the current timeout [%d] ",
3742 use_timeout / 1000);
3744 if (fgets(str, sizeof(str), stdin) != NULL) {
3746 new_timeout = atoi(str);
3749 if (new_timeout != 0) {
3750 use_timeout = new_timeout * 1000;
3751 fprintf(stdout, "Using new timeout value %d\n",
3752 use_timeout / 1000);
3757 * Keep this outside the if block below to silence any unused
3758 * variable warnings.
3760 bzero(&fh, sizeof(fh));
3763 * If we're in immediate mode, we've got to include the format
3766 if (immediate != 0) {
3767 fh.byte2 = FU_DLH_IMMED;
3768 data_ptr = (u_int8_t *)&fh;
3769 dxfer_len = sizeof(fh);
3770 byte2 = FU_FMT_DATA;
3771 } else if (quiet == 0) {
3772 fprintf(stdout, "Formatting...");
3776 scsi_format_unit(&ccb->csio,
3777 /* retries */ retry_count,
3779 /* tag_action */ MSG_SIMPLE_Q_TAG,
3782 /* data_ptr */ data_ptr,
3783 /* dxfer_len */ dxfer_len,
3784 /* sense_len */ SSD_FULL_SIZE,
3785 /* timeout */ use_timeout);
3787 /* Disable freezing the device queue */
3788 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3790 if (arglist & CAM_ARG_ERR_RECOVER)
3791 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3793 if (((retval = cam_send_ccb(device, ccb)) < 0)
3794 || ((immediate == 0)
3795 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3796 const char errstr[] = "error sending format command";
3803 if (arglist & CAM_ARG_VERBOSE) {
3804 cam_error_print(device, ccb, CAM_ESF_ALL,
3805 CAM_EPF_ALL, stderr);
3808 goto scsiformat_bailout;
3812 * If we ran in non-immediate mode, we already checked for errors
3813 * above and printed out any necessary information. If we're in
3814 * immediate mode, we need to loop through and get status
3815 * information periodically.
3817 if (immediate == 0) {
3819 fprintf(stdout, "Format Complete\n");
3821 goto scsiformat_bailout;
3828 bzero(&(&ccb->ccb_h)[1],
3829 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3832 * There's really no need to do error recovery or
3833 * retries here, since we're just going to sit in a
3834 * loop and wait for the device to finish formatting.
3836 scsi_test_unit_ready(&ccb->csio,
3839 /* tag_action */ MSG_SIMPLE_Q_TAG,
3840 /* sense_len */ SSD_FULL_SIZE,
3841 /* timeout */ 5000);
3843 /* Disable freezing the device queue */
3844 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3846 retval = cam_send_ccb(device, ccb);
3849 * If we get an error from the ioctl, bail out. SCSI
3850 * errors are expected.
3853 warn("error sending CAMIOCOMMAND ioctl");
3854 if (arglist & CAM_ARG_VERBOSE) {
3855 cam_error_print(device, ccb, CAM_ESF_ALL,
3856 CAM_EPF_ALL, stderr);
3859 goto scsiformat_bailout;
3862 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3864 if ((status != CAM_REQ_CMP)
3865 && (status == CAM_SCSI_STATUS_ERROR)
3866 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3867 struct scsi_sense_data *sense;
3868 int error_code, sense_key, asc, ascq;
3870 sense = &ccb->csio.sense_data;
3871 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3872 ccb->csio.sense_resid, &error_code, &sense_key,
3873 &asc, &ascq, /*show_errors*/ 1);
3876 * According to the SCSI-2 and SCSI-3 specs, a
3877 * drive that is in the middle of a format should
3878 * return NOT READY with an ASC of "logical unit
3879 * not ready, format in progress". The sense key
3880 * specific bytes will then be a progress indicator.
3882 if ((sense_key == SSD_KEY_NOT_READY)
3883 && (asc == 0x04) && (ascq == 0x04)) {
3886 if ((scsi_get_sks(sense, ccb->csio.sense_len -
3887 ccb->csio.sense_resid, sks) == 0)
3890 u_int64_t percentage;
3892 val = scsi_2btoul(&sks[1]);
3893 percentage = 10000 * val;
3896 "\rFormatting: %ju.%02u %% "
3898 (uintmax_t)(percentage /
3900 (unsigned)((percentage /
3904 } else if ((quiet == 0)
3905 && (++num_warnings <= 1)) {
3906 warnx("Unexpected SCSI Sense Key "
3907 "Specific value returned "
3909 scsi_sense_print(device, &ccb->csio,
3911 warnx("Unable to print status "
3912 "information, but format will "
3914 warnx("will exit when format is "
3919 warnx("Unexpected SCSI error during format");
3920 cam_error_print(device, ccb, CAM_ESF_ALL,
3921 CAM_EPF_ALL, stderr);
3923 goto scsiformat_bailout;
3926 } else if (status != CAM_REQ_CMP) {
3927 warnx("Unexpected CAM status %#x", status);
3928 if (arglist & CAM_ARG_VERBOSE)
3929 cam_error_print(device, ccb, CAM_ESF_ALL,
3930 CAM_EPF_ALL, stderr);
3932 goto scsiformat_bailout;
3935 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3938 fprintf(stdout, "\nFormat Complete\n");
3948 scsireportluns(struct cam_device *device, int argc, char **argv,
3949 char *combinedopt, int retry_count, int timeout)
3952 int c, countonly, lunsonly;
3953 struct scsi_report_luns_data *lundata;
3955 uint8_t report_type;
3956 uint32_t list_len, i, j;
3961 report_type = RPL_REPORT_DEFAULT;
3962 ccb = cam_getccb(device);
3965 warnx("%s: error allocating ccb", __func__);
3969 bzero(&(&ccb->ccb_h)[1],
3970 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3975 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3984 if (strcasecmp(optarg, "default") == 0)
3985 report_type = RPL_REPORT_DEFAULT;
3986 else if (strcasecmp(optarg, "wellknown") == 0)
3987 report_type = RPL_REPORT_WELLKNOWN;
3988 else if (strcasecmp(optarg, "all") == 0)
3989 report_type = RPL_REPORT_ALL;
3991 warnx("%s: invalid report type \"%s\"",
4002 if ((countonly != 0)
4003 && (lunsonly != 0)) {
4004 warnx("%s: you can only specify one of -c or -l", __func__);
4009 * According to SPC-4, the allocation length must be at least 16
4010 * bytes -- enough for the header and one LUN.
4012 alloc_len = sizeof(*lundata) + 8;
4016 lundata = malloc(alloc_len);
4018 if (lundata == NULL) {
4019 warn("%s: error mallocing %d bytes", __func__, alloc_len);
4024 scsi_report_luns(&ccb->csio,
4025 /*retries*/ retry_count,
4027 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4028 /*select_report*/ report_type,
4029 /*rpl_buf*/ lundata,
4030 /*alloc_len*/ alloc_len,
4031 /*sense_len*/ SSD_FULL_SIZE,
4032 /*timeout*/ timeout ? timeout : 5000);
4034 /* Disable freezing the device queue */
4035 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4037 if (arglist & CAM_ARG_ERR_RECOVER)
4038 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4040 if (cam_send_ccb(device, ccb) < 0) {
4041 warn("error sending REPORT LUNS command");
4043 if (arglist & CAM_ARG_VERBOSE)
4044 cam_error_print(device, ccb, CAM_ESF_ALL,
4045 CAM_EPF_ALL, stderr);
4051 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4052 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4058 list_len = scsi_4btoul(lundata->length);
4061 * If we need to list the LUNs, and our allocation
4062 * length was too short, reallocate and retry.
4064 if ((countonly == 0)
4065 && (list_len > (alloc_len - sizeof(*lundata)))) {
4066 alloc_len = list_len + sizeof(*lundata);
4072 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
4073 ((list_len / 8) > 1) ? "s" : "");
4078 for (i = 0; i < (list_len / 8); i++) {
4082 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4084 fprintf(stdout, ",");
4085 switch (lundata->luns[i].lundata[j] &
4086 RPL_LUNDATA_ATYP_MASK) {
4087 case RPL_LUNDATA_ATYP_PERIPH:
4088 if ((lundata->luns[i].lundata[j] &
4089 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4090 fprintf(stdout, "%d:",
4091 lundata->luns[i].lundata[j] &
4092 RPL_LUNDATA_PERIPH_BUS_MASK);
4094 && ((lundata->luns[i].lundata[j+2] &
4095 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4098 fprintf(stdout, "%d",
4099 lundata->luns[i].lundata[j+1]);
4101 case RPL_LUNDATA_ATYP_FLAT: {
4103 tmplun[0] = lundata->luns[i].lundata[j] &
4104 RPL_LUNDATA_FLAT_LUN_MASK;
4105 tmplun[1] = lundata->luns[i].lundata[j+1];
4107 fprintf(stdout, "%d", scsi_2btoul(tmplun));
4111 case RPL_LUNDATA_ATYP_LUN:
4112 fprintf(stdout, "%d:%d:%d",
4113 (lundata->luns[i].lundata[j+1] &
4114 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4115 lundata->luns[i].lundata[j] &
4116 RPL_LUNDATA_LUN_TARG_MASK,
4117 lundata->luns[i].lundata[j+1] &
4118 RPL_LUNDATA_LUN_LUN_MASK);
4120 case RPL_LUNDATA_ATYP_EXTLUN: {
4121 int field_len_code, eam_code;
4123 eam_code = lundata->luns[i].lundata[j] &
4124 RPL_LUNDATA_EXT_EAM_MASK;
4125 field_len_code = (lundata->luns[i].lundata[j] &
4126 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4128 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4129 && (field_len_code == 0x00)) {
4130 fprintf(stdout, "%d",
4131 lundata->luns[i].lundata[j+1]);
4132 } else if ((eam_code ==
4133 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4134 && (field_len_code == 0x03)) {
4138 * This format takes up all 8 bytes.
4139 * If we aren't starting at offset 0,
4143 fprintf(stdout, "Invalid "
4146 "specified format", j);
4150 bzero(tmp_lun, sizeof(tmp_lun));
4151 bcopy(&lundata->luns[i].lundata[j+1],
4152 &tmp_lun[1], sizeof(tmp_lun) - 1);
4153 fprintf(stdout, "%#jx",
4154 (intmax_t)scsi_8btou64(tmp_lun));
4157 fprintf(stderr, "Unknown Extended LUN"
4158 "Address method %#x, length "
4159 "code %#x", eam_code,
4166 fprintf(stderr, "Unknown LUN address method "
4167 "%#x\n", lundata->luns[i].lundata[0] &
4168 RPL_LUNDATA_ATYP_MASK);
4172 * For the flat addressing method, there are no
4173 * other levels after it.
4178 fprintf(stdout, "\n");
4191 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4192 char *combinedopt, int retry_count, int timeout)
4195 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4196 struct scsi_read_capacity_data rcap;
4197 struct scsi_read_capacity_data_long rcaplong;
4211 ccb = cam_getccb(device);
4214 warnx("%s: error allocating ccb", __func__);
4218 bzero(&(&ccb->ccb_h)[1],
4219 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4221 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4248 if ((blocksizeonly != 0)
4249 && (numblocks != 0)) {
4250 warnx("%s: you can only specify one of -b or -N", __func__);
4255 if ((blocksizeonly != 0)
4256 && (sizeonly != 0)) {
4257 warnx("%s: you can only specify one of -b or -s", __func__);
4264 warnx("%s: you can only specify one of -h/-H or -q", __func__);
4270 && (blocksizeonly != 0)) {
4271 warnx("%s: you can only specify one of -h/-H or -b", __func__);
4276 scsi_read_capacity(&ccb->csio,
4277 /*retries*/ retry_count,
4279 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4282 /*timeout*/ timeout ? timeout : 5000);
4284 /* Disable freezing the device queue */
4285 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4287 if (arglist & CAM_ARG_ERR_RECOVER)
4288 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4290 if (cam_send_ccb(device, ccb) < 0) {
4291 warn("error sending READ CAPACITY command");
4293 if (arglist & CAM_ARG_VERBOSE)
4294 cam_error_print(device, ccb, CAM_ESF_ALL,
4295 CAM_EPF_ALL, stderr);
4301 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4302 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4307 maxsector = scsi_4btoul(rcap.addr);
4308 block_len = scsi_4btoul(rcap.length);
4311 * A last block of 2^32-1 means that the true capacity is over 2TB,
4312 * and we need to issue the long READ CAPACITY to get the real
4313 * capacity. Otherwise, we're all set.
4315 if (maxsector != 0xffffffff)
4318 scsi_read_capacity_16(&ccb->csio,
4319 /*retries*/ retry_count,
4321 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4326 /*sense_len*/ SSD_FULL_SIZE,
4327 /*timeout*/ timeout ? timeout : 5000);
4329 /* Disable freezing the device queue */
4330 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4332 if (arglist & CAM_ARG_ERR_RECOVER)
4333 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4335 if (cam_send_ccb(device, ccb) < 0) {
4336 warn("error sending READ CAPACITY (16) command");
4338 if (arglist & CAM_ARG_VERBOSE)
4339 cam_error_print(device, ccb, CAM_ESF_ALL,
4340 CAM_EPF_ALL, stderr);
4346 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4347 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4352 maxsector = scsi_8btou64(rcaplong.addr);
4353 block_len = scsi_4btoul(rcaplong.length);
4356 if (blocksizeonly == 0) {
4358 * Humanize implies !quiet, and also implies numblocks.
4360 if (humanize != 0) {
4365 tmpbytes = (maxsector + 1) * block_len;
4366 ret = humanize_number(tmpstr, sizeof(tmpstr),
4367 tmpbytes, "", HN_AUTOSCALE,
4370 HN_DIVISOR_1000 : 0));
4372 warnx("%s: humanize_number failed!", __func__);
4376 fprintf(stdout, "Device Size: %s%s", tmpstr,
4377 (sizeonly == 0) ? ", " : "\n");
4378 } else if (numblocks != 0) {
4379 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4380 "Blocks: " : "", (uintmax_t)maxsector + 1,
4381 (sizeonly == 0) ? ", " : "\n");
4383 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4384 "Last Block: " : "", (uintmax_t)maxsector,
4385 (sizeonly == 0) ? ", " : "\n");
4389 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4390 "Block Length: " : "", block_len, (quiet == 0) ?
4399 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4400 int retry_count, int timeout)
4404 uint8_t *smp_request = NULL, *smp_response = NULL;
4405 int request_size = 0, response_size = 0;
4406 int fd_request = 0, fd_response = 0;
4407 char *datastr = NULL;
4408 struct get_hook hook;
4413 * Note that at the moment we don't support sending SMP CCBs to
4414 * devices that aren't probed by CAM.
4416 ccb = cam_getccb(device);
4418 warnx("%s: error allocating CCB", __func__);
4422 bzero(&(&ccb->ccb_h)[1],
4423 sizeof(union ccb) - sizeof(struct ccb_hdr));
4425 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4428 arglist |= CAM_ARG_CMD_IN;
4429 response_size = strtol(optarg, NULL, 0);
4430 if (response_size <= 0) {
4431 warnx("invalid number of response bytes %d",
4434 goto smpcmd_bailout;
4436 hook.argc = argc - optind;
4437 hook.argv = argv + optind;
4440 datastr = cget(&hook, NULL);
4442 * If the user supplied "-" instead of a format, he
4443 * wants the data to be written to stdout.
4445 if ((datastr != NULL)
4446 && (datastr[0] == '-'))
4449 smp_response = (u_int8_t *)malloc(response_size);
4450 if (smp_response == NULL) {
4451 warn("can't malloc memory for SMP response");
4453 goto smpcmd_bailout;
4457 arglist |= CAM_ARG_CMD_OUT;
4458 request_size = strtol(optarg, NULL, 0);
4459 if (request_size <= 0) {
4460 warnx("invalid number of request bytes %d",
4463 goto smpcmd_bailout;
4465 hook.argc = argc - optind;
4466 hook.argv = argv + optind;
4468 datastr = cget(&hook, NULL);
4469 smp_request = (u_int8_t *)malloc(request_size);
4470 if (smp_request == NULL) {
4471 warn("can't malloc memory for SMP request");
4473 goto smpcmd_bailout;
4475 bzero(smp_request, request_size);
4477 * If the user supplied "-" instead of a format, he
4478 * wants the data to be read from stdin.
4480 if ((datastr != NULL)
4481 && (datastr[0] == '-'))
4484 buff_encode_visit(smp_request, request_size,
4495 * If fd_data is set, and we're writing to the device, we need to
4496 * read the data the user wants written from stdin.
4498 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4500 int amt_to_read = request_size;
4501 u_int8_t *buf_ptr = smp_request;
4503 for (amt_read = 0; amt_to_read > 0;
4504 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4505 if (amt_read == -1) {
4506 warn("error reading data from stdin");
4508 goto smpcmd_bailout;
4510 amt_to_read -= amt_read;
4511 buf_ptr += amt_read;
4515 if (((arglist & CAM_ARG_CMD_IN) == 0)
4516 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
4517 warnx("%s: need both the request (-r) and response (-R) "
4518 "arguments", __func__);
4520 goto smpcmd_bailout;
4523 flags |= CAM_DEV_QFRZDIS;
4525 cam_fill_smpio(&ccb->smpio,
4526 /*retries*/ retry_count,
4529 /*smp_request*/ smp_request,
4530 /*smp_request_len*/ request_size,
4531 /*smp_response*/ smp_response,
4532 /*smp_response_len*/ response_size,
4533 /*timeout*/ timeout ? timeout : 5000);
4535 ccb->smpio.flags = SMP_FLAG_NONE;
4537 if (((retval = cam_send_ccb(device, ccb)) < 0)
4538 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4539 const char warnstr[] = "error sending command";
4546 if (arglist & CAM_ARG_VERBOSE) {
4547 cam_error_print(device, ccb, CAM_ESF_ALL,
4548 CAM_EPF_ALL, stderr);
4552 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4553 && (response_size > 0)) {
4554 if (fd_response == 0) {
4555 buff_decode_visit(smp_response, response_size,
4556 datastr, arg_put, NULL);
4557 fprintf(stdout, "\n");
4559 ssize_t amt_written;
4560 int amt_to_write = response_size;
4561 u_int8_t *buf_ptr = smp_response;
4563 for (amt_written = 0; (amt_to_write > 0) &&
4564 (amt_written = write(STDOUT_FILENO, buf_ptr,
4565 amt_to_write)) > 0;){
4566 amt_to_write -= amt_written;
4567 buf_ptr += amt_written;
4569 if (amt_written == -1) {
4570 warn("error writing data to stdout");
4572 goto smpcmd_bailout;
4573 } else if ((amt_written == 0)
4574 && (amt_to_write > 0)) {
4575 warnx("only wrote %u bytes out of %u",
4576 response_size - amt_to_write,
4585 if (smp_request != NULL)
4588 if (smp_response != NULL)
4595 smpreportgeneral(struct cam_device *device, int argc, char **argv,
4596 char *combinedopt, int retry_count, int timeout)
4599 struct smp_report_general_request *request = NULL;
4600 struct smp_report_general_response *response = NULL;
4601 struct sbuf *sb = NULL;
4603 int c, long_response = 0;
4607 * Note that at the moment we don't support sending SMP CCBs to
4608 * devices that aren't probed by CAM.
4610 ccb = cam_getccb(device);
4612 warnx("%s: error allocating CCB", __func__);
4616 bzero(&(&ccb->ccb_h)[1],
4617 sizeof(union ccb) - sizeof(struct ccb_hdr));
4619 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4628 request = malloc(sizeof(*request));
4629 if (request == NULL) {
4630 warn("%s: unable to allocate %zd bytes", __func__,
4636 response = malloc(sizeof(*response));
4637 if (response == NULL) {
4638 warn("%s: unable to allocate %zd bytes", __func__,
4645 smp_report_general(&ccb->smpio,
4649 /*request_len*/ sizeof(*request),
4650 (uint8_t *)response,
4651 /*response_len*/ sizeof(*response),
4652 /*long_response*/ long_response,
4655 if (((retval = cam_send_ccb(device, ccb)) < 0)
4656 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4657 const char warnstr[] = "error sending command";
4664 if (arglist & CAM_ARG_VERBOSE) {
4665 cam_error_print(device, ccb, CAM_ESF_ALL,
4666 CAM_EPF_ALL, stderr);
4673 * If the device supports the long response bit, try again and see
4674 * if we can get all of the data.
4676 if ((response->long_response & SMP_RG_LONG_RESPONSE)
4677 && (long_response == 0)) {
4678 ccb->ccb_h.status = CAM_REQ_INPROG;
4679 bzero(&(&ccb->ccb_h)[1],
4680 sizeof(union ccb) - sizeof(struct ccb_hdr));
4686 * XXX KDM detect and decode SMP errors here.
4688 sb = sbuf_new_auto();
4690 warnx("%s: error allocating sbuf", __func__);
4694 smp_report_general_sbuf(response, sizeof(*response), sb);
4698 printf("%s", sbuf_data(sb));
4704 if (request != NULL)
4707 if (response != NULL)
4716 struct camcontrol_opts phy_ops[] = {
4717 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
4718 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
4719 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
4720 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
4721 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
4722 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
4723 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
4724 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
4725 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
4730 smpphycontrol(struct cam_device *device, int argc, char **argv,
4731 char *combinedopt, int retry_count, int timeout)
4734 struct smp_phy_control_request *request = NULL;
4735 struct smp_phy_control_response *response = NULL;
4736 int long_response = 0;
4739 uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
4741 uint64_t attached_dev_name = 0;
4742 int dev_name_set = 0;
4743 uint32_t min_plr = 0, max_plr = 0;
4744 uint32_t pp_timeout_val = 0;
4745 int slumber_partial = 0;
4746 int set_pp_timeout_val = 0;
4750 * Note that at the moment we don't support sending SMP CCBs to
4751 * devices that aren't probed by CAM.
4753 ccb = cam_getccb(device);
4755 warnx("%s: error allocating CCB", __func__);
4759 bzero(&(&ccb->ccb_h)[1],
4760 sizeof(union ccb) - sizeof(struct ccb_hdr));
4762 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4770 if (strcasecmp(optarg, "enable") == 0)
4772 else if (strcasecmp(optarg, "disable") == 0)
4775 warnx("%s: Invalid argument %s", __func__,
4782 slumber_partial |= enable <<
4783 SMP_PC_SAS_SLUMBER_SHIFT;
4786 slumber_partial |= enable <<
4787 SMP_PC_SAS_PARTIAL_SHIFT;
4790 slumber_partial |= enable <<
4791 SMP_PC_SATA_SLUMBER_SHIFT;
4794 slumber_partial |= enable <<
4795 SMP_PC_SATA_PARTIAL_SHIFT;
4798 warnx("%s: programmer error", __func__);
4801 break; /*NOTREACHED*/
4806 attached_dev_name = (uintmax_t)strtoumax(optarg,
4815 * We don't do extensive checking here, so this
4816 * will continue to work when new speeds come out.
4818 min_plr = strtoul(optarg, NULL, 0);
4820 || (min_plr > 0xf)) {
4821 warnx("%s: invalid link rate %x",
4829 * We don't do extensive checking here, so this
4830 * will continue to work when new speeds come out.
4832 max_plr = strtoul(optarg, NULL, 0);
4834 || (max_plr > 0xf)) {
4835 warnx("%s: invalid link rate %x",
4842 camcontrol_optret optreturn;
4843 cam_argmask argnums;
4846 if (phy_op_set != 0) {
4847 warnx("%s: only one phy operation argument "
4848 "(-o) allowed", __func__);
4856 * Allow the user to specify the phy operation
4857 * numerically, as well as with a name. This will
4858 * future-proof it a bit, so options that are added
4859 * in future specs can be used.
4861 if (isdigit(optarg[0])) {
4862 phy_operation = strtoul(optarg, NULL, 0);
4863 if ((phy_operation == 0)
4864 || (phy_operation > 0xff)) {
4865 warnx("%s: invalid phy operation %#x",
4866 __func__, phy_operation);
4872 optreturn = getoption(phy_ops, optarg, &phy_operation,
4875 if (optreturn == CC_OR_AMBIGUOUS) {
4876 warnx("%s: ambiguous option %s", __func__,
4881 } else if (optreturn == CC_OR_NOT_FOUND) {
4882 warnx("%s: option %s not found", __func__,
4894 pp_timeout_val = strtoul(optarg, NULL, 0);
4895 if (pp_timeout_val > 15) {
4896 warnx("%s: invalid partial pathway timeout "
4897 "value %u, need a value less than 16",
4898 __func__, pp_timeout_val);
4902 set_pp_timeout_val = 1;
4910 warnx("%s: a PHY (-p phy) argument is required",__func__);
4915 if (((dev_name_set != 0)
4916 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
4917 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
4918 && (dev_name_set == 0))) {
4919 warnx("%s: -d name and -o setdevname arguments both "
4920 "required to set device name", __func__);
4925 request = malloc(sizeof(*request));
4926 if (request == NULL) {
4927 warn("%s: unable to allocate %zd bytes", __func__,
4933 response = malloc(sizeof(*response));
4934 if (response == NULL) {
4935 warn("%s: unable to allocate %zd bytes", __func__,
4941 smp_phy_control(&ccb->smpio,
4946 (uint8_t *)response,
4949 /*expected_exp_change_count*/ 0,
4952 (set_pp_timeout_val != 0) ? 1 : 0,
4960 if (((retval = cam_send_ccb(device, ccb)) < 0)
4961 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4962 const char warnstr[] = "error sending command";
4969 if (arglist & CAM_ARG_VERBOSE) {
4971 * Use CAM_EPF_NORMAL so we only get one line of
4972 * SMP command decoding.
4974 cam_error_print(device, ccb, CAM_ESF_ALL,
4975 CAM_EPF_NORMAL, stderr);
4981 /* XXX KDM print out something here for success? */
4986 if (request != NULL)
4989 if (response != NULL)
4996 smpmaninfo(struct cam_device *device, int argc, char **argv,
4997 char *combinedopt, int retry_count, int timeout)
5000 struct smp_report_manuf_info_request request;
5001 struct smp_report_manuf_info_response response;
5002 struct sbuf *sb = NULL;
5003 int long_response = 0;
5008 * Note that at the moment we don't support sending SMP CCBs to
5009 * devices that aren't probed by CAM.
5011 ccb = cam_getccb(device);
5013 warnx("%s: error allocating CCB", __func__);
5017 bzero(&(&ccb->ccb_h)[1],
5018 sizeof(union ccb) - sizeof(struct ccb_hdr));
5020 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5029 bzero(&request, sizeof(request));
5030 bzero(&response, sizeof(response));
5032 smp_report_manuf_info(&ccb->smpio,
5037 (uint8_t *)&response,
5042 if (((retval = cam_send_ccb(device, ccb)) < 0)
5043 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5044 const char warnstr[] = "error sending command";
5051 if (arglist & CAM_ARG_VERBOSE) {
5052 cam_error_print(device, ccb, CAM_ESF_ALL,
5053 CAM_EPF_ALL, stderr);
5059 sb = sbuf_new_auto();
5061 warnx("%s: error allocating sbuf", __func__);
5065 smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
5069 printf("%s", sbuf_data(sb));
5083 getdevid(struct cam_devitem *item)
5086 union ccb *ccb = NULL;
5088 struct cam_device *dev;
5090 dev = cam_open_btl(item->dev_match.path_id,
5091 item->dev_match.target_id,
5092 item->dev_match.target_lun, O_RDWR, NULL);
5095 warnx("%s", cam_errbuf);
5100 item->device_id_len = 0;
5102 ccb = cam_getccb(dev);
5104 warnx("%s: error allocating CCB", __func__);
5109 bzero(&(&ccb->ccb_h)[1],
5110 sizeof(union ccb) - sizeof(struct ccb_hdr));
5113 * On the first try, we just probe for the size of the data, and
5114 * then allocate that much memory and try again.
5117 ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
5118 ccb->ccb_h.flags = CAM_DIR_IN;
5119 ccb->cdai.flags = 0;
5120 ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
5121 ccb->cdai.bufsiz = item->device_id_len;
5122 if (item->device_id_len != 0)
5123 ccb->cdai.buf = (uint8_t *)item->device_id;
5125 if (cam_send_ccb(dev, ccb) < 0) {
5126 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
5131 if (ccb->ccb_h.status != CAM_REQ_CMP) {
5132 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
5137 if (item->device_id_len == 0) {
5139 * This is our first time through. Allocate the buffer,
5140 * and then go back to get the data.
5142 if (ccb->cdai.provsiz == 0) {
5143 warnx("%s: invalid .provsiz field returned with "
5144 "XPT_GDEV_ADVINFO CCB", __func__);
5148 item->device_id_len = ccb->cdai.provsiz;
5149 item->device_id = malloc(item->device_id_len);
5150 if (item->device_id == NULL) {
5151 warn("%s: unable to allocate %d bytes", __func__,
5152 item->device_id_len);
5156 ccb->ccb_h.status = CAM_REQ_INPROG;
5162 cam_close_device(dev);
5171 * XXX KDM merge this code with getdevtree()?
5174 buildbusdevlist(struct cam_devlist *devlist)
5177 int bufsize, fd = -1;
5178 struct dev_match_pattern *patterns;
5179 struct cam_devitem *item = NULL;
5180 int skip_device = 0;
5183 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
5184 warn("couldn't open %s", XPT_DEVICE);
5188 bzero(&ccb, sizeof(union ccb));
5190 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
5191 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
5192 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
5194 ccb.ccb_h.func_code = XPT_DEV_MATCH;
5195 bufsize = sizeof(struct dev_match_result) * 100;
5196 ccb.cdm.match_buf_len = bufsize;
5197 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
5198 if (ccb.cdm.matches == NULL) {
5199 warnx("can't malloc memory for matches");
5203 ccb.cdm.num_matches = 0;
5204 ccb.cdm.num_patterns = 2;
5205 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
5206 ccb.cdm.num_patterns;
5208 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
5209 if (patterns == NULL) {
5210 warnx("can't malloc memory for patterns");
5215 ccb.cdm.patterns = patterns;
5216 bzero(patterns, ccb.cdm.pattern_buf_len);
5218 patterns[0].type = DEV_MATCH_DEVICE;
5219 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
5220 patterns[0].pattern.device_pattern.path_id = devlist->path_id;
5221 patterns[1].type = DEV_MATCH_PERIPH;
5222 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
5223 patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
5226 * We do the ioctl multiple times if necessary, in case there are
5227 * more than 100 nodes in the EDT.
5232 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
5233 warn("error sending CAMIOCOMMAND ioctl");
5238 if ((ccb.ccb_h.status != CAM_REQ_CMP)
5239 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
5240 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
5241 warnx("got CAM error %#x, CDM error %d\n",
5242 ccb.ccb_h.status, ccb.cdm.status);
5247 for (i = 0; i < ccb.cdm.num_matches; i++) {
5248 switch (ccb.cdm.matches[i].type) {
5249 case DEV_MATCH_DEVICE: {
5250 struct device_match_result *dev_result;
5253 &ccb.cdm.matches[i].result.device_result;
5255 if (dev_result->flags &
5256 DEV_RESULT_UNCONFIGURED) {
5262 item = malloc(sizeof(*item));
5264 warn("%s: unable to allocate %zd bytes",
5265 __func__, sizeof(*item));
5269 bzero(item, sizeof(*item));
5270 bcopy(dev_result, &item->dev_match,
5271 sizeof(*dev_result));
5272 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
5275 if (getdevid(item) != 0) {
5281 case DEV_MATCH_PERIPH: {
5282 struct periph_match_result *periph_result;
5285 &ccb.cdm.matches[i].result.periph_result;
5287 if (skip_device != 0)
5289 item->num_periphs++;
5290 item->periph_matches = realloc(
5291 item->periph_matches,
5293 sizeof(struct periph_match_result));
5294 if (item->periph_matches == NULL) {
5295 warn("%s: error allocating periph "
5300 bcopy(periph_result, &item->periph_matches[
5301 item->num_periphs - 1],
5302 sizeof(*periph_result));
5306 fprintf(stderr, "%s: unexpected match "
5307 "type %d\n", __func__,
5308 ccb.cdm.matches[i].type);
5311 break; /*NOTREACHED*/
5314 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
5315 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
5323 free(ccb.cdm.matches);
5326 freebusdevlist(devlist);
5332 freebusdevlist(struct cam_devlist *devlist)
5334 struct cam_devitem *item, *item2;
5336 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
5337 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
5339 free(item->device_id);
5340 free(item->periph_matches);
5345 static struct cam_devitem *
5346 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
5348 struct cam_devitem *item;
5350 STAILQ_FOREACH(item, &devlist->dev_queue, links) {
5354 * XXX KDM look for LUN IDs as well?
5356 item_addr = scsi_get_devid(item->device_id,
5357 item->device_id_len,
5358 scsi_devid_is_sas_target);
5359 if (item_addr == NULL)
5362 if (scsi_8btou64(item_addr) == sasaddr)
5370 smpphylist(struct cam_device *device, int argc, char **argv,
5371 char *combinedopt, int retry_count, int timeout)
5373 struct smp_report_general_request *rgrequest = NULL;
5374 struct smp_report_general_response *rgresponse = NULL;
5375 struct smp_discover_request *disrequest = NULL;
5376 struct smp_discover_response *disresponse = NULL;
5377 struct cam_devlist devlist;
5379 int long_response = 0;
5386 * Note that at the moment we don't support sending SMP CCBs to
5387 * devices that aren't probed by CAM.
5389 ccb = cam_getccb(device);
5391 warnx("%s: error allocating CCB", __func__);
5395 bzero(&(&ccb->ccb_h)[1],
5396 sizeof(union ccb) - sizeof(struct ccb_hdr));
5398 rgrequest = malloc(sizeof(*rgrequest));
5399 if (rgrequest == NULL) {
5400 warn("%s: unable to allocate %zd bytes", __func__,
5401 sizeof(*rgrequest));
5406 rgresponse = malloc(sizeof(*rgresponse));
5407 if (rgresponse == NULL) {
5408 warn("%s: unable to allocate %zd bytes", __func__,
5409 sizeof(*rgresponse));
5414 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5427 smp_report_general(&ccb->smpio,
5431 /*request_len*/ sizeof(*rgrequest),
5432 (uint8_t *)rgresponse,
5433 /*response_len*/ sizeof(*rgresponse),
5434 /*long_response*/ long_response,
5437 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5439 if (((retval = cam_send_ccb(device, ccb)) < 0)
5440 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5441 const char warnstr[] = "error sending command";
5448 if (arglist & CAM_ARG_VERBOSE) {
5449 cam_error_print(device, ccb, CAM_ESF_ALL,
5450 CAM_EPF_ALL, stderr);
5456 num_phys = rgresponse->num_phys;
5458 if (num_phys == 0) {
5460 fprintf(stdout, "%s: No Phys reported\n", __func__);
5465 STAILQ_INIT(&devlist.dev_queue);
5466 devlist.path_id = device->path_id;
5468 retval = buildbusdevlist(&devlist);
5473 fprintf(stdout, "%d PHYs:\n", num_phys);
5474 fprintf(stdout, "PHY Attached SAS Address\n");
5477 disrequest = malloc(sizeof(*disrequest));
5478 if (disrequest == NULL) {
5479 warn("%s: unable to allocate %zd bytes", __func__,
5480 sizeof(*disrequest));
5485 disresponse = malloc(sizeof(*disresponse));
5486 if (disresponse == NULL) {
5487 warn("%s: unable to allocate %zd bytes", __func__,
5488 sizeof(*disresponse));
5493 for (i = 0; i < num_phys; i++) {
5494 struct cam_devitem *item;
5495 struct device_match_result *dev_match;
5496 char vendor[16], product[48], revision[16];
5500 bzero(&(&ccb->ccb_h)[1],
5501 sizeof(union ccb) - sizeof(struct ccb_hdr));
5503 ccb->ccb_h.status = CAM_REQ_INPROG;
5504 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5506 smp_discover(&ccb->smpio,
5510 sizeof(*disrequest),
5511 (uint8_t *)disresponse,
5512 sizeof(*disresponse),
5514 /*ignore_zone_group*/ 0,
5518 if (((retval = cam_send_ccb(device, ccb)) < 0)
5519 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
5520 && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
5521 const char warnstr[] = "error sending command";
5528 if (arglist & CAM_ARG_VERBOSE) {
5529 cam_error_print(device, ccb, CAM_ESF_ALL,
5530 CAM_EPF_ALL, stderr);
5536 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
5538 fprintf(stdout, "%3d <vacant>\n", i);
5542 item = findsasdevice(&devlist,
5543 scsi_8btou64(disresponse->attached_sas_address));
5546 || (item != NULL)) {
5547 fprintf(stdout, "%3d 0x%016jx", i,
5548 (uintmax_t)scsi_8btou64(
5549 disresponse->attached_sas_address));
5551 fprintf(stdout, "\n");
5554 } else if (quiet != 0)
5557 dev_match = &item->dev_match;
5559 if (dev_match->protocol == PROTO_SCSI) {
5560 cam_strvis(vendor, dev_match->inq_data.vendor,
5561 sizeof(dev_match->inq_data.vendor),
5563 cam_strvis(product, dev_match->inq_data.product,
5564 sizeof(dev_match->inq_data.product),
5566 cam_strvis(revision, dev_match->inq_data.revision,
5567 sizeof(dev_match->inq_data.revision),
5569 sprintf(tmpstr, "<%s %s %s>", vendor, product,
5571 } else if ((dev_match->protocol == PROTO_ATA)
5572 || (dev_match->protocol == PROTO_SATAPM)) {
5573 cam_strvis(product, dev_match->ident_data.model,
5574 sizeof(dev_match->ident_data.model),
5576 cam_strvis(revision, dev_match->ident_data.revision,
5577 sizeof(dev_match->ident_data.revision),
5579 sprintf(tmpstr, "<%s %s>", product, revision);
5581 sprintf(tmpstr, "<>");
5583 fprintf(stdout, " %-33s ", tmpstr);
5586 * If we have 0 periphs, that's a bug...
5588 if (item->num_periphs == 0) {
5589 fprintf(stdout, "\n");
5593 fprintf(stdout, "(");
5594 for (j = 0; j < item->num_periphs; j++) {
5596 fprintf(stdout, ",");
5598 fprintf(stdout, "%s%d",
5599 item->periph_matches[j].periph_name,
5600 item->periph_matches[j].unit_number);
5603 fprintf(stdout, ")\n");
5617 freebusdevlist(&devlist);
5623 atapm(struct cam_device *device, int argc, char **argv,
5624 char *combinedopt, int retry_count, int timeout)
5632 ccb = cam_getccb(device);
5635 warnx("%s: error allocating ccb", __func__);
5639 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5648 if (strcmp(argv[1], "idle") == 0) {
5650 cmd = ATA_IDLE_IMMEDIATE;
5653 } else if (strcmp(argv[1], "standby") == 0) {
5655 cmd = ATA_STANDBY_IMMEDIATE;
5657 cmd = ATA_STANDBY_CMD;
5665 else if (t <= (240 * 5))
5667 else if (t <= (252 * 5))
5668 /* special encoding for 21 minutes */
5670 else if (t <= (11 * 30 * 60))
5671 sc = (t - 1) / (30 * 60) + 241;
5675 cam_fill_ataio(&ccb->ataio,
5678 /*flags*/CAM_DIR_NONE,
5682 timeout ? timeout : 30 * 1000);
5683 ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
5685 /* Disable freezing the device queue */
5686 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5688 if (arglist & CAM_ARG_ERR_RECOVER)
5689 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5691 if (cam_send_ccb(device, ccb) < 0) {
5692 warn("error sending command");
5694 if (arglist & CAM_ARG_VERBOSE)
5695 cam_error_print(device, ccb, CAM_ESF_ALL,
5696 CAM_EPF_ALL, stderr);
5702 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5703 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5712 #endif /* MINIMALISTIC */
5717 fprintf(verbose ? stdout : stderr,
5718 "usage: camcontrol <command> [device id][generic args][command args]\n"
5719 " camcontrol devlist [-v]\n"
5720 #ifndef MINIMALISTIC
5721 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
5722 " camcontrol tur [dev_id][generic args]\n"
5723 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
5724 " camcontrol identify [dev_id][generic args] [-v]\n"
5725 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
5726 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
5728 " camcontrol start [dev_id][generic args]\n"
5729 " camcontrol stop [dev_id][generic args]\n"
5730 " camcontrol load [dev_id][generic args]\n"
5731 " camcontrol eject [dev_id][generic args]\n"
5732 #endif /* MINIMALISTIC */
5733 " camcontrol rescan <all | bus[:target:lun]>\n"
5734 " camcontrol reset <all | bus[:target:lun]>\n"
5735 #ifndef MINIMALISTIC
5736 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
5737 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
5738 " [-P pagectl][-e | -b][-d]\n"
5739 " camcontrol cmd [dev_id][generic args]\n"
5740 " <-a cmd [args] | -c cmd [args]>\n"
5741 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
5742 " camcontrol smpcmd [dev_id][generic args]\n"
5743 " <-r len fmt [args]> <-R len fmt [args]>\n"
5744 " camcontrol smprg [dev_id][generic args][-l]\n"
5745 " camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n"
5746 " [-o operation][-d name][-m rate][-M rate]\n"
5747 " [-T pp_timeout][-a enable|disable]\n"
5748 " [-A enable|disable][-s enable|disable]\n"
5749 " [-S enable|disable]\n"
5750 " camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
5751 " camcontrol smpmaninfo [dev_id][generic args][-l]\n"
5752 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
5753 " <all|bus[:target[:lun]]|off>\n"
5754 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
5755 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
5756 " [-D <enable|disable>][-M mode][-O offset]\n"
5757 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
5758 " [-U][-W bus_width]\n"
5759 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
5760 " camcontrol idle [dev_id][generic args][-t time]\n"
5761 " camcontrol standby [dev_id][generic args][-t time]\n"
5762 " camcontrol sleep [dev_id][generic args]\n"
5763 #endif /* MINIMALISTIC */
5764 " camcontrol help\n");
5767 #ifndef MINIMALISTIC
5769 "Specify one of the following options:\n"
5770 "devlist list all CAM devices\n"
5771 "periphlist list all CAM peripheral drivers attached to a device\n"
5772 "tur send a test unit ready to the named device\n"
5773 "inquiry send a SCSI inquiry command to the named device\n"
5774 "identify send a ATA identify command to the named device\n"
5775 "reportluns send a SCSI report luns command to the device\n"
5776 "readcap send a SCSI read capacity command to the device\n"
5777 "start send a Start Unit command to the device\n"
5778 "stop send a Stop Unit command to the device\n"
5779 "load send a Start Unit command to the device with the load bit set\n"
5780 "eject send a Stop Unit command to the device with the eject bit set\n"
5781 "rescan rescan all busses, the given bus, or bus:target:lun\n"
5782 "reset reset all busses, the given bus, or bus:target:lun\n"
5783 "defects read the defect list of the specified device\n"
5784 "modepage display or edit (-e) the given mode page\n"
5785 "cmd send the given SCSI command, may need -i or -o as well\n"
5786 "smpcmd send the given SMP command, requires -o and -i\n"
5787 "smprg send the SMP Report General command\n"
5788 "smppc send the SMP PHY Control command, requires -p\n"
5789 "smpphylist display phys attached to a SAS expander\n"
5790 "smpmaninfo send the SMP Report Manufacturer Info command\n"
5791 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
5792 "tags report or set the number of transaction slots for a device\n"
5793 "negotiate report or set device negotiation parameters\n"
5794 "format send the SCSI FORMAT UNIT command to the named device\n"
5795 "idle send the ATA IDLE command to the named device\n"
5796 "standby send the ATA STANDBY command to the named device\n"
5797 "sleep send the ATA SLEEP command to the named device\n"
5798 "help this message\n"
5799 "Device Identifiers:\n"
5800 "bus:target specify the bus and target, lun defaults to 0\n"
5801 "bus:target:lun specify the bus, target and lun\n"
5802 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
5803 "Generic arguments:\n"
5804 "-v be verbose, print out sense information\n"
5805 "-t timeout command timeout in seconds, overrides default timeout\n"
5806 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
5807 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
5808 "-E have the kernel attempt to perform SCSI error recovery\n"
5809 "-C count specify the SCSI command retry count (needs -E to work)\n"
5810 "modepage arguments:\n"
5811 "-l list all available mode pages\n"
5812 "-m page specify the mode page to view or edit\n"
5813 "-e edit the specified mode page\n"
5814 "-b force view to binary mode\n"
5815 "-d disable block descriptors for mode sense\n"
5816 "-P pgctl page control field 0-3\n"
5817 "defects arguments:\n"
5818 "-f format specify defect list format (block, bfi or phys)\n"
5819 "-G get the grown defect list\n"
5820 "-P get the permanant defect list\n"
5821 "inquiry arguments:\n"
5822 "-D get the standard inquiry data\n"
5823 "-S get the serial number\n"
5824 "-R get the transfer rate, etc.\n"
5825 "reportluns arguments:\n"
5826 "-c only report a count of available LUNs\n"
5827 "-l only print out luns, and not a count\n"
5828 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
5829 "readcap arguments\n"
5830 "-b only report the blocksize\n"
5831 "-h human readable device size, base 2\n"
5832 "-H human readable device size, base 10\n"
5833 "-N print the number of blocks instead of last block\n"
5834 "-q quiet, print numbers only\n"
5835 "-s only report the last block/device size\n"
5837 "-c cdb [args] specify the SCSI CDB\n"
5838 "-i len fmt specify input data and input data format\n"
5839 "-o len fmt [args] specify output data and output data fmt\n"
5840 "smpcmd arguments:\n"
5841 "-r len fmt [args] specify the SMP command to be sent\n"
5842 "-R len fmt [args] specify SMP response format\n"
5843 "smprg arguments:\n"
5844 "-l specify the long response format\n"
5845 "smppc arguments:\n"
5846 "-p phy specify the PHY to operate on\n"
5847 "-l specify the long request/response format\n"
5848 "-o operation specify the phy control operation\n"
5849 "-d name set the attached device name\n"
5850 "-m rate set the minimum physical link rate\n"
5851 "-M rate set the maximum physical link rate\n"
5852 "-T pp_timeout set the partial pathway timeout value\n"
5853 "-a enable|disable enable or disable SATA slumber\n"
5854 "-A enable|disable enable or disable SATA partial phy power\n"
5855 "-s enable|disable enable or disable SAS slumber\n"
5856 "-S enable|disable enable or disable SAS partial phy power\n"
5857 "smpphylist arguments:\n"
5858 "-l specify the long response format\n"
5859 "-q only print phys with attached devices\n"
5860 "smpmaninfo arguments:\n"
5861 "-l specify the long response format\n"
5862 "debug arguments:\n"
5863 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
5864 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
5865 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
5866 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
5868 "-N tags specify the number of tags to use for this device\n"
5869 "-q be quiet, don't report the number of tags\n"
5870 "-v report a number of tag-related parameters\n"
5871 "negotiate arguments:\n"
5872 "-a send a test unit ready after negotiation\n"
5873 "-c report/set current negotiation settings\n"
5874 "-D <arg> \"enable\" or \"disable\" disconnection\n"
5875 "-M mode set ATA mode\n"
5876 "-O offset set command delay offset\n"
5877 "-q be quiet, don't report anything\n"
5878 "-R syncrate synchronization rate in MHz\n"
5879 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
5880 "-U report/set user negotiation settings\n"
5881 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
5882 "-v also print a Path Inquiry CCB for the controller\n"
5883 "format arguments:\n"
5884 "-q be quiet, don't print status messages\n"
5885 "-r run in report only mode\n"
5886 "-w don't send immediate format command\n"
5887 "-y don't ask any questions\n"
5888 "idle/standby arguments:\n"
5889 "-t <arg> number of seconds before respective state.\n");
5890 #endif /* MINIMALISTIC */
5894 main(int argc, char **argv)
5897 char *device = NULL;
5899 struct cam_device *cam_dev = NULL;
5900 int timeout = 0, retry_count = 1;
5901 camcontrol_optret optreturn;
5903 const char *mainopt = "C:En:t:u:v";
5904 const char *subopt = NULL;
5905 char combinedopt[256];
5906 int error = 0, optstart = 2;
5908 #ifndef MINIMALISTIC
5909 int bus, target, lun;
5910 #endif /* MINIMALISTIC */
5912 cmdlist = CAM_CMD_NONE;
5913 arglist = CAM_ARG_NONE;
5921 * Get the base option.
5923 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
5925 if (optreturn == CC_OR_AMBIGUOUS) {
5926 warnx("ambiguous option %s", argv[1]);
5929 } else if (optreturn == CC_OR_NOT_FOUND) {
5930 warnx("option %s not found", argv[1]);
5936 * Ahh, getopt(3) is a pain.
5938 * This is a gross hack. There really aren't many other good
5939 * options (excuse the pun) for parsing options in a situation like
5940 * this. getopt is kinda braindead, so you end up having to run
5941 * through the options twice, and give each invocation of getopt
5942 * the option string for the other invocation.
5944 * You would think that you could just have two groups of options.
5945 * The first group would get parsed by the first invocation of
5946 * getopt, and the second group would get parsed by the second
5947 * invocation of getopt. It doesn't quite work out that way. When
5948 * the first invocation of getopt finishes, it leaves optind pointing
5949 * to the argument _after_ the first argument in the second group.
5950 * So when the second invocation of getopt comes around, it doesn't
5951 * recognize the first argument it gets and then bails out.
5953 * A nice alternative would be to have a flag for getopt that says
5954 * "just keep parsing arguments even when you encounter an unknown
5955 * argument", but there isn't one. So there's no real clean way to
5956 * easily parse two sets of arguments without having one invocation
5957 * of getopt know about the other.
5959 * Without this hack, the first invocation of getopt would work as
5960 * long as the generic arguments are first, but the second invocation
5961 * (in the subfunction) would fail in one of two ways. In the case
5962 * where you don't set optreset, it would fail because optind may be
5963 * pointing to the argument after the one it should be pointing at.
5964 * In the case where you do set optreset, and reset optind, it would
5965 * fail because getopt would run into the first set of options, which
5966 * it doesn't understand.
5968 * All of this would "sort of" work if you could somehow figure out
5969 * whether optind had been incremented one option too far. The
5970 * mechanics of that, however, are more daunting than just giving
5971 * both invocations all of the expect options for either invocation.
5973 * Needless to say, I wouldn't mind if someone invented a better
5974 * (non-GPL!) command line parsing interface than getopt. I
5975 * wouldn't mind if someone added more knobs to getopt to make it
5976 * work better. Who knows, I may talk myself into doing it someday,
5977 * if the standards weenies let me. As it is, it just leads to
5978 * hackery like this and causes people to avoid it in some cases.
5980 * KDM, September 8th, 1998
5983 sprintf(combinedopt, "%s%s", mainopt, subopt);
5985 sprintf(combinedopt, "%s", mainopt);
5988 * For these options we do not parse optional device arguments and
5989 * we do not open a passthrough device.
5991 if ((cmdlist == CAM_CMD_RESCAN)
5992 || (cmdlist == CAM_CMD_RESET)
5993 || (cmdlist == CAM_CMD_DEVTREE)
5994 || (cmdlist == CAM_CMD_USAGE)
5995 || (cmdlist == CAM_CMD_DEBUG))
5998 #ifndef MINIMALISTIC
6000 && (argc > 2 && argv[2][0] != '-')) {
6004 if (isdigit(argv[2][0])) {
6005 /* device specified as bus:target[:lun] */
6006 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
6008 errx(1, "numeric device specification must "
6009 "be either bus:target, or "
6011 /* default to 0 if lun was not specified */
6012 if ((arglist & CAM_ARG_LUN) == 0) {
6014 arglist |= CAM_ARG_LUN;
6018 if (cam_get_device(argv[2], name, sizeof name, &unit)
6020 errx(1, "%s", cam_errbuf);
6021 device = strdup(name);
6022 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
6026 #endif /* MINIMALISTIC */
6028 * Start getopt processing at argv[2/3], since we've already
6029 * accepted argv[1..2] as the command name, and as a possible
6035 * Now we run through the argument list looking for generic
6036 * options, and ignoring options that possibly belong to
6039 while ((c = getopt(argc, argv, combinedopt))!= -1){
6042 retry_count = strtol(optarg, NULL, 0);
6043 if (retry_count < 0)
6044 errx(1, "retry count %d is < 0",
6046 arglist |= CAM_ARG_RETRIES;
6049 arglist |= CAM_ARG_ERR_RECOVER;
6052 arglist |= CAM_ARG_DEVICE;
6054 while (isspace(*tstr) && (*tstr != '\0'))
6056 device = (char *)strdup(tstr);
6059 timeout = strtol(optarg, NULL, 0);
6061 errx(1, "invalid timeout %d", timeout);
6062 /* Convert the timeout from seconds to ms */
6064 arglist |= CAM_ARG_TIMEOUT;
6067 arglist |= CAM_ARG_UNIT;
6068 unit = strtol(optarg, NULL, 0);
6071 arglist |= CAM_ARG_VERBOSE;
6078 #ifndef MINIMALISTIC
6080 * For most commands we'll want to open the passthrough device
6081 * associated with the specified device. In the case of the rescan
6082 * commands, we don't use a passthrough device at all, just the
6083 * transport layer device.
6086 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
6087 && (((arglist & CAM_ARG_DEVICE) == 0)
6088 || ((arglist & CAM_ARG_UNIT) == 0))) {
6089 errx(1, "subcommand \"%s\" requires a valid device "
6090 "identifier", argv[1]);
6093 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
6094 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
6095 cam_open_spec_device(device,unit,O_RDWR,NULL)))
6097 errx(1,"%s", cam_errbuf);
6099 #endif /* MINIMALISTIC */
6102 * Reset optind to 2, and reset getopt, so these routines can parse
6103 * the arguments again.
6109 #ifndef MINIMALISTIC
6110 case CAM_CMD_DEVLIST:
6111 error = getdevlist(cam_dev);
6113 #endif /* MINIMALISTIC */
6114 case CAM_CMD_DEVTREE:
6115 error = getdevtree();
6117 #ifndef MINIMALISTIC
6119 error = testunitready(cam_dev, retry_count, timeout, 0);
6121 case CAM_CMD_INQUIRY:
6122 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
6123 retry_count, timeout);
6125 case CAM_CMD_IDENTIFY:
6126 error = ataidentify(cam_dev, retry_count, timeout);
6128 case CAM_CMD_STARTSTOP:
6129 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
6130 arglist & CAM_ARG_EJECT, retry_count,
6133 #endif /* MINIMALISTIC */
6134 case CAM_CMD_RESCAN:
6135 error = dorescan_or_reset(argc, argv, 1);
6138 error = dorescan_or_reset(argc, argv, 0);
6140 #ifndef MINIMALISTIC
6141 case CAM_CMD_READ_DEFECTS:
6142 error = readdefects(cam_dev, argc, argv, combinedopt,
6143 retry_count, timeout);
6145 case CAM_CMD_MODE_PAGE:
6146 modepage(cam_dev, argc, argv, combinedopt,
6147 retry_count, timeout);
6149 case CAM_CMD_SCSI_CMD:
6150 error = scsicmd(cam_dev, argc, argv, combinedopt,
6151 retry_count, timeout);
6153 case CAM_CMD_SMP_CMD:
6154 error = smpcmd(cam_dev, argc, argv, combinedopt,
6155 retry_count, timeout);
6157 case CAM_CMD_SMP_RG:
6158 error = smpreportgeneral(cam_dev, argc, argv,
6159 combinedopt, retry_count,
6162 case CAM_CMD_SMP_PC:
6163 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
6164 retry_count, timeout);
6166 case CAM_CMD_SMP_PHYLIST:
6167 error = smpphylist(cam_dev, argc, argv, combinedopt,
6168 retry_count, timeout);
6170 case CAM_CMD_SMP_MANINFO:
6171 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
6172 retry_count, timeout);
6175 error = camdebug(argc, argv, combinedopt);
6178 error = tagcontrol(cam_dev, argc, argv, combinedopt);
6181 error = ratecontrol(cam_dev, retry_count, timeout,
6182 argc, argv, combinedopt);
6184 case CAM_CMD_FORMAT:
6185 error = scsiformat(cam_dev, argc, argv,
6186 combinedopt, retry_count, timeout);
6188 case CAM_CMD_REPORTLUNS:
6189 error = scsireportluns(cam_dev, argc, argv,
6190 combinedopt, retry_count,
6193 case CAM_CMD_READCAP:
6194 error = scsireadcapacity(cam_dev, argc, argv,
6195 combinedopt, retry_count,
6199 case CAM_CMD_STANDBY:
6201 error = atapm(cam_dev, argc, argv,
6202 combinedopt, retry_count,
6205 #endif /* MINIMALISTIC */
6215 if (cam_dev != NULL)
6216 cam_close_device(cam_dev);