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,
125 CAM_ARG_DEBUG_PROBE = 0x40000000,
128 struct camcontrol_opts {
136 static const char scsicmd_opts[] = "a:c:dfi:o:r";
137 static const char readdefect_opts[] = "f:GP";
138 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
139 static const char smprg_opts[] = "l";
140 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
141 static const char smpphylist_opts[] = "lq";
144 struct camcontrol_opts option_table[] = {
146 {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
147 {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
148 {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
149 {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
150 {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
151 {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
152 {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
153 {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
154 {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
155 #endif /* MINIMALISTIC */
156 {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
157 {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
159 {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
160 {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
161 {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
162 {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
163 {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
164 {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
165 {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
166 {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
167 {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
168 {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
169 {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
170 {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
171 #endif /* MINIMALISTIC */
172 {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
174 {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
175 {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
176 {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
177 {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
178 {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
179 {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
180 {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
181 {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
182 {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
183 {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
184 #endif /* MINIMALISTIC */
185 {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
186 {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
187 {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
198 struct device_match_result dev_match;
200 struct periph_match_result *periph_matches;
201 struct scsi_vpd_device_id *device_id;
203 STAILQ_ENTRY(cam_devitem) links;
207 STAILQ_HEAD(, cam_devitem) dev_queue;
214 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
215 uint32_t *cmdnum, cam_argmask *argnum,
216 const char **subopt);
218 static int getdevlist(struct cam_device *device);
219 #endif /* MINIMALISTIC */
220 static int getdevtree(void);
222 static int testunitready(struct cam_device *device, int retry_count,
223 int timeout, int quiet);
224 static int scsistart(struct cam_device *device, int startstop, int loadeject,
225 int retry_count, int timeout);
226 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
227 char *combinedopt, int retry_count, int timeout);
228 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
229 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
230 static int camxferrate(struct cam_device *device);
231 #endif /* MINIMALISTIC */
232 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
233 cam_argmask *arglst);
234 static int dorescan_or_reset(int argc, char **argv, int rescan);
235 static int rescan_or_reset_bus(int bus, int rescan);
236 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
238 static int readdefects(struct cam_device *device, int argc, char **argv,
239 char *combinedopt, int retry_count, int timeout);
240 static void modepage(struct cam_device *device, int argc, char **argv,
241 char *combinedopt, int retry_count, int timeout);
242 static int scsicmd(struct cam_device *device, int argc, char **argv,
243 char *combinedopt, int retry_count, int timeout);
244 static int smpcmd(struct cam_device *device, int argc, char **argv,
245 char *combinedopt, int retry_count, int timeout);
246 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
247 char *combinedopt, int retry_count, int timeout);
248 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
249 char *combinedopt, int retry_count, int timeout);
250 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
251 char *combinedopt, int retry_count, int timeout);
252 static int getdevid(struct cam_devitem *item);
253 static int buildbusdevlist(struct cam_devlist *devlist);
254 static void freebusdevlist(struct cam_devlist *devlist);
255 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
257 static int smpphylist(struct cam_device *device, int argc, char **argv,
258 char *combinedopt, int retry_count, int timeout);
259 static int tagcontrol(struct cam_device *device, int argc, char **argv,
261 static void cts_print(struct cam_device *device,
262 struct ccb_trans_settings *cts);
263 static void cpi_print(struct ccb_pathinq *cpi);
264 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
265 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
266 static int get_print_cts(struct cam_device *device, int user_settings,
267 int quiet, struct ccb_trans_settings *cts);
268 static int ratecontrol(struct cam_device *device, int retry_count,
269 int timeout, int argc, char **argv, char *combinedopt);
270 static int scsiformat(struct cam_device *device, int argc, char **argv,
271 char *combinedopt, int retry_count, int timeout);
272 static int scsireportluns(struct cam_device *device, int argc, char **argv,
273 char *combinedopt, int retry_count, int timeout);
274 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
275 char *combinedopt, int retry_count, int timeout);
276 static int atapm(struct cam_device *device, int argc, char **argv,
277 char *combinedopt, int retry_count, int timeout);
278 #endif /* MINIMALISTIC */
280 #define min(a,b) (((a)<(b))?(a):(b))
283 #define max(a,b) (((a)>(b))?(a):(b))
287 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
288 cam_argmask *argnum, const char **subopt)
290 struct camcontrol_opts *opts;
293 for (opts = table; (opts != NULL) && (opts->optname != NULL);
295 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
296 *cmdnum = opts->cmdnum;
297 *argnum = opts->argnum;
298 *subopt = opts->subopt;
299 if (++num_matches > 1)
300 return(CC_OR_AMBIGUOUS);
307 return(CC_OR_NOT_FOUND);
312 getdevlist(struct cam_device *device)
318 ccb = cam_getccb(device);
320 ccb->ccb_h.func_code = XPT_GDEVLIST;
321 ccb->ccb_h.flags = CAM_DIR_NONE;
322 ccb->ccb_h.retry_count = 1;
324 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
325 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
326 if (cam_send_ccb(device, ccb) < 0) {
327 perror("error getting device list");
334 switch (ccb->cgdl.status) {
335 case CAM_GDEVLIST_MORE_DEVS:
336 strcpy(status, "MORE");
338 case CAM_GDEVLIST_LAST_DEVICE:
339 strcpy(status, "LAST");
341 case CAM_GDEVLIST_LIST_CHANGED:
342 strcpy(status, "CHANGED");
344 case CAM_GDEVLIST_ERROR:
345 strcpy(status, "ERROR");
350 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
351 ccb->cgdl.periph_name,
352 ccb->cgdl.unit_number,
353 ccb->cgdl.generation,
358 * If the list has changed, we need to start over from the
361 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
369 #endif /* MINIMALISTIC */
381 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
382 warn("couldn't open %s", XPT_DEVICE);
386 bzero(&ccb, sizeof(union ccb));
388 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
389 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
390 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
392 ccb.ccb_h.func_code = XPT_DEV_MATCH;
393 bufsize = sizeof(struct dev_match_result) * 100;
394 ccb.cdm.match_buf_len = bufsize;
395 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
396 if (ccb.cdm.matches == NULL) {
397 warnx("can't malloc memory for matches");
401 ccb.cdm.num_matches = 0;
404 * We fetch all nodes, since we display most of them in the default
405 * case, and all in the verbose case.
407 ccb.cdm.num_patterns = 0;
408 ccb.cdm.pattern_buf_len = 0;
411 * We do the ioctl multiple times if necessary, in case there are
412 * more than 100 nodes in the EDT.
415 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
416 warn("error sending CAMIOCOMMAND ioctl");
421 if ((ccb.ccb_h.status != CAM_REQ_CMP)
422 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
423 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
424 warnx("got CAM error %#x, CDM error %d\n",
425 ccb.ccb_h.status, ccb.cdm.status);
430 for (i = 0; i < ccb.cdm.num_matches; i++) {
431 switch (ccb.cdm.matches[i].type) {
432 case DEV_MATCH_BUS: {
433 struct bus_match_result *bus_result;
436 * Only print the bus information if the
437 * user turns on the verbose flag.
439 if ((arglist & CAM_ARG_VERBOSE) == 0)
443 &ccb.cdm.matches[i].result.bus_result;
446 fprintf(stdout, ")\n");
450 fprintf(stdout, "scbus%d on %s%d bus %d:\n",
452 bus_result->dev_name,
453 bus_result->unit_number,
457 case DEV_MATCH_DEVICE: {
458 struct device_match_result *dev_result;
459 char vendor[16], product[48], revision[16];
460 char fw[5], tmpstr[256];
463 &ccb.cdm.matches[i].result.device_result;
465 if ((dev_result->flags
466 & DEV_RESULT_UNCONFIGURED)
467 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
473 if (dev_result->protocol == PROTO_SCSI) {
474 cam_strvis(vendor, dev_result->inq_data.vendor,
475 sizeof(dev_result->inq_data.vendor),
478 dev_result->inq_data.product,
479 sizeof(dev_result->inq_data.product),
482 dev_result->inq_data.revision,
483 sizeof(dev_result->inq_data.revision),
485 sprintf(tmpstr, "<%s %s %s>", vendor, product,
487 } else if (dev_result->protocol == PROTO_ATA ||
488 dev_result->protocol == PROTO_SATAPM) {
490 dev_result->ident_data.model,
491 sizeof(dev_result->ident_data.model),
494 dev_result->ident_data.revision,
495 sizeof(dev_result->ident_data.revision),
497 sprintf(tmpstr, "<%s %s>", product,
499 } else if (dev_result->protocol == PROTO_SEMB) {
500 struct sep_identify_data *sid;
502 sid = (struct sep_identify_data *)
503 &dev_result->ident_data;
504 cam_strvis(vendor, sid->vendor_id,
505 sizeof(sid->vendor_id),
507 cam_strvis(product, sid->product_id,
508 sizeof(sid->product_id),
510 cam_strvis(revision, sid->product_rev,
511 sizeof(sid->product_rev),
513 cam_strvis(fw, sid->firmware_rev,
514 sizeof(sid->firmware_rev),
516 sprintf(tmpstr, "<%s %s %s %s>",
517 vendor, product, revision, fw);
519 sprintf(tmpstr, "<>");
522 fprintf(stdout, ")\n");
526 fprintf(stdout, "%-33s at scbus%d "
527 "target %d lun %d (",
530 dev_result->target_id,
531 dev_result->target_lun);
537 case DEV_MATCH_PERIPH: {
538 struct periph_match_result *periph_result;
541 &ccb.cdm.matches[i].result.periph_result;
543 if (skip_device != 0)
547 fprintf(stdout, ",");
549 fprintf(stdout, "%s%d",
550 periph_result->periph_name,
551 periph_result->unit_number);
557 fprintf(stdout, "unknown match type\n");
562 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
563 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
566 fprintf(stdout, ")\n");
575 testunitready(struct cam_device *device, int retry_count, int timeout,
581 ccb = cam_getccb(device);
583 scsi_test_unit_ready(&ccb->csio,
584 /* retries */ retry_count,
586 /* tag_action */ MSG_SIMPLE_Q_TAG,
587 /* sense_len */ SSD_FULL_SIZE,
588 /* timeout */ timeout ? timeout : 5000);
590 /* Disable freezing the device queue */
591 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
593 if (arglist & CAM_ARG_ERR_RECOVER)
594 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
596 if (cam_send_ccb(device, ccb) < 0) {
598 perror("error sending test unit ready");
600 if (arglist & CAM_ARG_VERBOSE) {
601 cam_error_print(device, ccb, CAM_ESF_ALL,
602 CAM_EPF_ALL, stderr);
609 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
611 fprintf(stdout, "Unit is ready\n");
614 fprintf(stdout, "Unit is not ready\n");
617 if (arglist & CAM_ARG_VERBOSE) {
618 cam_error_print(device, ccb, CAM_ESF_ALL,
619 CAM_EPF_ALL, stderr);
629 scsistart(struct cam_device *device, int startstop, int loadeject,
630 int retry_count, int timeout)
635 ccb = cam_getccb(device);
638 * If we're stopping, send an ordered tag so the drive in question
639 * will finish any previously queued writes before stopping. If
640 * the device isn't capable of tagged queueing, or if tagged
641 * queueing is turned off, the tag action is a no-op.
643 scsi_start_stop(&ccb->csio,
644 /* retries */ retry_count,
646 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
648 /* start/stop */ startstop,
649 /* load_eject */ loadeject,
651 /* sense_len */ SSD_FULL_SIZE,
652 /* timeout */ timeout ? timeout : 120000);
654 /* Disable freezing the device queue */
655 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
657 if (arglist & CAM_ARG_ERR_RECOVER)
658 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
660 if (cam_send_ccb(device, ccb) < 0) {
661 perror("error sending start unit");
663 if (arglist & CAM_ARG_VERBOSE) {
664 cam_error_print(device, ccb, CAM_ESF_ALL,
665 CAM_EPF_ALL, stderr);
672 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
674 fprintf(stdout, "Unit started successfully");
676 fprintf(stdout,", Media loaded\n");
678 fprintf(stdout,"\n");
680 fprintf(stdout, "Unit stopped successfully");
682 fprintf(stdout, ", Media ejected\n");
684 fprintf(stdout, "\n");
690 "Error received from start unit command\n");
693 "Error received from stop unit command\n");
695 if (arglist & CAM_ARG_VERBOSE) {
696 cam_error_print(device, ccb, CAM_ESF_ALL,
697 CAM_EPF_ALL, stderr);
707 scsidoinquiry(struct cam_device *device, int argc, char **argv,
708 char *combinedopt, int retry_count, int timeout)
713 while ((c = getopt(argc, argv, combinedopt)) != -1) {
716 arglist |= CAM_ARG_GET_STDINQ;
719 arglist |= CAM_ARG_GET_XFERRATE;
722 arglist |= CAM_ARG_GET_SERIAL;
730 * If the user didn't specify any inquiry options, he wants all of
733 if ((arglist & CAM_ARG_INQ_MASK) == 0)
734 arglist |= CAM_ARG_INQ_MASK;
736 if (arglist & CAM_ARG_GET_STDINQ)
737 error = scsiinquiry(device, retry_count, timeout);
742 if (arglist & CAM_ARG_GET_SERIAL)
743 scsiserial(device, retry_count, timeout);
748 if (arglist & CAM_ARG_GET_XFERRATE)
749 error = camxferrate(device);
755 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
758 struct scsi_inquiry_data *inq_buf;
761 ccb = cam_getccb(device);
764 warnx("couldn't allocate CCB");
768 /* cam_getccb cleans up the header, caller has to zero the payload */
769 bzero(&(&ccb->ccb_h)[1],
770 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
772 inq_buf = (struct scsi_inquiry_data *)malloc(
773 sizeof(struct scsi_inquiry_data));
775 if (inq_buf == NULL) {
777 warnx("can't malloc memory for inquiry\n");
780 bzero(inq_buf, sizeof(*inq_buf));
783 * Note that although the size of the inquiry buffer is the full
784 * 256 bytes specified in the SCSI spec, we only tell the device
785 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
786 * two reasons for this:
788 * - The SCSI spec says that when a length field is only 1 byte,
789 * a value of 0 will be interpreted as 256. Therefore
790 * scsi_inquiry() will convert an inq_len (which is passed in as
791 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
792 * to 0. Evidently, very few devices meet the spec in that
793 * regard. Some devices, like many Seagate disks, take the 0 as
794 * 0, and don't return any data. One Pioneer DVD-R drive
795 * returns more data than the command asked for.
797 * So, since there are numerous devices that just don't work
798 * right with the full inquiry size, we don't send the full size.
800 * - The second reason not to use the full inquiry data length is
801 * that we don't need it here. The only reason we issue a
802 * standard inquiry is to get the vendor name, device name,
803 * and revision so scsi_print_inquiry() can print them.
805 * If, at some point in the future, more inquiry data is needed for
806 * some reason, this code should use a procedure similar to the
807 * probe code. i.e., issue a short inquiry, and determine from
808 * the additional length passed back from the device how much
809 * inquiry data the device supports. Once the amount the device
810 * supports is determined, issue an inquiry for that amount and no
815 scsi_inquiry(&ccb->csio,
816 /* retries */ retry_count,
818 /* tag_action */ MSG_SIMPLE_Q_TAG,
819 /* inq_buf */ (u_int8_t *)inq_buf,
820 /* inq_len */ SHORT_INQUIRY_LENGTH,
823 /* sense_len */ SSD_FULL_SIZE,
824 /* timeout */ timeout ? timeout : 5000);
826 /* Disable freezing the device queue */
827 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
829 if (arglist & CAM_ARG_ERR_RECOVER)
830 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
832 if (cam_send_ccb(device, ccb) < 0) {
833 perror("error sending SCSI inquiry");
835 if (arglist & CAM_ARG_VERBOSE) {
836 cam_error_print(device, ccb, CAM_ESF_ALL,
837 CAM_EPF_ALL, stderr);
844 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
847 if (arglist & CAM_ARG_VERBOSE) {
848 cam_error_print(device, ccb, CAM_ESF_ALL,
849 CAM_EPF_ALL, stderr);
860 fprintf(stdout, "%s%d: ", device->device_name,
861 device->dev_unit_num);
862 scsi_print_inquiry(inq_buf);
870 scsiserial(struct cam_device *device, int retry_count, int timeout)
873 struct scsi_vpd_unit_serial_number *serial_buf;
874 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
877 ccb = cam_getccb(device);
880 warnx("couldn't allocate CCB");
884 /* cam_getccb cleans up the header, caller has to zero the payload */
885 bzero(&(&ccb->ccb_h)[1],
886 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
888 serial_buf = (struct scsi_vpd_unit_serial_number *)
889 malloc(sizeof(*serial_buf));
891 if (serial_buf == NULL) {
893 warnx("can't malloc memory for serial number");
897 scsi_inquiry(&ccb->csio,
898 /*retries*/ retry_count,
900 /* tag_action */ MSG_SIMPLE_Q_TAG,
901 /* inq_buf */ (u_int8_t *)serial_buf,
902 /* inq_len */ sizeof(*serial_buf),
904 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
905 /* sense_len */ SSD_FULL_SIZE,
906 /* timeout */ timeout ? timeout : 5000);
908 /* Disable freezing the device queue */
909 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
911 if (arglist & CAM_ARG_ERR_RECOVER)
912 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
914 if (cam_send_ccb(device, ccb) < 0) {
915 warn("error getting serial number");
917 if (arglist & CAM_ARG_VERBOSE) {
918 cam_error_print(device, ccb, CAM_ESF_ALL,
919 CAM_EPF_ALL, stderr);
927 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
930 if (arglist & CAM_ARG_VERBOSE) {
931 cam_error_print(device, ccb, CAM_ESF_ALL,
932 CAM_EPF_ALL, stderr);
943 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
944 serial_num[serial_buf->length] = '\0';
946 if ((arglist & CAM_ARG_GET_STDINQ)
947 || (arglist & CAM_ARG_GET_XFERRATE))
948 fprintf(stdout, "%s%d: Serial Number ",
949 device->device_name, device->dev_unit_num);
951 fprintf(stdout, "%.60s\n", serial_num);
959 camxferrate(struct cam_device *device)
961 struct ccb_pathinq cpi;
968 if ((retval = get_cpi(device, &cpi)) != 0)
971 ccb = cam_getccb(device);
974 warnx("couldn't allocate CCB");
978 bzero(&(&ccb->ccb_h)[1],
979 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
981 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
982 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
984 if (((retval = cam_send_ccb(device, ccb)) < 0)
985 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
986 const char error_string[] = "error getting transfer settings";
993 if (arglist & CAM_ARG_VERBOSE)
994 cam_error_print(device, ccb, CAM_ESF_ALL,
995 CAM_EPF_ALL, stderr);
999 goto xferrate_bailout;
1003 speed = cpi.base_transfer_speed;
1005 if (ccb->cts.transport == XPORT_SPI) {
1006 struct ccb_trans_settings_spi *spi =
1007 &ccb->cts.xport_specific.spi;
1009 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1010 freq = scsi_calc_syncsrate(spi->sync_period);
1013 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1014 speed *= (0x01 << spi->bus_width);
1016 } else if (ccb->cts.transport == XPORT_FC) {
1017 struct ccb_trans_settings_fc *fc =
1018 &ccb->cts.xport_specific.fc;
1020 if (fc->valid & CTS_FC_VALID_SPEED)
1021 speed = fc->bitrate;
1022 } else if (ccb->cts.transport == XPORT_SAS) {
1023 struct ccb_trans_settings_sas *sas =
1024 &ccb->cts.xport_specific.sas;
1026 if (sas->valid & CTS_SAS_VALID_SPEED)
1027 speed = sas->bitrate;
1028 } else if (ccb->cts.transport == XPORT_ATA) {
1029 struct ccb_trans_settings_pata *pata =
1030 &ccb->cts.xport_specific.ata;
1032 if (pata->valid & CTS_ATA_VALID_MODE)
1033 speed = ata_mode2speed(pata->mode);
1034 } else if (ccb->cts.transport == XPORT_SATA) {
1035 struct ccb_trans_settings_sata *sata =
1036 &ccb->cts.xport_specific.sata;
1038 if (sata->valid & CTS_SATA_VALID_REVISION)
1039 speed = ata_revision2speed(sata->revision);
1044 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1045 device->device_name, device->dev_unit_num,
1048 fprintf(stdout, "%s%d: %dKB/s transfers",
1049 device->device_name, device->dev_unit_num,
1053 if (ccb->cts.transport == XPORT_SPI) {
1054 struct ccb_trans_settings_spi *spi =
1055 &ccb->cts.xport_specific.spi;
1057 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1058 && (spi->sync_offset != 0))
1059 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1060 freq % 1000, spi->sync_offset);
1062 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1063 && (spi->bus_width > 0)) {
1064 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1065 && (spi->sync_offset != 0)) {
1066 fprintf(stdout, ", ");
1068 fprintf(stdout, " (");
1070 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1071 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1072 && (spi->sync_offset != 0)) {
1073 fprintf(stdout, ")");
1075 } else if (ccb->cts.transport == XPORT_ATA) {
1076 struct ccb_trans_settings_pata *pata =
1077 &ccb->cts.xport_specific.ata;
1080 if (pata->valid & CTS_ATA_VALID_MODE)
1081 printf("%s, ", ata_mode2string(pata->mode));
1082 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1083 printf("ATAPI %dbytes, ", pata->atapi);
1084 if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1085 printf("PIO %dbytes", pata->bytecount);
1087 } else if (ccb->cts.transport == XPORT_SATA) {
1088 struct ccb_trans_settings_sata *sata =
1089 &ccb->cts.xport_specific.sata;
1092 if (sata->valid & CTS_SATA_VALID_REVISION)
1093 printf("SATA %d.x, ", sata->revision);
1096 if (sata->valid & CTS_SATA_VALID_MODE)
1097 printf("%s, ", ata_mode2string(sata->mode));
1098 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1099 printf("ATAPI %dbytes, ", sata->atapi);
1100 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1101 printf("PIO %dbytes", sata->bytecount);
1105 if (ccb->cts.protocol == PROTO_SCSI) {
1106 struct ccb_trans_settings_scsi *scsi =
1107 &ccb->cts.proto_specific.scsi;
1108 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1109 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1110 fprintf(stdout, ", Command Queueing Enabled");
1115 fprintf(stdout, "\n");
1125 atacapprint(struct ata_params *parm)
1127 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1128 ((u_int32_t)parm->lba_size_2 << 16);
1130 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1131 ((u_int64_t)parm->lba_size48_2 << 16) |
1132 ((u_int64_t)parm->lba_size48_3 << 32) |
1133 ((u_int64_t)parm->lba_size48_4 << 48);
1136 printf("protocol ");
1137 printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1138 if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1139 if (parm->satacapabilities & ATA_SATA_GEN3)
1140 printf(" SATA 3.x\n");
1141 else if (parm->satacapabilities & ATA_SATA_GEN2)
1142 printf(" SATA 2.x\n");
1143 else if (parm->satacapabilities & ATA_SATA_GEN1)
1144 printf(" SATA 1.x\n");
1150 printf("device model %.40s\n", parm->model);
1151 printf("firmware revision %.8s\n", parm->revision);
1152 printf("serial number %.20s\n", parm->serial);
1153 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1154 printf("WWN %04x%04x%04x%04x\n",
1155 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1157 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1158 printf("media serial number %.30s\n",
1159 parm->media_serial);
1162 printf("cylinders %d\n", parm->cylinders);
1163 printf("heads %d\n", parm->heads);
1164 printf("sectors/track %d\n", parm->sectors);
1165 printf("sector size logical %u, physical %lu, offset %lu\n",
1166 ata_logical_sector_size(parm),
1167 (unsigned long)ata_physical_sector_size(parm),
1168 (unsigned long)ata_logical_sector_offset(parm));
1170 if (parm->config == ATA_PROTO_CFA ||
1171 (parm->support.command2 & ATA_SUPPORT_CFA))
1172 printf("CFA supported\n");
1174 printf("LBA%ssupported ",
1175 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1177 printf("%d sectors\n", lbasize);
1181 printf("LBA48%ssupported ",
1182 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1184 printf("%ju sectors\n", (uintmax_t)lbasize48);
1188 printf("PIO supported PIO");
1189 switch (ata_max_pmode(parm)) {
1205 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1206 printf(" w/o IORDY");
1209 printf("DMA%ssupported ",
1210 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1211 if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1212 if (parm->mwdmamodes & 0xff) {
1214 if (parm->mwdmamodes & 0x04)
1216 else if (parm->mwdmamodes & 0x02)
1218 else if (parm->mwdmamodes & 0x01)
1222 if ((parm->atavalid & ATA_FLAG_88) &&
1223 (parm->udmamodes & 0xff)) {
1225 if (parm->udmamodes & 0x40)
1227 else if (parm->udmamodes & 0x20)
1229 else if (parm->udmamodes & 0x10)
1231 else if (parm->udmamodes & 0x08)
1233 else if (parm->udmamodes & 0x04)
1235 else if (parm->udmamodes & 0x02)
1237 else if (parm->udmamodes & 0x01)
1244 if (parm->media_rotation_rate == 1) {
1245 printf("media RPM non-rotating\n");
1246 } else if (parm->media_rotation_rate >= 0x0401 &&
1247 parm->media_rotation_rate <= 0xFFFE) {
1248 printf("media RPM %d\n",
1249 parm->media_rotation_rate);
1253 "Support Enabled Value Vendor\n");
1254 printf("read ahead %s %s\n",
1255 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1256 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1257 printf("write cache %s %s\n",
1258 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1259 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1260 printf("flush cache %s %s\n",
1261 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1262 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1263 printf("overlap %s\n",
1264 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1265 printf("Tagged Command Queuing (TCQ) %s %s",
1266 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1267 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1268 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1269 printf(" %d tags\n",
1270 ATA_QUEUE_LEN(parm->queue) + 1);
1273 printf("Native Command Queuing (NCQ) ");
1274 if (parm->satacapabilities != 0xffff &&
1275 (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1276 printf("yes %d tags\n",
1277 ATA_QUEUE_LEN(parm->queue) + 1);
1280 printf("SMART %s %s\n",
1281 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1282 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1283 printf("microcode download %s %s\n",
1284 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1285 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1286 printf("security %s %s\n",
1287 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1288 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1289 printf("power management %s %s\n",
1290 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1291 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1292 printf("advanced power management %s %s",
1293 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1294 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1295 if (parm->support.command2 & ATA_SUPPORT_APM) {
1296 printf(" %d/0x%02X\n",
1297 parm->apm_value, parm->apm_value);
1300 printf("automatic acoustic management %s %s",
1301 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1302 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1303 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1304 printf(" %d/0x%02X %d/0x%02X\n",
1305 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1306 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1307 ATA_ACOUSTIC_VENDOR(parm->acoustic),
1308 ATA_ACOUSTIC_VENDOR(parm->acoustic));
1311 printf("media status notification %s %s\n",
1312 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1313 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1314 printf("power-up in Standby %s %s\n",
1315 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1316 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1317 printf("write-read-verify %s %s",
1318 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1319 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1320 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1321 printf(" %d/0x%x\n",
1322 parm->wrv_mode, parm->wrv_mode);
1325 printf("unload %s %s\n",
1326 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1327 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1328 printf("free-fall %s %s\n",
1329 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1330 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1331 printf("data set management (TRIM) %s\n",
1332 parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1336 ataidentify(struct cam_device *device, int retry_count, int timeout)
1339 struct ata_params *ident_buf;
1340 struct ccb_getdev cgd;
1344 if (get_cgd(device, &cgd) != 0) {
1345 warnx("couldn't get CGD");
1348 ccb = cam_getccb(device);
1351 warnx("couldn't allocate CCB");
1355 /* cam_getccb cleans up the header, caller has to zero the payload */
1356 bzero(&(&ccb->ccb_h)[1],
1357 sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1359 ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1363 warnx("can't malloc memory for identify\n");
1366 bzero(ptr, sizeof(struct ata_params));
1368 cam_fill_ataio(&ccb->ataio,
1371 /*flags*/CAM_DIR_IN,
1373 /*data_ptr*/(u_int8_t *)ptr,
1374 /*dxfer_len*/sizeof(struct ata_params),
1375 timeout ? timeout : 30 * 1000);
1376 if (cgd.protocol == PROTO_ATA)
1377 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1379 ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1381 /* Disable freezing the device queue */
1382 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1384 if (arglist & CAM_ARG_ERR_RECOVER)
1385 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1387 if (cam_send_ccb(device, ccb) < 0) {
1388 perror("error sending ATA identify");
1390 if (arglist & CAM_ARG_VERBOSE) {
1391 cam_error_print(device, ccb, CAM_ESF_ALL,
1392 CAM_EPF_ALL, stderr);
1400 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1403 if (arglist & CAM_ARG_VERBOSE) {
1404 cam_error_print(device, ccb, CAM_ESF_ALL,
1405 CAM_EPF_ALL, stderr);
1416 for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1417 ptr[i] = le16toh(ptr[i]);
1418 if (arglist & CAM_ARG_VERBOSE) {
1419 fprintf(stdout, "%s%d: Raw identify data:\n",
1420 device->device_name, device->dev_unit_num);
1421 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1423 fprintf(stdout, " %3d: ", i);
1424 fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1426 fprintf(stdout, "\n");
1429 ident_buf = (struct ata_params *)ptr;
1430 if (strncmp(ident_buf->model, "FX", 2) &&
1431 strncmp(ident_buf->model, "NEC", 3) &&
1432 strncmp(ident_buf->model, "Pioneer", 7) &&
1433 strncmp(ident_buf->model, "SHARP", 5)) {
1434 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1435 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1436 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1437 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1439 ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1440 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1441 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1442 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1443 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1444 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1445 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1446 ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1447 sizeof(ident_buf->media_serial));
1449 fprintf(stdout, "%s%d: ", device->device_name,
1450 device->dev_unit_num);
1451 ata_print_ident(ident_buf);
1452 camxferrate(device);
1453 atacapprint(ident_buf);
1459 #endif /* MINIMALISTIC */
1462 * Parse out a bus, or a bus, target and lun in the following
1468 * Returns the number of parsed components, or 0.
1471 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1476 while (isspace(*tstr) && (*tstr != '\0'))
1479 tmpstr = (char *)strtok(tstr, ":");
1480 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1481 *bus = strtol(tmpstr, NULL, 0);
1482 *arglst |= CAM_ARG_BUS;
1484 tmpstr = (char *)strtok(NULL, ":");
1485 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1486 *target = strtol(tmpstr, NULL, 0);
1487 *arglst |= CAM_ARG_TARGET;
1489 tmpstr = (char *)strtok(NULL, ":");
1490 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1491 *lun = strtol(tmpstr, NULL, 0);
1492 *arglst |= CAM_ARG_LUN;
1502 dorescan_or_reset(int argc, char **argv, int rescan)
1504 static const char must[] =
1505 "you must specify \"all\", a bus, or a bus:target:lun to %s";
1507 int bus = -1, target = -1, lun = -1;
1511 warnx(must, rescan? "rescan" : "reset");
1515 tstr = argv[optind];
1516 while (isspace(*tstr) && (*tstr != '\0'))
1518 if (strncasecmp(tstr, "all", strlen("all")) == 0)
1519 arglist |= CAM_ARG_BUS;
1521 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1522 if (rv != 1 && rv != 3) {
1523 warnx(must, rescan? "rescan" : "reset");
1528 if ((arglist & CAM_ARG_BUS)
1529 && (arglist & CAM_ARG_TARGET)
1530 && (arglist & CAM_ARG_LUN))
1531 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1533 error = rescan_or_reset_bus(bus, rescan);
1539 rescan_or_reset_bus(int bus, int rescan)
1541 union ccb ccb, matchccb;
1547 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1548 warnx("error opening transport layer device %s", XPT_DEVICE);
1549 warn("%s", XPT_DEVICE);
1554 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1555 ccb.ccb_h.path_id = bus;
1556 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1557 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1558 ccb.crcn.flags = CAM_FLAG_NONE;
1560 /* run this at a low priority */
1561 ccb.ccb_h.pinfo.priority = 5;
1563 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1564 warn("CAMIOCOMMAND ioctl failed");
1569 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1570 fprintf(stdout, "%s of bus %d was successful\n",
1571 rescan ? "Re-scan" : "Reset", bus);
1573 fprintf(stdout, "%s of bus %d returned error %#x\n",
1574 rescan ? "Re-scan" : "Reset", bus,
1575 ccb.ccb_h.status & CAM_STATUS_MASK);
1586 * The right way to handle this is to modify the xpt so that it can
1587 * handle a wildcarded bus in a rescan or reset CCB. At the moment
1588 * that isn't implemented, so instead we enumerate the busses and
1589 * send the rescan or reset to those busses in the case where the
1590 * given bus is -1 (wildcard). We don't send a rescan or reset
1591 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1592 * no-op, sending a rescan to the xpt bus would result in a status of
1595 bzero(&(&matchccb.ccb_h)[1],
1596 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1597 matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1598 matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
1599 bufsize = sizeof(struct dev_match_result) * 20;
1600 matchccb.cdm.match_buf_len = bufsize;
1601 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1602 if (matchccb.cdm.matches == NULL) {
1603 warnx("can't malloc memory for matches");
1607 matchccb.cdm.num_matches = 0;
1609 matchccb.cdm.num_patterns = 1;
1610 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1612 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1613 matchccb.cdm.pattern_buf_len);
1614 if (matchccb.cdm.patterns == NULL) {
1615 warnx("can't malloc memory for patterns");
1619 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1620 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1625 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1626 warn("CAMIOCOMMAND ioctl failed");
1631 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1632 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1633 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1634 warnx("got CAM error %#x, CDM error %d\n",
1635 matchccb.ccb_h.status, matchccb.cdm.status);
1640 for (i = 0; i < matchccb.cdm.num_matches; i++) {
1641 struct bus_match_result *bus_result;
1643 /* This shouldn't happen. */
1644 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1647 bus_result = &matchccb.cdm.matches[i].result.bus_result;
1650 * We don't want to rescan or reset the xpt bus.
1653 if ((int)bus_result->path_id == -1)
1656 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1658 ccb.ccb_h.path_id = bus_result->path_id;
1659 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1660 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1661 ccb.crcn.flags = CAM_FLAG_NONE;
1663 /* run this at a low priority */
1664 ccb.ccb_h.pinfo.priority = 5;
1666 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1667 warn("CAMIOCOMMAND ioctl failed");
1672 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1673 fprintf(stdout, "%s of bus %d was successful\n",
1674 rescan? "Re-scan" : "Reset",
1675 bus_result->path_id);
1678 * Don't bail out just yet, maybe the other
1679 * rescan or reset commands will complete
1682 fprintf(stderr, "%s of bus %d returned error "
1683 "%#x\n", rescan? "Re-scan" : "Reset",
1684 bus_result->path_id,
1685 ccb.ccb_h.status & CAM_STATUS_MASK);
1689 } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1690 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1697 if (matchccb.cdm.patterns != NULL)
1698 free(matchccb.cdm.patterns);
1699 if (matchccb.cdm.matches != NULL)
1700 free(matchccb.cdm.matches);
1706 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1709 struct cam_device *device;
1715 warnx("invalid bus number %d", bus);
1720 warnx("invalid target number %d", target);
1725 warnx("invalid lun number %d", lun);
1731 bzero(&ccb, sizeof(union ccb));
1734 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1735 warnx("error opening transport layer device %s\n",
1737 warn("%s", XPT_DEVICE);
1741 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1742 if (device == NULL) {
1743 warnx("%s", cam_errbuf);
1748 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1749 ccb.ccb_h.path_id = bus;
1750 ccb.ccb_h.target_id = target;
1751 ccb.ccb_h.target_lun = lun;
1752 ccb.ccb_h.timeout = 5000;
1753 ccb.crcn.flags = CAM_FLAG_NONE;
1755 /* run this at a low priority */
1756 ccb.ccb_h.pinfo.priority = 5;
1759 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1760 warn("CAMIOCOMMAND ioctl failed");
1765 if (cam_send_ccb(device, &ccb) < 0) {
1766 warn("error sending XPT_RESET_DEV CCB");
1767 cam_close_device(device);
1775 cam_close_device(device);
1778 * An error code of CAM_BDR_SENT is normal for a BDR request.
1780 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1782 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1783 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1784 scan? "Re-scan" : "Reset", bus, target, lun);
1787 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1788 scan? "Re-scan" : "Reset", bus, target, lun,
1789 ccb.ccb_h.status & CAM_STATUS_MASK);
1794 #ifndef MINIMALISTIC
1796 readdefects(struct cam_device *device, int argc, char **argv,
1797 char *combinedopt, int retry_count, int timeout)
1799 union ccb *ccb = NULL;
1800 struct scsi_read_defect_data_10 *rdd_cdb;
1801 u_int8_t *defect_list = NULL;
1802 u_int32_t dlist_length = 65000;
1803 u_int32_t returned_length = 0;
1804 u_int32_t num_returned = 0;
1805 u_int8_t returned_format;
1808 int lists_specified = 0;
1810 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1816 while (isspace(*tstr) && (*tstr != '\0'))
1818 if (strcmp(tstr, "block") == 0)
1819 arglist |= CAM_ARG_FORMAT_BLOCK;
1820 else if (strcmp(tstr, "bfi") == 0)
1821 arglist |= CAM_ARG_FORMAT_BFI;
1822 else if (strcmp(tstr, "phys") == 0)
1823 arglist |= CAM_ARG_FORMAT_PHYS;
1826 warnx("invalid defect format %s", tstr);
1827 goto defect_bailout;
1832 arglist |= CAM_ARG_GLIST;
1835 arglist |= CAM_ARG_PLIST;
1842 ccb = cam_getccb(device);
1845 * Hopefully 65000 bytes is enough to hold the defect list. If it
1846 * isn't, the disk is probably dead already. We'd have to go with
1847 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1850 defect_list = malloc(dlist_length);
1851 if (defect_list == NULL) {
1852 warnx("can't malloc memory for defect list");
1854 goto defect_bailout;
1857 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1860 * cam_getccb() zeros the CCB header only. So we need to zero the
1861 * payload portion of the ccb.
1863 bzero(&(&ccb->ccb_h)[1],
1864 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1866 cam_fill_csio(&ccb->csio,
1867 /*retries*/ retry_count,
1869 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1870 CAM_PASS_ERR_RECOVER : 0),
1871 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1872 /*data_ptr*/ defect_list,
1873 /*dxfer_len*/ dlist_length,
1874 /*sense_len*/ SSD_FULL_SIZE,
1875 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1876 /*timeout*/ timeout ? timeout : 5000);
1878 rdd_cdb->opcode = READ_DEFECT_DATA_10;
1879 if (arglist & CAM_ARG_FORMAT_BLOCK)
1880 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1881 else if (arglist & CAM_ARG_FORMAT_BFI)
1882 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1883 else if (arglist & CAM_ARG_FORMAT_PHYS)
1884 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1887 warnx("no defect list format specified");
1888 goto defect_bailout;
1890 if (arglist & CAM_ARG_PLIST) {
1891 rdd_cdb->format |= SRDD10_PLIST;
1895 if (arglist & CAM_ARG_GLIST) {
1896 rdd_cdb->format |= SRDD10_GLIST;
1900 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1902 /* Disable freezing the device queue */
1903 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1905 if (cam_send_ccb(device, ccb) < 0) {
1906 perror("error reading defect list");
1908 if (arglist & CAM_ARG_VERBOSE) {
1909 cam_error_print(device, ccb, CAM_ESF_ALL,
1910 CAM_EPF_ALL, stderr);
1914 goto defect_bailout;
1917 returned_length = scsi_2btoul(((struct
1918 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1920 returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1921 defect_list)->format;
1923 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1924 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1925 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1926 struct scsi_sense_data *sense;
1927 int error_code, sense_key, asc, ascq;
1929 sense = &ccb->csio.sense_data;
1930 scsi_extract_sense_len(sense, ccb->csio.sense_len -
1931 ccb->csio.sense_resid, &error_code, &sense_key, &asc,
1932 &ascq, /*show_errors*/ 1);
1935 * According to the SCSI spec, if the disk doesn't support
1936 * the requested format, it will generally return a sense
1937 * key of RECOVERED ERROR, and an additional sense code
1938 * of "DEFECT LIST NOT FOUND". So, we check for that, and
1939 * also check to make sure that the returned length is
1940 * greater than 0, and then print out whatever format the
1943 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1944 && (asc == 0x1c) && (ascq == 0x00)
1945 && (returned_length > 0)) {
1946 warnx("requested defect format not available");
1947 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1948 case SRDD10_BLOCK_FORMAT:
1949 warnx("Device returned block format");
1951 case SRDD10_BYTES_FROM_INDEX_FORMAT:
1952 warnx("Device returned bytes from index"
1955 case SRDD10_PHYSICAL_SECTOR_FORMAT:
1956 warnx("Device returned physical sector format");
1960 warnx("Device returned unknown defect"
1961 " data format %#x", returned_format);
1962 goto defect_bailout;
1963 break; /* NOTREACHED */
1967 warnx("Error returned from read defect data command");
1968 if (arglist & CAM_ARG_VERBOSE)
1969 cam_error_print(device, ccb, CAM_ESF_ALL,
1970 CAM_EPF_ALL, stderr);
1971 goto defect_bailout;
1973 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1975 warnx("Error returned from read defect data command");
1976 if (arglist & CAM_ARG_VERBOSE)
1977 cam_error_print(device, ccb, CAM_ESF_ALL,
1978 CAM_EPF_ALL, stderr);
1979 goto defect_bailout;
1983 * XXX KDM I should probably clean up the printout format for the
1986 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1987 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1989 struct scsi_defect_desc_phys_sector *dlist;
1991 dlist = (struct scsi_defect_desc_phys_sector *)
1993 sizeof(struct scsi_read_defect_data_hdr_10));
1995 num_returned = returned_length /
1996 sizeof(struct scsi_defect_desc_phys_sector);
1998 fprintf(stderr, "Got %d defect", num_returned);
2000 if ((lists_specified == 0) || (num_returned == 0)) {
2001 fprintf(stderr, "s.\n");
2003 } else if (num_returned == 1)
2004 fprintf(stderr, ":\n");
2006 fprintf(stderr, "s:\n");
2008 for (i = 0; i < num_returned; i++) {
2009 fprintf(stdout, "%d:%d:%d\n",
2010 scsi_3btoul(dlist[i].cylinder),
2012 scsi_4btoul(dlist[i].sector));
2016 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
2018 struct scsi_defect_desc_bytes_from_index *dlist;
2020 dlist = (struct scsi_defect_desc_bytes_from_index *)
2022 sizeof(struct scsi_read_defect_data_hdr_10));
2024 num_returned = returned_length /
2025 sizeof(struct scsi_defect_desc_bytes_from_index);
2027 fprintf(stderr, "Got %d defect", num_returned);
2029 if ((lists_specified == 0) || (num_returned == 0)) {
2030 fprintf(stderr, "s.\n");
2032 } else if (num_returned == 1)
2033 fprintf(stderr, ":\n");
2035 fprintf(stderr, "s:\n");
2037 for (i = 0; i < num_returned; i++) {
2038 fprintf(stdout, "%d:%d:%d\n",
2039 scsi_3btoul(dlist[i].cylinder),
2041 scsi_4btoul(dlist[i].bytes_from_index));
2045 case SRDDH10_BLOCK_FORMAT:
2047 struct scsi_defect_desc_block *dlist;
2049 dlist = (struct scsi_defect_desc_block *)(defect_list +
2050 sizeof(struct scsi_read_defect_data_hdr_10));
2052 num_returned = returned_length /
2053 sizeof(struct scsi_defect_desc_block);
2055 fprintf(stderr, "Got %d defect", num_returned);
2057 if ((lists_specified == 0) || (num_returned == 0)) {
2058 fprintf(stderr, "s.\n");
2060 } else if (num_returned == 1)
2061 fprintf(stderr, ":\n");
2063 fprintf(stderr, "s:\n");
2065 for (i = 0; i < num_returned; i++)
2066 fprintf(stdout, "%u\n",
2067 scsi_4btoul(dlist[i].address));
2071 fprintf(stderr, "Unknown defect format %d\n",
2072 returned_format & SRDDH10_DLIST_FORMAT_MASK);
2078 if (defect_list != NULL)
2086 #endif /* MINIMALISTIC */
2090 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2094 ccb = cam_getccb(device);
2100 #ifndef MINIMALISTIC
2102 mode_sense(struct cam_device *device, int mode_page, int page_control,
2103 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2108 ccb = cam_getccb(device);
2111 errx(1, "mode_sense: couldn't allocate CCB");
2113 bzero(&(&ccb->ccb_h)[1],
2114 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2116 scsi_mode_sense(&ccb->csio,
2117 /* retries */ retry_count,
2119 /* tag_action */ MSG_SIMPLE_Q_TAG,
2121 /* page_code */ page_control << 6,
2122 /* page */ mode_page,
2123 /* param_buf */ data,
2124 /* param_len */ datalen,
2125 /* sense_len */ SSD_FULL_SIZE,
2126 /* timeout */ timeout ? timeout : 5000);
2128 if (arglist & CAM_ARG_ERR_RECOVER)
2129 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2131 /* Disable freezing the device queue */
2132 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2134 if (((retval = cam_send_ccb(device, ccb)) < 0)
2135 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2136 if (arglist & CAM_ARG_VERBOSE) {
2137 cam_error_print(device, ccb, CAM_ESF_ALL,
2138 CAM_EPF_ALL, stderr);
2141 cam_close_device(device);
2143 err(1, "error sending mode sense command");
2145 errx(1, "error sending mode sense command");
2152 mode_select(struct cam_device *device, int save_pages, int retry_count,
2153 int timeout, u_int8_t *data, int datalen)
2158 ccb = cam_getccb(device);
2161 errx(1, "mode_select: couldn't allocate CCB");
2163 bzero(&(&ccb->ccb_h)[1],
2164 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2166 scsi_mode_select(&ccb->csio,
2167 /* retries */ retry_count,
2169 /* tag_action */ MSG_SIMPLE_Q_TAG,
2170 /* scsi_page_fmt */ 1,
2171 /* save_pages */ save_pages,
2172 /* param_buf */ data,
2173 /* param_len */ datalen,
2174 /* sense_len */ SSD_FULL_SIZE,
2175 /* timeout */ timeout ? timeout : 5000);
2177 if (arglist & CAM_ARG_ERR_RECOVER)
2178 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2180 /* Disable freezing the device queue */
2181 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2183 if (((retval = cam_send_ccb(device, ccb)) < 0)
2184 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2185 if (arglist & CAM_ARG_VERBOSE) {
2186 cam_error_print(device, ccb, CAM_ESF_ALL,
2187 CAM_EPF_ALL, stderr);
2190 cam_close_device(device);
2193 err(1, "error sending mode select command");
2195 errx(1, "error sending mode select command");
2203 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2204 int retry_count, int timeout)
2206 int c, mode_page = -1, page_control = 0;
2207 int binary = 0, list = 0;
2209 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2215 arglist |= CAM_ARG_DBD;
2218 arglist |= CAM_ARG_MODE_EDIT;
2224 mode_page = strtol(optarg, NULL, 0);
2226 errx(1, "invalid mode page %d", mode_page);
2229 page_control = strtol(optarg, NULL, 0);
2230 if ((page_control < 0) || (page_control > 3))
2231 errx(1, "invalid page control field %d",
2233 arglist |= CAM_ARG_PAGE_CNTL;
2240 if (mode_page == -1 && list == 0)
2241 errx(1, "you must specify a mode page!");
2244 mode_list(device, page_control, arglist & CAM_ARG_DBD,
2245 retry_count, timeout);
2247 mode_edit(device, mode_page, page_control,
2248 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2249 retry_count, timeout);
2254 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2255 int retry_count, int timeout)
2258 u_int32_t flags = CAM_DIR_NONE;
2259 u_int8_t *data_ptr = NULL;
2261 u_int8_t atacmd[12];
2262 struct get_hook hook;
2263 int c, data_bytes = 0;
2269 char *datastr = NULL, *tstr, *resstr = NULL;
2271 int fd_data = 0, fd_res = 0;
2274 ccb = cam_getccb(device);
2277 warnx("scsicmd: error allocating ccb");
2281 bzero(&(&ccb->ccb_h)[1],
2282 sizeof(union ccb) - sizeof(struct ccb_hdr));
2284 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2288 while (isspace(*tstr) && (*tstr != '\0'))
2290 hook.argc = argc - optind;
2291 hook.argv = argv + optind;
2293 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2296 * Increment optind by the number of arguments the
2297 * encoding routine processed. After each call to
2298 * getopt(3), optind points to the argument that
2299 * getopt should process _next_. In this case,
2300 * that means it points to the first command string
2301 * argument, if there is one. Once we increment
2302 * this, it should point to either the next command
2303 * line argument, or it should be past the end of
2310 while (isspace(*tstr) && (*tstr != '\0'))
2312 hook.argc = argc - optind;
2313 hook.argv = argv + optind;
2315 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2318 * Increment optind by the number of arguments the
2319 * encoding routine processed. After each call to
2320 * getopt(3), optind points to the argument that
2321 * getopt should process _next_. In this case,
2322 * that means it points to the first command string
2323 * argument, if there is one. Once we increment
2324 * this, it should point to either the next command
2325 * line argument, or it should be past the end of
2337 if (arglist & CAM_ARG_CMD_OUT) {
2338 warnx("command must either be "
2339 "read or write, not both");
2341 goto scsicmd_bailout;
2343 arglist |= CAM_ARG_CMD_IN;
2345 data_bytes = strtol(optarg, NULL, 0);
2346 if (data_bytes <= 0) {
2347 warnx("invalid number of input bytes %d",
2350 goto scsicmd_bailout;
2352 hook.argc = argc - optind;
2353 hook.argv = argv + optind;
2356 datastr = cget(&hook, NULL);
2358 * If the user supplied "-" instead of a format, he
2359 * wants the data to be written to stdout.
2361 if ((datastr != NULL)
2362 && (datastr[0] == '-'))
2365 data_ptr = (u_int8_t *)malloc(data_bytes);
2366 if (data_ptr == NULL) {
2367 warnx("can't malloc memory for data_ptr");
2369 goto scsicmd_bailout;
2373 if (arglist & CAM_ARG_CMD_IN) {
2374 warnx("command must either be "
2375 "read or write, not both");
2377 goto scsicmd_bailout;
2379 arglist |= CAM_ARG_CMD_OUT;
2380 flags = CAM_DIR_OUT;
2381 data_bytes = strtol(optarg, NULL, 0);
2382 if (data_bytes <= 0) {
2383 warnx("invalid number of output bytes %d",
2386 goto scsicmd_bailout;
2388 hook.argc = argc - optind;
2389 hook.argv = argv + optind;
2391 datastr = cget(&hook, NULL);
2392 data_ptr = (u_int8_t *)malloc(data_bytes);
2393 if (data_ptr == NULL) {
2394 warnx("can't malloc memory for data_ptr");
2396 goto scsicmd_bailout;
2398 bzero(data_ptr, data_bytes);
2400 * If the user supplied "-" instead of a format, he
2401 * wants the data to be read from stdin.
2403 if ((datastr != NULL)
2404 && (datastr[0] == '-'))
2407 buff_encode_visit(data_ptr, data_bytes, datastr,
2413 hook.argc = argc - optind;
2414 hook.argv = argv + optind;
2416 resstr = cget(&hook, NULL);
2417 if ((resstr != NULL) && (resstr[0] == '-'))
2427 * If fd_data is set, and we're writing to the device, we need to
2428 * read the data the user wants written from stdin.
2430 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2432 int amt_to_read = data_bytes;
2433 u_int8_t *buf_ptr = data_ptr;
2435 for (amt_read = 0; amt_to_read > 0;
2436 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2437 if (amt_read == -1) {
2438 warn("error reading data from stdin");
2440 goto scsicmd_bailout;
2442 amt_to_read -= amt_read;
2443 buf_ptr += amt_read;
2447 if (arglist & CAM_ARG_ERR_RECOVER)
2448 flags |= CAM_PASS_ERR_RECOVER;
2450 /* Disable freezing the device queue */
2451 flags |= CAM_DEV_QFRZDIS;
2455 * This is taken from the SCSI-3 draft spec.
2456 * (T10/1157D revision 0.3)
2457 * The top 3 bits of an opcode are the group code.
2458 * The next 5 bits are the command code.
2459 * Group 0: six byte commands
2460 * Group 1: ten byte commands
2461 * Group 2: ten byte commands
2463 * Group 4: sixteen byte commands
2464 * Group 5: twelve byte commands
2465 * Group 6: vendor specific
2466 * Group 7: vendor specific
2468 switch((cdb[0] >> 5) & 0x7) {
2479 /* computed by buff_encode_visit */
2490 * We should probably use csio_build_visit or something like that
2491 * here, but it's easier to encode arguments as you go. The
2492 * alternative would be skipping the CDB argument and then encoding
2493 * it here, since we've got the data buffer argument by now.
2495 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2497 cam_fill_csio(&ccb->csio,
2498 /*retries*/ retry_count,
2501 /*tag_action*/ MSG_SIMPLE_Q_TAG,
2502 /*data_ptr*/ data_ptr,
2503 /*dxfer_len*/ data_bytes,
2504 /*sense_len*/ SSD_FULL_SIZE,
2505 /*cdb_len*/ cdb_len,
2506 /*timeout*/ timeout ? timeout : 5000);
2509 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2511 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2513 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2515 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2517 cam_fill_ataio(&ccb->ataio,
2518 /*retries*/ retry_count,
2522 /*data_ptr*/ data_ptr,
2523 /*dxfer_len*/ data_bytes,
2524 /*timeout*/ timeout ? timeout : 5000);
2527 if (((retval = cam_send_ccb(device, ccb)) < 0)
2528 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2529 const char warnstr[] = "error sending command";
2536 if (arglist & CAM_ARG_VERBOSE) {
2537 cam_error_print(device, ccb, CAM_ESF_ALL,
2538 CAM_EPF_ALL, stderr);
2542 goto scsicmd_bailout;
2545 if (atacmd_len && need_res) {
2547 buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2549 fprintf(stdout, "\n");
2552 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2553 ccb->ataio.res.status,
2554 ccb->ataio.res.error,
2555 ccb->ataio.res.lba_low,
2556 ccb->ataio.res.lba_mid,
2557 ccb->ataio.res.lba_high,
2558 ccb->ataio.res.device,
2559 ccb->ataio.res.lba_low_exp,
2560 ccb->ataio.res.lba_mid_exp,
2561 ccb->ataio.res.lba_high_exp,
2562 ccb->ataio.res.sector_count,
2563 ccb->ataio.res.sector_count_exp);
2568 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2569 && (arglist & CAM_ARG_CMD_IN)
2570 && (data_bytes > 0)) {
2572 buff_decode_visit(data_ptr, data_bytes, datastr,
2574 fprintf(stdout, "\n");
2576 ssize_t amt_written;
2577 int amt_to_write = data_bytes;
2578 u_int8_t *buf_ptr = data_ptr;
2580 for (amt_written = 0; (amt_to_write > 0) &&
2581 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2582 amt_to_write -= amt_written;
2583 buf_ptr += amt_written;
2585 if (amt_written == -1) {
2586 warn("error writing data to stdout");
2588 goto scsicmd_bailout;
2589 } else if ((amt_written == 0)
2590 && (amt_to_write > 0)) {
2591 warnx("only wrote %u bytes out of %u",
2592 data_bytes - amt_to_write, data_bytes);
2599 if ((data_bytes > 0) && (data_ptr != NULL))
2608 camdebug(int argc, char **argv, char *combinedopt)
2611 int bus = -1, target = -1, lun = -1;
2612 char *tstr, *tmpstr = NULL;
2616 bzero(&ccb, sizeof(union ccb));
2618 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2621 arglist |= CAM_ARG_DEBUG_INFO;
2622 ccb.cdbg.flags |= CAM_DEBUG_INFO;
2625 arglist |= CAM_ARG_DEBUG_PERIPH;
2626 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2629 arglist |= CAM_ARG_DEBUG_SUBTRACE;
2630 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2633 arglist |= CAM_ARG_DEBUG_TRACE;
2634 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2637 arglist |= CAM_ARG_DEBUG_XPT;
2638 ccb.cdbg.flags |= CAM_DEBUG_XPT;
2641 arglist |= CAM_ARG_DEBUG_CDB;
2642 ccb.cdbg.flags |= CAM_DEBUG_CDB;
2645 arglist |= CAM_ARG_DEBUG_PROBE;
2646 ccb.cdbg.flags |= CAM_DEBUG_PROBE;
2653 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2654 warnx("error opening transport layer device %s", XPT_DEVICE);
2655 warn("%s", XPT_DEVICE);
2662 warnx("you must specify \"off\", \"all\" or a bus,");
2663 warnx("bus:target, or bus:target:lun");
2670 while (isspace(*tstr) && (*tstr != '\0'))
2673 if (strncmp(tstr, "off", 3) == 0) {
2674 ccb.cdbg.flags = CAM_DEBUG_NONE;
2675 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2676 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2677 CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
2678 } else if (strncmp(tstr, "all", 3) != 0) {
2679 tmpstr = (char *)strtok(tstr, ":");
2680 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2681 bus = strtol(tmpstr, NULL, 0);
2682 arglist |= CAM_ARG_BUS;
2683 tmpstr = (char *)strtok(NULL, ":");
2684 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2685 target = strtol(tmpstr, NULL, 0);
2686 arglist |= CAM_ARG_TARGET;
2687 tmpstr = (char *)strtok(NULL, ":");
2688 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2689 lun = strtol(tmpstr, NULL, 0);
2690 arglist |= CAM_ARG_LUN;
2695 warnx("you must specify \"all\", \"off\", or a bus,");
2696 warnx("bus:target, or bus:target:lun to debug");
2702 ccb.ccb_h.func_code = XPT_DEBUG;
2703 ccb.ccb_h.path_id = bus;
2704 ccb.ccb_h.target_id = target;
2705 ccb.ccb_h.target_lun = lun;
2707 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2708 warn("CAMIOCOMMAND ioctl failed");
2713 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2714 CAM_FUNC_NOTAVAIL) {
2715 warnx("CAM debugging not available");
2716 warnx("you need to put options CAMDEBUG in"
2717 " your kernel config file!");
2719 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2721 warnx("XPT_DEBUG CCB failed with status %#x",
2725 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2727 "Debugging turned off\n");
2730 "Debugging enabled for "
2743 tagcontrol(struct cam_device *device, int argc, char **argv,
2753 ccb = cam_getccb(device);
2756 warnx("tagcontrol: error allocating ccb");
2760 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2763 numtags = strtol(optarg, NULL, 0);
2765 warnx("tag count %d is < 0", numtags);
2767 goto tagcontrol_bailout;
2778 cam_path_string(device, pathstr, sizeof(pathstr));
2781 bzero(&(&ccb->ccb_h)[1],
2782 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2783 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2784 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
2785 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2786 ccb->crs.openings = numtags;
2789 if (cam_send_ccb(device, ccb) < 0) {
2790 perror("error sending XPT_REL_SIMQ CCB");
2792 goto tagcontrol_bailout;
2795 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2796 warnx("XPT_REL_SIMQ CCB failed");
2797 cam_error_print(device, ccb, CAM_ESF_ALL,
2798 CAM_EPF_ALL, stderr);
2800 goto tagcontrol_bailout;
2805 fprintf(stdout, "%stagged openings now %d\n",
2806 pathstr, ccb->crs.openings);
2809 bzero(&(&ccb->ccb_h)[1],
2810 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2812 ccb->ccb_h.func_code = XPT_GDEV_STATS;
2814 if (cam_send_ccb(device, ccb) < 0) {
2815 perror("error sending XPT_GDEV_STATS CCB");
2817 goto tagcontrol_bailout;
2820 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2821 warnx("XPT_GDEV_STATS CCB failed");
2822 cam_error_print(device, ccb, CAM_ESF_ALL,
2823 CAM_EPF_ALL, stderr);
2825 goto tagcontrol_bailout;
2828 if (arglist & CAM_ARG_VERBOSE) {
2829 fprintf(stdout, "%s", pathstr);
2830 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
2831 fprintf(stdout, "%s", pathstr);
2832 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
2833 fprintf(stdout, "%s", pathstr);
2834 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2835 fprintf(stdout, "%s", pathstr);
2836 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued);
2837 fprintf(stdout, "%s", pathstr);
2838 fprintf(stdout, "held %d\n", ccb->cgds.held);
2839 fprintf(stdout, "%s", pathstr);
2840 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
2841 fprintf(stdout, "%s", pathstr);
2842 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
2845 fprintf(stdout, "%s", pathstr);
2846 fprintf(stdout, "device openings: ");
2848 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2849 ccb->cgds.dev_active);
2859 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2863 cam_path_string(device, pathstr, sizeof(pathstr));
2865 if (cts->transport == XPORT_SPI) {
2866 struct ccb_trans_settings_spi *spi =
2867 &cts->xport_specific.spi;
2869 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2871 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2874 if (spi->sync_offset != 0) {
2877 freq = scsi_calc_syncsrate(spi->sync_period);
2878 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2879 pathstr, freq / 1000, freq % 1000);
2883 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2884 fprintf(stdout, "%soffset: %d\n", pathstr,
2888 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2889 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2890 (0x01 << spi->bus_width) * 8);
2893 if (spi->valid & CTS_SPI_VALID_DISC) {
2894 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2895 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2896 "enabled" : "disabled");
2899 if (cts->transport == XPORT_FC) {
2900 struct ccb_trans_settings_fc *fc =
2901 &cts->xport_specific.fc;
2903 if (fc->valid & CTS_FC_VALID_WWNN)
2904 fprintf(stdout, "%sWWNN: 0x%llx", pathstr,
2905 (long long) fc->wwnn);
2906 if (fc->valid & CTS_FC_VALID_WWPN)
2907 fprintf(stdout, "%sWWPN: 0x%llx", pathstr,
2908 (long long) fc->wwpn);
2909 if (fc->valid & CTS_FC_VALID_PORT)
2910 fprintf(stdout, "%sPortID: 0x%x", pathstr, fc->port);
2911 if (fc->valid & CTS_FC_VALID_SPEED)
2912 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2913 pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
2915 if (cts->transport == XPORT_SAS) {
2916 struct ccb_trans_settings_sas *sas =
2917 &cts->xport_specific.sas;
2919 if (sas->valid & CTS_SAS_VALID_SPEED)
2920 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2921 pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
2923 if (cts->transport == XPORT_ATA) {
2924 struct ccb_trans_settings_pata *pata =
2925 &cts->xport_specific.ata;
2927 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
2928 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2929 ata_mode2string(pata->mode));
2931 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2932 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2935 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2936 fprintf(stdout, "%sPIO transaction length: %d\n",
2937 pathstr, pata->bytecount);
2940 if (cts->transport == XPORT_SATA) {
2941 struct ccb_trans_settings_sata *sata =
2942 &cts->xport_specific.sata;
2944 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2945 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2948 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2949 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2950 ata_mode2string(sata->mode));
2952 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2953 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2956 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2957 fprintf(stdout, "%sPIO transaction length: %d\n",
2958 pathstr, sata->bytecount);
2960 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2961 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2964 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2965 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2968 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2969 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2973 if (cts->protocol == PROTO_ATA) {
2974 struct ccb_trans_settings_ata *ata=
2975 &cts->proto_specific.ata;
2977 if (ata->valid & CTS_ATA_VALID_TQ) {
2978 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
2979 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
2980 "enabled" : "disabled");
2983 if (cts->protocol == PROTO_SCSI) {
2984 struct ccb_trans_settings_scsi *scsi=
2985 &cts->proto_specific.scsi;
2987 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2988 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
2989 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2990 "enabled" : "disabled");
2997 * Get a path inquiry CCB for the specified device.
3000 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
3005 ccb = cam_getccb(device);
3007 warnx("get_cpi: couldn't allocate CCB");
3010 bzero(&(&ccb->ccb_h)[1],
3011 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3012 ccb->ccb_h.func_code = XPT_PATH_INQ;
3013 if (cam_send_ccb(device, ccb) < 0) {
3014 warn("get_cpi: error sending Path Inquiry CCB");
3015 if (arglist & CAM_ARG_VERBOSE)
3016 cam_error_print(device, ccb, CAM_ESF_ALL,
3017 CAM_EPF_ALL, stderr);
3019 goto get_cpi_bailout;
3021 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3022 if (arglist & CAM_ARG_VERBOSE)
3023 cam_error_print(device, ccb, CAM_ESF_ALL,
3024 CAM_EPF_ALL, stderr);
3026 goto get_cpi_bailout;
3028 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
3036 * Get a get device CCB for the specified device.
3039 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
3044 ccb = cam_getccb(device);
3046 warnx("get_cgd: couldn't allocate CCB");
3049 bzero(&(&ccb->ccb_h)[1],
3050 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3051 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
3052 if (cam_send_ccb(device, ccb) < 0) {
3053 warn("get_cgd: error sending Path Inquiry CCB");
3054 if (arglist & CAM_ARG_VERBOSE)
3055 cam_error_print(device, ccb, CAM_ESF_ALL,
3056 CAM_EPF_ALL, stderr);
3058 goto get_cgd_bailout;
3060 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3061 if (arglist & CAM_ARG_VERBOSE)
3062 cam_error_print(device, ccb, CAM_ESF_ALL,
3063 CAM_EPF_ALL, stderr);
3065 goto get_cgd_bailout;
3067 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3075 cpi_print(struct ccb_pathinq *cpi)
3077 char adapter_str[1024];
3080 snprintf(adapter_str, sizeof(adapter_str),
3081 "%s%d:", cpi->dev_name, cpi->unit_number);
3083 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3086 for (i = 1; i < 0xff; i = i << 1) {
3089 if ((i & cpi->hba_inquiry) == 0)
3092 fprintf(stdout, "%s supports ", adapter_str);
3096 str = "MDP message";
3099 str = "32 bit wide SCSI";
3102 str = "16 bit wide SCSI";
3105 str = "SDTR message";
3108 str = "linked CDBs";
3111 str = "tag queue messages";
3114 str = "soft reset alternative";
3117 str = "SATA Port Multiplier";
3120 str = "unknown PI bit set";
3123 fprintf(stdout, "%s\n", str);
3126 for (i = 1; i < 0xff; i = i << 1) {
3129 if ((i & cpi->hba_misc) == 0)
3132 fprintf(stdout, "%s ", adapter_str);
3136 str = "bus scans from high ID to low ID";
3139 str = "removable devices not included in scan";
3141 case PIM_NOINITIATOR:
3142 str = "initiator role not supported";
3144 case PIM_NOBUSRESET:
3145 str = "user has disabled initial BUS RESET or"
3146 " controller is in target/mixed mode";
3149 str = "do not send 6-byte commands";
3152 str = "scan bus sequentially";
3155 str = "unknown PIM bit set";
3158 fprintf(stdout, "%s\n", str);
3161 for (i = 1; i < 0xff; i = i << 1) {
3164 if ((i & cpi->target_sprt) == 0)
3167 fprintf(stdout, "%s supports ", adapter_str);
3170 str = "target mode processor mode";
3173 str = "target mode phase cog. mode";
3175 case PIT_DISCONNECT:
3176 str = "disconnects in target mode";
3179 str = "terminate I/O message in target mode";
3182 str = "group 6 commands in target mode";
3185 str = "group 7 commands in target mode";
3188 str = "unknown PIT bit set";
3192 fprintf(stdout, "%s\n", str);
3194 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3196 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3198 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3200 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3201 adapter_str, cpi->hpath_id);
3202 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3204 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3205 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3206 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
3207 adapter_str, cpi->hba_vendor);
3208 fprintf(stdout, "%s HBA device ID: 0x%04x\n",
3209 adapter_str, cpi->hba_device);
3210 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
3211 adapter_str, cpi->hba_subvendor);
3212 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
3213 adapter_str, cpi->hba_subdevice);
3214 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3215 fprintf(stdout, "%s base transfer speed: ", adapter_str);
3216 if (cpi->base_transfer_speed > 1000)
3217 fprintf(stdout, "%d.%03dMB/sec\n",
3218 cpi->base_transfer_speed / 1000,
3219 cpi->base_transfer_speed % 1000);
3221 fprintf(stdout, "%dKB/sec\n",
3222 (cpi->base_transfer_speed % 1000) * 1000);
3223 fprintf(stdout, "%s maximum transfer size: %u bytes\n",
3224 adapter_str, cpi->maxio);
3228 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3229 struct ccb_trans_settings *cts)
3235 ccb = cam_getccb(device);
3238 warnx("get_print_cts: error allocating ccb");
3242 bzero(&(&ccb->ccb_h)[1],
3243 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3245 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3247 if (user_settings == 0)
3248 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3250 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3252 if (cam_send_ccb(device, ccb) < 0) {
3253 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3254 if (arglist & CAM_ARG_VERBOSE)
3255 cam_error_print(device, ccb, CAM_ESF_ALL,
3256 CAM_EPF_ALL, stderr);
3258 goto get_print_cts_bailout;
3261 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3262 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3263 if (arglist & CAM_ARG_VERBOSE)
3264 cam_error_print(device, ccb, CAM_ESF_ALL,
3265 CAM_EPF_ALL, stderr);
3267 goto get_print_cts_bailout;
3271 cts_print(device, &ccb->cts);
3274 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3276 get_print_cts_bailout:
3284 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3285 int argc, char **argv, char *combinedopt)
3289 int user_settings = 0;
3291 int disc_enable = -1, tag_enable = -1;
3294 double syncrate = -1;
3297 int change_settings = 0, send_tur = 0;
3298 struct ccb_pathinq cpi;
3300 ccb = cam_getccb(device);
3302 warnx("ratecontrol: error allocating ccb");
3305 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3314 if (strncasecmp(optarg, "enable", 6) == 0)
3316 else if (strncasecmp(optarg, "disable", 7) == 0)
3319 warnx("-D argument \"%s\" is unknown", optarg);
3321 goto ratecontrol_bailout;
3323 change_settings = 1;
3326 mode = ata_string2mode(optarg);
3328 warnx("unknown mode '%s'", optarg);
3330 goto ratecontrol_bailout;
3332 change_settings = 1;
3335 offset = strtol(optarg, NULL, 0);
3337 warnx("offset value %d is < 0", offset);
3339 goto ratecontrol_bailout;
3341 change_settings = 1;
3347 syncrate = atof(optarg);
3349 warnx("sync rate %f is < 0", syncrate);
3351 goto ratecontrol_bailout;
3353 change_settings = 1;
3356 if (strncasecmp(optarg, "enable", 6) == 0)
3358 else if (strncasecmp(optarg, "disable", 7) == 0)
3361 warnx("-T argument \"%s\" is unknown", optarg);
3363 goto ratecontrol_bailout;
3365 change_settings = 1;
3371 bus_width = strtol(optarg, NULL, 0);
3372 if (bus_width < 0) {
3373 warnx("bus width %d is < 0", bus_width);
3375 goto ratecontrol_bailout;
3377 change_settings = 1;
3383 bzero(&(&ccb->ccb_h)[1],
3384 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3386 * Grab path inquiry information, so we can determine whether
3387 * or not the initiator is capable of the things that the user
3390 ccb->ccb_h.func_code = XPT_PATH_INQ;
3391 if (cam_send_ccb(device, ccb) < 0) {
3392 perror("error sending XPT_PATH_INQ CCB");
3393 if (arglist & CAM_ARG_VERBOSE) {
3394 cam_error_print(device, ccb, CAM_ESF_ALL,
3395 CAM_EPF_ALL, stderr);
3398 goto ratecontrol_bailout;
3400 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3401 warnx("XPT_PATH_INQ CCB failed");
3402 if (arglist & CAM_ARG_VERBOSE) {
3403 cam_error_print(device, ccb, CAM_ESF_ALL,
3404 CAM_EPF_ALL, stderr);
3407 goto ratecontrol_bailout;
3409 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3410 bzero(&(&ccb->ccb_h)[1],
3411 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3413 fprintf(stdout, "%s parameters:\n",
3414 user_settings ? "User" : "Current");
3416 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3418 goto ratecontrol_bailout;
3420 if (arglist & CAM_ARG_VERBOSE)
3423 if (change_settings) {
3424 int didsettings = 0;
3425 struct ccb_trans_settings_spi *spi = NULL;
3426 struct ccb_trans_settings_pata *pata = NULL;
3427 struct ccb_trans_settings_sata *sata = NULL;
3428 struct ccb_trans_settings_ata *ata = NULL;
3429 struct ccb_trans_settings_scsi *scsi = NULL;
3431 if (ccb->cts.transport == XPORT_SPI)
3432 spi = &ccb->cts.xport_specific.spi;
3433 if (ccb->cts.transport == XPORT_ATA)
3434 pata = &ccb->cts.xport_specific.ata;
3435 if (ccb->cts.transport == XPORT_SATA)
3436 sata = &ccb->cts.xport_specific.sata;
3437 if (ccb->cts.protocol == PROTO_ATA)
3438 ata = &ccb->cts.proto_specific.ata;
3439 if (ccb->cts.protocol == PROTO_SCSI)
3440 scsi = &ccb->cts.proto_specific.scsi;
3441 ccb->cts.xport_specific.valid = 0;
3442 ccb->cts.proto_specific.valid = 0;
3443 if (spi && disc_enable != -1) {
3444 spi->valid |= CTS_SPI_VALID_DISC;
3445 if (disc_enable == 0)
3446 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3448 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3451 if (tag_enable != -1) {
3452 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3453 warnx("HBA does not support tagged queueing, "
3454 "so you cannot modify tag settings");
3456 goto ratecontrol_bailout;
3459 ata->valid |= CTS_SCSI_VALID_TQ;
3460 if (tag_enable == 0)
3461 ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
3463 ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
3466 scsi->valid |= CTS_SCSI_VALID_TQ;
3467 if (tag_enable == 0)
3468 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3470 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3474 if (spi && offset != -1) {
3475 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3476 warnx("HBA is not capable of changing offset");
3478 goto ratecontrol_bailout;
3480 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3481 spi->sync_offset = offset;
3484 if (spi && syncrate != -1) {
3485 int prelim_sync_period;
3487 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3488 warnx("HBA is not capable of changing "
3491 goto ratecontrol_bailout;
3493 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3495 * The sync rate the user gives us is in MHz.
3496 * We need to translate it into KHz for this
3501 * Next, we calculate a "preliminary" sync period
3502 * in tenths of a nanosecond.
3505 prelim_sync_period = 0;
3507 prelim_sync_period = 10000000 / syncrate;
3509 scsi_calc_syncparam(prelim_sync_period);
3512 if (sata && syncrate != -1) {
3513 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3514 warnx("HBA is not capable of changing "
3517 goto ratecontrol_bailout;
3519 if (!user_settings) {
3520 warnx("You can modify only user rate "
3521 "settings for SATA");
3523 goto ratecontrol_bailout;
3525 sata->revision = ata_speed2revision(syncrate * 100);
3526 if (sata->revision < 0) {
3527 warnx("Invalid rate %f", syncrate);
3529 goto ratecontrol_bailout;
3531 sata->valid |= CTS_SATA_VALID_REVISION;
3534 if ((pata || sata) && mode != -1) {
3535 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3536 warnx("HBA is not capable of changing "
3539 goto ratecontrol_bailout;
3541 if (!user_settings) {
3542 warnx("You can modify only user mode "
3543 "settings for ATA/SATA");
3545 goto ratecontrol_bailout;
3549 pata->valid |= CTS_ATA_VALID_MODE;
3552 sata->valid |= CTS_SATA_VALID_MODE;
3557 * The bus_width argument goes like this:
3561 * Therefore, if you shift the number of bits given on the
3562 * command line right by 4, you should get the correct
3565 if (spi && bus_width != -1) {
3567 * We might as well validate things here with a
3568 * decipherable error message, rather than what
3569 * will probably be an indecipherable error message
3570 * by the time it gets back to us.
3572 if ((bus_width == 16)
3573 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3574 warnx("HBA does not support 16 bit bus width");
3576 goto ratecontrol_bailout;
3577 } else if ((bus_width == 32)
3578 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3579 warnx("HBA does not support 32 bit bus width");
3581 goto ratecontrol_bailout;
3582 } else if ((bus_width != 8)
3583 && (bus_width != 16)
3584 && (bus_width != 32)) {
3585 warnx("Invalid bus width %d", bus_width);
3587 goto ratecontrol_bailout;
3589 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3590 spi->bus_width = bus_width >> 4;
3593 if (didsettings == 0) {
3594 goto ratecontrol_bailout;
3596 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3597 if (cam_send_ccb(device, ccb) < 0) {
3598 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3599 if (arglist & CAM_ARG_VERBOSE) {
3600 cam_error_print(device, ccb, CAM_ESF_ALL,
3601 CAM_EPF_ALL, stderr);
3604 goto ratecontrol_bailout;
3606 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3607 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3608 if (arglist & CAM_ARG_VERBOSE) {
3609 cam_error_print(device, ccb, CAM_ESF_ALL,
3610 CAM_EPF_ALL, stderr);
3613 goto ratecontrol_bailout;
3617 retval = testunitready(device, retry_count, timeout,
3618 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3620 * If the TUR didn't succeed, just bail.
3624 fprintf(stderr, "Test Unit Ready failed\n");
3625 goto ratecontrol_bailout;
3628 if ((change_settings || send_tur) && !quiet &&
3629 (ccb->cts.transport == XPORT_ATA ||
3630 ccb->cts.transport == XPORT_SATA || send_tur)) {
3631 fprintf(stdout, "New parameters:\n");
3632 retval = get_print_cts(device, user_settings, 0, NULL);
3635 ratecontrol_bailout:
3641 scsiformat(struct cam_device *device, int argc, char **argv,
3642 char *combinedopt, int retry_count, int timeout)
3646 int ycount = 0, quiet = 0;
3647 int error = 0, response = 0, retval = 0;
3648 int use_timeout = 10800 * 1000;
3650 struct format_defect_list_header fh;
3651 u_int8_t *data_ptr = NULL;
3652 u_int32_t dxfer_len = 0;
3654 int num_warnings = 0;
3657 ccb = cam_getccb(device);
3660 warnx("scsiformat: error allocating ccb");
3664 bzero(&(&ccb->ccb_h)[1],
3665 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3667 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3688 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3689 "following device:\n");
3691 error = scsidoinquiry(device, argc, argv, combinedopt,
3692 retry_count, timeout);
3695 warnx("scsiformat: error sending inquiry");
3696 goto scsiformat_bailout;
3705 fprintf(stdout, "Are you SURE you want to do "
3708 if (fgets(str, sizeof(str), stdin) != NULL) {
3710 if (strncasecmp(str, "yes", 3) == 0)
3712 else if (strncasecmp(str, "no", 2) == 0)
3715 fprintf(stdout, "Please answer"
3716 " \"yes\" or \"no\"\n");
3719 } while (response == 0);
3721 if (response == -1) {
3723 goto scsiformat_bailout;
3728 use_timeout = timeout;
3731 fprintf(stdout, "Current format timeout is %d seconds\n",
3732 use_timeout / 1000);
3736 * If the user hasn't disabled questions and didn't specify a
3737 * timeout on the command line, ask them if they want the current
3741 && (timeout == 0)) {
3743 int new_timeout = 0;
3745 fprintf(stdout, "Enter new timeout in seconds or press\n"
3746 "return to keep the current timeout [%d] ",
3747 use_timeout / 1000);
3749 if (fgets(str, sizeof(str), stdin) != NULL) {
3751 new_timeout = atoi(str);
3754 if (new_timeout != 0) {
3755 use_timeout = new_timeout * 1000;
3756 fprintf(stdout, "Using new timeout value %d\n",
3757 use_timeout / 1000);
3762 * Keep this outside the if block below to silence any unused
3763 * variable warnings.
3765 bzero(&fh, sizeof(fh));
3768 * If we're in immediate mode, we've got to include the format
3771 if (immediate != 0) {
3772 fh.byte2 = FU_DLH_IMMED;
3773 data_ptr = (u_int8_t *)&fh;
3774 dxfer_len = sizeof(fh);
3775 byte2 = FU_FMT_DATA;
3776 } else if (quiet == 0) {
3777 fprintf(stdout, "Formatting...");
3781 scsi_format_unit(&ccb->csio,
3782 /* retries */ retry_count,
3784 /* tag_action */ MSG_SIMPLE_Q_TAG,
3787 /* data_ptr */ data_ptr,
3788 /* dxfer_len */ dxfer_len,
3789 /* sense_len */ SSD_FULL_SIZE,
3790 /* timeout */ use_timeout);
3792 /* Disable freezing the device queue */
3793 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3795 if (arglist & CAM_ARG_ERR_RECOVER)
3796 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3798 if (((retval = cam_send_ccb(device, ccb)) < 0)
3799 || ((immediate == 0)
3800 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3801 const char errstr[] = "error sending format command";
3808 if (arglist & CAM_ARG_VERBOSE) {
3809 cam_error_print(device, ccb, CAM_ESF_ALL,
3810 CAM_EPF_ALL, stderr);
3813 goto scsiformat_bailout;
3817 * If we ran in non-immediate mode, we already checked for errors
3818 * above and printed out any necessary information. If we're in
3819 * immediate mode, we need to loop through and get status
3820 * information periodically.
3822 if (immediate == 0) {
3824 fprintf(stdout, "Format Complete\n");
3826 goto scsiformat_bailout;
3833 bzero(&(&ccb->ccb_h)[1],
3834 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3837 * There's really no need to do error recovery or
3838 * retries here, since we're just going to sit in a
3839 * loop and wait for the device to finish formatting.
3841 scsi_test_unit_ready(&ccb->csio,
3844 /* tag_action */ MSG_SIMPLE_Q_TAG,
3845 /* sense_len */ SSD_FULL_SIZE,
3846 /* timeout */ 5000);
3848 /* Disable freezing the device queue */
3849 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3851 retval = cam_send_ccb(device, ccb);
3854 * If we get an error from the ioctl, bail out. SCSI
3855 * errors are expected.
3858 warn("error sending CAMIOCOMMAND ioctl");
3859 if (arglist & CAM_ARG_VERBOSE) {
3860 cam_error_print(device, ccb, CAM_ESF_ALL,
3861 CAM_EPF_ALL, stderr);
3864 goto scsiformat_bailout;
3867 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3869 if ((status != CAM_REQ_CMP)
3870 && (status == CAM_SCSI_STATUS_ERROR)
3871 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3872 struct scsi_sense_data *sense;
3873 int error_code, sense_key, asc, ascq;
3875 sense = &ccb->csio.sense_data;
3876 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3877 ccb->csio.sense_resid, &error_code, &sense_key,
3878 &asc, &ascq, /*show_errors*/ 1);
3881 * According to the SCSI-2 and SCSI-3 specs, a
3882 * drive that is in the middle of a format should
3883 * return NOT READY with an ASC of "logical unit
3884 * not ready, format in progress". The sense key
3885 * specific bytes will then be a progress indicator.
3887 if ((sense_key == SSD_KEY_NOT_READY)
3888 && (asc == 0x04) && (ascq == 0x04)) {
3891 if ((scsi_get_sks(sense, ccb->csio.sense_len -
3892 ccb->csio.sense_resid, sks) == 0)
3895 u_int64_t percentage;
3897 val = scsi_2btoul(&sks[1]);
3898 percentage = 10000 * val;
3901 "\rFormatting: %ju.%02u %% "
3903 (uintmax_t)(percentage /
3905 (unsigned)((percentage /
3909 } else if ((quiet == 0)
3910 && (++num_warnings <= 1)) {
3911 warnx("Unexpected SCSI Sense Key "
3912 "Specific value returned "
3914 scsi_sense_print(device, &ccb->csio,
3916 warnx("Unable to print status "
3917 "information, but format will "
3919 warnx("will exit when format is "
3924 warnx("Unexpected SCSI error during format");
3925 cam_error_print(device, ccb, CAM_ESF_ALL,
3926 CAM_EPF_ALL, stderr);
3928 goto scsiformat_bailout;
3931 } else if (status != CAM_REQ_CMP) {
3932 warnx("Unexpected CAM status %#x", status);
3933 if (arglist & CAM_ARG_VERBOSE)
3934 cam_error_print(device, ccb, CAM_ESF_ALL,
3935 CAM_EPF_ALL, stderr);
3937 goto scsiformat_bailout;
3940 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3943 fprintf(stdout, "\nFormat Complete\n");
3953 scsireportluns(struct cam_device *device, int argc, char **argv,
3954 char *combinedopt, int retry_count, int timeout)
3957 int c, countonly, lunsonly;
3958 struct scsi_report_luns_data *lundata;
3960 uint8_t report_type;
3961 uint32_t list_len, i, j;
3966 report_type = RPL_REPORT_DEFAULT;
3967 ccb = cam_getccb(device);
3970 warnx("%s: error allocating ccb", __func__);
3974 bzero(&(&ccb->ccb_h)[1],
3975 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3980 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3989 if (strcasecmp(optarg, "default") == 0)
3990 report_type = RPL_REPORT_DEFAULT;
3991 else if (strcasecmp(optarg, "wellknown") == 0)
3992 report_type = RPL_REPORT_WELLKNOWN;
3993 else if (strcasecmp(optarg, "all") == 0)
3994 report_type = RPL_REPORT_ALL;
3996 warnx("%s: invalid report type \"%s\"",
4007 if ((countonly != 0)
4008 && (lunsonly != 0)) {
4009 warnx("%s: you can only specify one of -c or -l", __func__);
4014 * According to SPC-4, the allocation length must be at least 16
4015 * bytes -- enough for the header and one LUN.
4017 alloc_len = sizeof(*lundata) + 8;
4021 lundata = malloc(alloc_len);
4023 if (lundata == NULL) {
4024 warn("%s: error mallocing %d bytes", __func__, alloc_len);
4029 scsi_report_luns(&ccb->csio,
4030 /*retries*/ retry_count,
4032 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4033 /*select_report*/ report_type,
4034 /*rpl_buf*/ lundata,
4035 /*alloc_len*/ alloc_len,
4036 /*sense_len*/ SSD_FULL_SIZE,
4037 /*timeout*/ timeout ? timeout : 5000);
4039 /* Disable freezing the device queue */
4040 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4042 if (arglist & CAM_ARG_ERR_RECOVER)
4043 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4045 if (cam_send_ccb(device, ccb) < 0) {
4046 warn("error sending REPORT LUNS command");
4048 if (arglist & CAM_ARG_VERBOSE)
4049 cam_error_print(device, ccb, CAM_ESF_ALL,
4050 CAM_EPF_ALL, stderr);
4056 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4057 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4063 list_len = scsi_4btoul(lundata->length);
4066 * If we need to list the LUNs, and our allocation
4067 * length was too short, reallocate and retry.
4069 if ((countonly == 0)
4070 && (list_len > (alloc_len - sizeof(*lundata)))) {
4071 alloc_len = list_len + sizeof(*lundata);
4077 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
4078 ((list_len / 8) > 1) ? "s" : "");
4083 for (i = 0; i < (list_len / 8); i++) {
4087 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4089 fprintf(stdout, ",");
4090 switch (lundata->luns[i].lundata[j] &
4091 RPL_LUNDATA_ATYP_MASK) {
4092 case RPL_LUNDATA_ATYP_PERIPH:
4093 if ((lundata->luns[i].lundata[j] &
4094 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4095 fprintf(stdout, "%d:",
4096 lundata->luns[i].lundata[j] &
4097 RPL_LUNDATA_PERIPH_BUS_MASK);
4099 && ((lundata->luns[i].lundata[j+2] &
4100 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4103 fprintf(stdout, "%d",
4104 lundata->luns[i].lundata[j+1]);
4106 case RPL_LUNDATA_ATYP_FLAT: {
4108 tmplun[0] = lundata->luns[i].lundata[j] &
4109 RPL_LUNDATA_FLAT_LUN_MASK;
4110 tmplun[1] = lundata->luns[i].lundata[j+1];
4112 fprintf(stdout, "%d", scsi_2btoul(tmplun));
4116 case RPL_LUNDATA_ATYP_LUN:
4117 fprintf(stdout, "%d:%d:%d",
4118 (lundata->luns[i].lundata[j+1] &
4119 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4120 lundata->luns[i].lundata[j] &
4121 RPL_LUNDATA_LUN_TARG_MASK,
4122 lundata->luns[i].lundata[j+1] &
4123 RPL_LUNDATA_LUN_LUN_MASK);
4125 case RPL_LUNDATA_ATYP_EXTLUN: {
4126 int field_len_code, eam_code;
4128 eam_code = lundata->luns[i].lundata[j] &
4129 RPL_LUNDATA_EXT_EAM_MASK;
4130 field_len_code = (lundata->luns[i].lundata[j] &
4131 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4133 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4134 && (field_len_code == 0x00)) {
4135 fprintf(stdout, "%d",
4136 lundata->luns[i].lundata[j+1]);
4137 } else if ((eam_code ==
4138 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4139 && (field_len_code == 0x03)) {
4143 * This format takes up all 8 bytes.
4144 * If we aren't starting at offset 0,
4148 fprintf(stdout, "Invalid "
4151 "specified format", j);
4155 bzero(tmp_lun, sizeof(tmp_lun));
4156 bcopy(&lundata->luns[i].lundata[j+1],
4157 &tmp_lun[1], sizeof(tmp_lun) - 1);
4158 fprintf(stdout, "%#jx",
4159 (intmax_t)scsi_8btou64(tmp_lun));
4162 fprintf(stderr, "Unknown Extended LUN"
4163 "Address method %#x, length "
4164 "code %#x", eam_code,
4171 fprintf(stderr, "Unknown LUN address method "
4172 "%#x\n", lundata->luns[i].lundata[0] &
4173 RPL_LUNDATA_ATYP_MASK);
4177 * For the flat addressing method, there are no
4178 * other levels after it.
4183 fprintf(stdout, "\n");
4196 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4197 char *combinedopt, int retry_count, int timeout)
4200 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4201 struct scsi_read_capacity_data rcap;
4202 struct scsi_read_capacity_data_long rcaplong;
4216 ccb = cam_getccb(device);
4219 warnx("%s: error allocating ccb", __func__);
4223 bzero(&(&ccb->ccb_h)[1],
4224 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4226 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4253 if ((blocksizeonly != 0)
4254 && (numblocks != 0)) {
4255 warnx("%s: you can only specify one of -b or -N", __func__);
4260 if ((blocksizeonly != 0)
4261 && (sizeonly != 0)) {
4262 warnx("%s: you can only specify one of -b or -s", __func__);
4269 warnx("%s: you can only specify one of -h/-H or -q", __func__);
4275 && (blocksizeonly != 0)) {
4276 warnx("%s: you can only specify one of -h/-H or -b", __func__);
4281 scsi_read_capacity(&ccb->csio,
4282 /*retries*/ retry_count,
4284 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4287 /*timeout*/ timeout ? timeout : 5000);
4289 /* Disable freezing the device queue */
4290 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4292 if (arglist & CAM_ARG_ERR_RECOVER)
4293 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4295 if (cam_send_ccb(device, ccb) < 0) {
4296 warn("error sending READ CAPACITY command");
4298 if (arglist & CAM_ARG_VERBOSE)
4299 cam_error_print(device, ccb, CAM_ESF_ALL,
4300 CAM_EPF_ALL, stderr);
4306 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4307 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4312 maxsector = scsi_4btoul(rcap.addr);
4313 block_len = scsi_4btoul(rcap.length);
4316 * A last block of 2^32-1 means that the true capacity is over 2TB,
4317 * and we need to issue the long READ CAPACITY to get the real
4318 * capacity. Otherwise, we're all set.
4320 if (maxsector != 0xffffffff)
4323 scsi_read_capacity_16(&ccb->csio,
4324 /*retries*/ retry_count,
4326 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4331 /*sense_len*/ SSD_FULL_SIZE,
4332 /*timeout*/ timeout ? timeout : 5000);
4334 /* Disable freezing the device queue */
4335 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4337 if (arglist & CAM_ARG_ERR_RECOVER)
4338 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4340 if (cam_send_ccb(device, ccb) < 0) {
4341 warn("error sending READ CAPACITY (16) command");
4343 if (arglist & CAM_ARG_VERBOSE)
4344 cam_error_print(device, ccb, CAM_ESF_ALL,
4345 CAM_EPF_ALL, stderr);
4351 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4352 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4357 maxsector = scsi_8btou64(rcaplong.addr);
4358 block_len = scsi_4btoul(rcaplong.length);
4361 if (blocksizeonly == 0) {
4363 * Humanize implies !quiet, and also implies numblocks.
4365 if (humanize != 0) {
4370 tmpbytes = (maxsector + 1) * block_len;
4371 ret = humanize_number(tmpstr, sizeof(tmpstr),
4372 tmpbytes, "", HN_AUTOSCALE,
4375 HN_DIVISOR_1000 : 0));
4377 warnx("%s: humanize_number failed!", __func__);
4381 fprintf(stdout, "Device Size: %s%s", tmpstr,
4382 (sizeonly == 0) ? ", " : "\n");
4383 } else if (numblocks != 0) {
4384 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4385 "Blocks: " : "", (uintmax_t)maxsector + 1,
4386 (sizeonly == 0) ? ", " : "\n");
4388 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4389 "Last Block: " : "", (uintmax_t)maxsector,
4390 (sizeonly == 0) ? ", " : "\n");
4394 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4395 "Block Length: " : "", block_len, (quiet == 0) ?
4404 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4405 int retry_count, int timeout)
4409 uint8_t *smp_request = NULL, *smp_response = NULL;
4410 int request_size = 0, response_size = 0;
4411 int fd_request = 0, fd_response = 0;
4412 char *datastr = NULL;
4413 struct get_hook hook;
4418 * Note that at the moment we don't support sending SMP CCBs to
4419 * devices that aren't probed by CAM.
4421 ccb = cam_getccb(device);
4423 warnx("%s: error allocating CCB", __func__);
4427 bzero(&(&ccb->ccb_h)[1],
4428 sizeof(union ccb) - sizeof(struct ccb_hdr));
4430 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4433 arglist |= CAM_ARG_CMD_IN;
4434 response_size = strtol(optarg, NULL, 0);
4435 if (response_size <= 0) {
4436 warnx("invalid number of response bytes %d",
4439 goto smpcmd_bailout;
4441 hook.argc = argc - optind;
4442 hook.argv = argv + optind;
4445 datastr = cget(&hook, NULL);
4447 * If the user supplied "-" instead of a format, he
4448 * wants the data to be written to stdout.
4450 if ((datastr != NULL)
4451 && (datastr[0] == '-'))
4454 smp_response = (u_int8_t *)malloc(response_size);
4455 if (smp_response == NULL) {
4456 warn("can't malloc memory for SMP response");
4458 goto smpcmd_bailout;
4462 arglist |= CAM_ARG_CMD_OUT;
4463 request_size = strtol(optarg, NULL, 0);
4464 if (request_size <= 0) {
4465 warnx("invalid number of request bytes %d",
4468 goto smpcmd_bailout;
4470 hook.argc = argc - optind;
4471 hook.argv = argv + optind;
4473 datastr = cget(&hook, NULL);
4474 smp_request = (u_int8_t *)malloc(request_size);
4475 if (smp_request == NULL) {
4476 warn("can't malloc memory for SMP request");
4478 goto smpcmd_bailout;
4480 bzero(smp_request, request_size);
4482 * If the user supplied "-" instead of a format, he
4483 * wants the data to be read from stdin.
4485 if ((datastr != NULL)
4486 && (datastr[0] == '-'))
4489 buff_encode_visit(smp_request, request_size,
4500 * If fd_data is set, and we're writing to the device, we need to
4501 * read the data the user wants written from stdin.
4503 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4505 int amt_to_read = request_size;
4506 u_int8_t *buf_ptr = smp_request;
4508 for (amt_read = 0; amt_to_read > 0;
4509 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4510 if (amt_read == -1) {
4511 warn("error reading data from stdin");
4513 goto smpcmd_bailout;
4515 amt_to_read -= amt_read;
4516 buf_ptr += amt_read;
4520 if (((arglist & CAM_ARG_CMD_IN) == 0)
4521 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
4522 warnx("%s: need both the request (-r) and response (-R) "
4523 "arguments", __func__);
4525 goto smpcmd_bailout;
4528 flags |= CAM_DEV_QFRZDIS;
4530 cam_fill_smpio(&ccb->smpio,
4531 /*retries*/ retry_count,
4534 /*smp_request*/ smp_request,
4535 /*smp_request_len*/ request_size,
4536 /*smp_response*/ smp_response,
4537 /*smp_response_len*/ response_size,
4538 /*timeout*/ timeout ? timeout : 5000);
4540 ccb->smpio.flags = SMP_FLAG_NONE;
4542 if (((retval = cam_send_ccb(device, ccb)) < 0)
4543 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4544 const char warnstr[] = "error sending command";
4551 if (arglist & CAM_ARG_VERBOSE) {
4552 cam_error_print(device, ccb, CAM_ESF_ALL,
4553 CAM_EPF_ALL, stderr);
4557 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4558 && (response_size > 0)) {
4559 if (fd_response == 0) {
4560 buff_decode_visit(smp_response, response_size,
4561 datastr, arg_put, NULL);
4562 fprintf(stdout, "\n");
4564 ssize_t amt_written;
4565 int amt_to_write = response_size;
4566 u_int8_t *buf_ptr = smp_response;
4568 for (amt_written = 0; (amt_to_write > 0) &&
4569 (amt_written = write(STDOUT_FILENO, buf_ptr,
4570 amt_to_write)) > 0;){
4571 amt_to_write -= amt_written;
4572 buf_ptr += amt_written;
4574 if (amt_written == -1) {
4575 warn("error writing data to stdout");
4577 goto smpcmd_bailout;
4578 } else if ((amt_written == 0)
4579 && (amt_to_write > 0)) {
4580 warnx("only wrote %u bytes out of %u",
4581 response_size - amt_to_write,
4590 if (smp_request != NULL)
4593 if (smp_response != NULL)
4600 smpreportgeneral(struct cam_device *device, int argc, char **argv,
4601 char *combinedopt, int retry_count, int timeout)
4604 struct smp_report_general_request *request = NULL;
4605 struct smp_report_general_response *response = NULL;
4606 struct sbuf *sb = NULL;
4608 int c, long_response = 0;
4612 * Note that at the moment we don't support sending SMP CCBs to
4613 * devices that aren't probed by CAM.
4615 ccb = cam_getccb(device);
4617 warnx("%s: error allocating CCB", __func__);
4621 bzero(&(&ccb->ccb_h)[1],
4622 sizeof(union ccb) - sizeof(struct ccb_hdr));
4624 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4633 request = malloc(sizeof(*request));
4634 if (request == NULL) {
4635 warn("%s: unable to allocate %zd bytes", __func__,
4641 response = malloc(sizeof(*response));
4642 if (response == NULL) {
4643 warn("%s: unable to allocate %zd bytes", __func__,
4650 smp_report_general(&ccb->smpio,
4654 /*request_len*/ sizeof(*request),
4655 (uint8_t *)response,
4656 /*response_len*/ sizeof(*response),
4657 /*long_response*/ long_response,
4660 if (((retval = cam_send_ccb(device, ccb)) < 0)
4661 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4662 const char warnstr[] = "error sending command";
4669 if (arglist & CAM_ARG_VERBOSE) {
4670 cam_error_print(device, ccb, CAM_ESF_ALL,
4671 CAM_EPF_ALL, stderr);
4678 * If the device supports the long response bit, try again and see
4679 * if we can get all of the data.
4681 if ((response->long_response & SMP_RG_LONG_RESPONSE)
4682 && (long_response == 0)) {
4683 ccb->ccb_h.status = CAM_REQ_INPROG;
4684 bzero(&(&ccb->ccb_h)[1],
4685 sizeof(union ccb) - sizeof(struct ccb_hdr));
4691 * XXX KDM detect and decode SMP errors here.
4693 sb = sbuf_new_auto();
4695 warnx("%s: error allocating sbuf", __func__);
4699 smp_report_general_sbuf(response, sizeof(*response), sb);
4703 printf("%s", sbuf_data(sb));
4709 if (request != NULL)
4712 if (response != NULL)
4721 struct camcontrol_opts phy_ops[] = {
4722 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
4723 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
4724 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
4725 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
4726 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
4727 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
4728 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
4729 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
4730 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
4735 smpphycontrol(struct cam_device *device, int argc, char **argv,
4736 char *combinedopt, int retry_count, int timeout)
4739 struct smp_phy_control_request *request = NULL;
4740 struct smp_phy_control_response *response = NULL;
4741 int long_response = 0;
4744 uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
4746 uint64_t attached_dev_name = 0;
4747 int dev_name_set = 0;
4748 uint32_t min_plr = 0, max_plr = 0;
4749 uint32_t pp_timeout_val = 0;
4750 int slumber_partial = 0;
4751 int set_pp_timeout_val = 0;
4755 * Note that at the moment we don't support sending SMP CCBs to
4756 * devices that aren't probed by CAM.
4758 ccb = cam_getccb(device);
4760 warnx("%s: error allocating CCB", __func__);
4764 bzero(&(&ccb->ccb_h)[1],
4765 sizeof(union ccb) - sizeof(struct ccb_hdr));
4767 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4775 if (strcasecmp(optarg, "enable") == 0)
4777 else if (strcasecmp(optarg, "disable") == 0)
4780 warnx("%s: Invalid argument %s", __func__,
4787 slumber_partial |= enable <<
4788 SMP_PC_SAS_SLUMBER_SHIFT;
4791 slumber_partial |= enable <<
4792 SMP_PC_SAS_PARTIAL_SHIFT;
4795 slumber_partial |= enable <<
4796 SMP_PC_SATA_SLUMBER_SHIFT;
4799 slumber_partial |= enable <<
4800 SMP_PC_SATA_PARTIAL_SHIFT;
4803 warnx("%s: programmer error", __func__);
4806 break; /*NOTREACHED*/
4811 attached_dev_name = (uintmax_t)strtoumax(optarg,
4820 * We don't do extensive checking here, so this
4821 * will continue to work when new speeds come out.
4823 min_plr = strtoul(optarg, NULL, 0);
4825 || (min_plr > 0xf)) {
4826 warnx("%s: invalid link rate %x",
4834 * We don't do extensive checking here, so this
4835 * will continue to work when new speeds come out.
4837 max_plr = strtoul(optarg, NULL, 0);
4839 || (max_plr > 0xf)) {
4840 warnx("%s: invalid link rate %x",
4847 camcontrol_optret optreturn;
4848 cam_argmask argnums;
4851 if (phy_op_set != 0) {
4852 warnx("%s: only one phy operation argument "
4853 "(-o) allowed", __func__);
4861 * Allow the user to specify the phy operation
4862 * numerically, as well as with a name. This will
4863 * future-proof it a bit, so options that are added
4864 * in future specs can be used.
4866 if (isdigit(optarg[0])) {
4867 phy_operation = strtoul(optarg, NULL, 0);
4868 if ((phy_operation == 0)
4869 || (phy_operation > 0xff)) {
4870 warnx("%s: invalid phy operation %#x",
4871 __func__, phy_operation);
4877 optreturn = getoption(phy_ops, optarg, &phy_operation,
4880 if (optreturn == CC_OR_AMBIGUOUS) {
4881 warnx("%s: ambiguous option %s", __func__,
4886 } else if (optreturn == CC_OR_NOT_FOUND) {
4887 warnx("%s: option %s not found", __func__,
4899 pp_timeout_val = strtoul(optarg, NULL, 0);
4900 if (pp_timeout_val > 15) {
4901 warnx("%s: invalid partial pathway timeout "
4902 "value %u, need a value less than 16",
4903 __func__, pp_timeout_val);
4907 set_pp_timeout_val = 1;
4915 warnx("%s: a PHY (-p phy) argument is required",__func__);
4920 if (((dev_name_set != 0)
4921 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
4922 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
4923 && (dev_name_set == 0))) {
4924 warnx("%s: -d name and -o setdevname arguments both "
4925 "required to set device name", __func__);
4930 request = malloc(sizeof(*request));
4931 if (request == NULL) {
4932 warn("%s: unable to allocate %zd bytes", __func__,
4938 response = malloc(sizeof(*response));
4939 if (response == NULL) {
4940 warn("%s: unable to allocate %zd bytes", __func__,
4946 smp_phy_control(&ccb->smpio,
4951 (uint8_t *)response,
4954 /*expected_exp_change_count*/ 0,
4957 (set_pp_timeout_val != 0) ? 1 : 0,
4965 if (((retval = cam_send_ccb(device, ccb)) < 0)
4966 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4967 const char warnstr[] = "error sending command";
4974 if (arglist & CAM_ARG_VERBOSE) {
4976 * Use CAM_EPF_NORMAL so we only get one line of
4977 * SMP command decoding.
4979 cam_error_print(device, ccb, CAM_ESF_ALL,
4980 CAM_EPF_NORMAL, stderr);
4986 /* XXX KDM print out something here for success? */
4991 if (request != NULL)
4994 if (response != NULL)
5001 smpmaninfo(struct cam_device *device, int argc, char **argv,
5002 char *combinedopt, int retry_count, int timeout)
5005 struct smp_report_manuf_info_request request;
5006 struct smp_report_manuf_info_response response;
5007 struct sbuf *sb = NULL;
5008 int long_response = 0;
5013 * Note that at the moment we don't support sending SMP CCBs to
5014 * devices that aren't probed by CAM.
5016 ccb = cam_getccb(device);
5018 warnx("%s: error allocating CCB", __func__);
5022 bzero(&(&ccb->ccb_h)[1],
5023 sizeof(union ccb) - sizeof(struct ccb_hdr));
5025 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5034 bzero(&request, sizeof(request));
5035 bzero(&response, sizeof(response));
5037 smp_report_manuf_info(&ccb->smpio,
5042 (uint8_t *)&response,
5047 if (((retval = cam_send_ccb(device, ccb)) < 0)
5048 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5049 const char warnstr[] = "error sending command";
5056 if (arglist & CAM_ARG_VERBOSE) {
5057 cam_error_print(device, ccb, CAM_ESF_ALL,
5058 CAM_EPF_ALL, stderr);
5064 sb = sbuf_new_auto();
5066 warnx("%s: error allocating sbuf", __func__);
5070 smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
5074 printf("%s", sbuf_data(sb));
5088 getdevid(struct cam_devitem *item)
5091 union ccb *ccb = NULL;
5093 struct cam_device *dev;
5095 dev = cam_open_btl(item->dev_match.path_id,
5096 item->dev_match.target_id,
5097 item->dev_match.target_lun, O_RDWR, NULL);
5100 warnx("%s", cam_errbuf);
5105 item->device_id_len = 0;
5107 ccb = cam_getccb(dev);
5109 warnx("%s: error allocating CCB", __func__);
5114 bzero(&(&ccb->ccb_h)[1],
5115 sizeof(union ccb) - sizeof(struct ccb_hdr));
5118 * On the first try, we just probe for the size of the data, and
5119 * then allocate that much memory and try again.
5122 ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
5123 ccb->ccb_h.flags = CAM_DIR_IN;
5124 ccb->cdai.flags = 0;
5125 ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
5126 ccb->cdai.bufsiz = item->device_id_len;
5127 if (item->device_id_len != 0)
5128 ccb->cdai.buf = (uint8_t *)item->device_id;
5130 if (cam_send_ccb(dev, ccb) < 0) {
5131 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
5136 if (ccb->ccb_h.status != CAM_REQ_CMP) {
5137 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
5142 if (item->device_id_len == 0) {
5144 * This is our first time through. Allocate the buffer,
5145 * and then go back to get the data.
5147 if (ccb->cdai.provsiz == 0) {
5148 warnx("%s: invalid .provsiz field returned with "
5149 "XPT_GDEV_ADVINFO CCB", __func__);
5153 item->device_id_len = ccb->cdai.provsiz;
5154 item->device_id = malloc(item->device_id_len);
5155 if (item->device_id == NULL) {
5156 warn("%s: unable to allocate %d bytes", __func__,
5157 item->device_id_len);
5161 ccb->ccb_h.status = CAM_REQ_INPROG;
5167 cam_close_device(dev);
5176 * XXX KDM merge this code with getdevtree()?
5179 buildbusdevlist(struct cam_devlist *devlist)
5182 int bufsize, fd = -1;
5183 struct dev_match_pattern *patterns;
5184 struct cam_devitem *item = NULL;
5185 int skip_device = 0;
5188 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
5189 warn("couldn't open %s", XPT_DEVICE);
5193 bzero(&ccb, sizeof(union ccb));
5195 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
5196 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
5197 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
5199 ccb.ccb_h.func_code = XPT_DEV_MATCH;
5200 bufsize = sizeof(struct dev_match_result) * 100;
5201 ccb.cdm.match_buf_len = bufsize;
5202 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
5203 if (ccb.cdm.matches == NULL) {
5204 warnx("can't malloc memory for matches");
5208 ccb.cdm.num_matches = 0;
5209 ccb.cdm.num_patterns = 2;
5210 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
5211 ccb.cdm.num_patterns;
5213 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
5214 if (patterns == NULL) {
5215 warnx("can't malloc memory for patterns");
5220 ccb.cdm.patterns = patterns;
5221 bzero(patterns, ccb.cdm.pattern_buf_len);
5223 patterns[0].type = DEV_MATCH_DEVICE;
5224 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
5225 patterns[0].pattern.device_pattern.path_id = devlist->path_id;
5226 patterns[1].type = DEV_MATCH_PERIPH;
5227 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
5228 patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
5231 * We do the ioctl multiple times if necessary, in case there are
5232 * more than 100 nodes in the EDT.
5237 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
5238 warn("error sending CAMIOCOMMAND ioctl");
5243 if ((ccb.ccb_h.status != CAM_REQ_CMP)
5244 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
5245 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
5246 warnx("got CAM error %#x, CDM error %d\n",
5247 ccb.ccb_h.status, ccb.cdm.status);
5252 for (i = 0; i < ccb.cdm.num_matches; i++) {
5253 switch (ccb.cdm.matches[i].type) {
5254 case DEV_MATCH_DEVICE: {
5255 struct device_match_result *dev_result;
5258 &ccb.cdm.matches[i].result.device_result;
5260 if (dev_result->flags &
5261 DEV_RESULT_UNCONFIGURED) {
5267 item = malloc(sizeof(*item));
5269 warn("%s: unable to allocate %zd bytes",
5270 __func__, sizeof(*item));
5274 bzero(item, sizeof(*item));
5275 bcopy(dev_result, &item->dev_match,
5276 sizeof(*dev_result));
5277 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
5280 if (getdevid(item) != 0) {
5286 case DEV_MATCH_PERIPH: {
5287 struct periph_match_result *periph_result;
5290 &ccb.cdm.matches[i].result.periph_result;
5292 if (skip_device != 0)
5294 item->num_periphs++;
5295 item->periph_matches = realloc(
5296 item->periph_matches,
5298 sizeof(struct periph_match_result));
5299 if (item->periph_matches == NULL) {
5300 warn("%s: error allocating periph "
5305 bcopy(periph_result, &item->periph_matches[
5306 item->num_periphs - 1],
5307 sizeof(*periph_result));
5311 fprintf(stderr, "%s: unexpected match "
5312 "type %d\n", __func__,
5313 ccb.cdm.matches[i].type);
5316 break; /*NOTREACHED*/
5319 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
5320 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
5328 free(ccb.cdm.matches);
5331 freebusdevlist(devlist);
5337 freebusdevlist(struct cam_devlist *devlist)
5339 struct cam_devitem *item, *item2;
5341 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
5342 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
5344 free(item->device_id);
5345 free(item->periph_matches);
5350 static struct cam_devitem *
5351 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
5353 struct cam_devitem *item;
5355 STAILQ_FOREACH(item, &devlist->dev_queue, links) {
5359 * XXX KDM look for LUN IDs as well?
5361 item_addr = scsi_get_devid(item->device_id,
5362 item->device_id_len,
5363 scsi_devid_is_sas_target);
5364 if (item_addr == NULL)
5367 if (scsi_8btou64(item_addr) == sasaddr)
5375 smpphylist(struct cam_device *device, int argc, char **argv,
5376 char *combinedopt, int retry_count, int timeout)
5378 struct smp_report_general_request *rgrequest = NULL;
5379 struct smp_report_general_response *rgresponse = NULL;
5380 struct smp_discover_request *disrequest = NULL;
5381 struct smp_discover_response *disresponse = NULL;
5382 struct cam_devlist devlist;
5384 int long_response = 0;
5391 * Note that at the moment we don't support sending SMP CCBs to
5392 * devices that aren't probed by CAM.
5394 ccb = cam_getccb(device);
5396 warnx("%s: error allocating CCB", __func__);
5400 bzero(&(&ccb->ccb_h)[1],
5401 sizeof(union ccb) - sizeof(struct ccb_hdr));
5403 rgrequest = malloc(sizeof(*rgrequest));
5404 if (rgrequest == NULL) {
5405 warn("%s: unable to allocate %zd bytes", __func__,
5406 sizeof(*rgrequest));
5411 rgresponse = malloc(sizeof(*rgresponse));
5412 if (rgresponse == NULL) {
5413 warn("%s: unable to allocate %zd bytes", __func__,
5414 sizeof(*rgresponse));
5419 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5432 smp_report_general(&ccb->smpio,
5436 /*request_len*/ sizeof(*rgrequest),
5437 (uint8_t *)rgresponse,
5438 /*response_len*/ sizeof(*rgresponse),
5439 /*long_response*/ long_response,
5442 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5444 if (((retval = cam_send_ccb(device, ccb)) < 0)
5445 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5446 const char warnstr[] = "error sending command";
5453 if (arglist & CAM_ARG_VERBOSE) {
5454 cam_error_print(device, ccb, CAM_ESF_ALL,
5455 CAM_EPF_ALL, stderr);
5461 num_phys = rgresponse->num_phys;
5463 if (num_phys == 0) {
5465 fprintf(stdout, "%s: No Phys reported\n", __func__);
5470 STAILQ_INIT(&devlist.dev_queue);
5471 devlist.path_id = device->path_id;
5473 retval = buildbusdevlist(&devlist);
5478 fprintf(stdout, "%d PHYs:\n", num_phys);
5479 fprintf(stdout, "PHY Attached SAS Address\n");
5482 disrequest = malloc(sizeof(*disrequest));
5483 if (disrequest == NULL) {
5484 warn("%s: unable to allocate %zd bytes", __func__,
5485 sizeof(*disrequest));
5490 disresponse = malloc(sizeof(*disresponse));
5491 if (disresponse == NULL) {
5492 warn("%s: unable to allocate %zd bytes", __func__,
5493 sizeof(*disresponse));
5498 for (i = 0; i < num_phys; i++) {
5499 struct cam_devitem *item;
5500 struct device_match_result *dev_match;
5501 char vendor[16], product[48], revision[16];
5505 bzero(&(&ccb->ccb_h)[1],
5506 sizeof(union ccb) - sizeof(struct ccb_hdr));
5508 ccb->ccb_h.status = CAM_REQ_INPROG;
5509 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5511 smp_discover(&ccb->smpio,
5515 sizeof(*disrequest),
5516 (uint8_t *)disresponse,
5517 sizeof(*disresponse),
5519 /*ignore_zone_group*/ 0,
5523 if (((retval = cam_send_ccb(device, ccb)) < 0)
5524 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
5525 && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
5526 const char warnstr[] = "error sending command";
5533 if (arglist & CAM_ARG_VERBOSE) {
5534 cam_error_print(device, ccb, CAM_ESF_ALL,
5535 CAM_EPF_ALL, stderr);
5541 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
5543 fprintf(stdout, "%3d <vacant>\n", i);
5547 item = findsasdevice(&devlist,
5548 scsi_8btou64(disresponse->attached_sas_address));
5551 || (item != NULL)) {
5552 fprintf(stdout, "%3d 0x%016jx", i,
5553 (uintmax_t)scsi_8btou64(
5554 disresponse->attached_sas_address));
5556 fprintf(stdout, "\n");
5559 } else if (quiet != 0)
5562 dev_match = &item->dev_match;
5564 if (dev_match->protocol == PROTO_SCSI) {
5565 cam_strvis(vendor, dev_match->inq_data.vendor,
5566 sizeof(dev_match->inq_data.vendor),
5568 cam_strvis(product, dev_match->inq_data.product,
5569 sizeof(dev_match->inq_data.product),
5571 cam_strvis(revision, dev_match->inq_data.revision,
5572 sizeof(dev_match->inq_data.revision),
5574 sprintf(tmpstr, "<%s %s %s>", vendor, product,
5576 } else if ((dev_match->protocol == PROTO_ATA)
5577 || (dev_match->protocol == PROTO_SATAPM)) {
5578 cam_strvis(product, dev_match->ident_data.model,
5579 sizeof(dev_match->ident_data.model),
5581 cam_strvis(revision, dev_match->ident_data.revision,
5582 sizeof(dev_match->ident_data.revision),
5584 sprintf(tmpstr, "<%s %s>", product, revision);
5586 sprintf(tmpstr, "<>");
5588 fprintf(stdout, " %-33s ", tmpstr);
5591 * If we have 0 periphs, that's a bug...
5593 if (item->num_periphs == 0) {
5594 fprintf(stdout, "\n");
5598 fprintf(stdout, "(");
5599 for (j = 0; j < item->num_periphs; j++) {
5601 fprintf(stdout, ",");
5603 fprintf(stdout, "%s%d",
5604 item->periph_matches[j].periph_name,
5605 item->periph_matches[j].unit_number);
5608 fprintf(stdout, ")\n");
5622 freebusdevlist(&devlist);
5628 atapm(struct cam_device *device, int argc, char **argv,
5629 char *combinedopt, int retry_count, int timeout)
5637 ccb = cam_getccb(device);
5640 warnx("%s: error allocating ccb", __func__);
5644 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5653 if (strcmp(argv[1], "idle") == 0) {
5655 cmd = ATA_IDLE_IMMEDIATE;
5658 } else if (strcmp(argv[1], "standby") == 0) {
5660 cmd = ATA_STANDBY_IMMEDIATE;
5662 cmd = ATA_STANDBY_CMD;
5670 else if (t <= (240 * 5))
5672 else if (t <= (252 * 5))
5673 /* special encoding for 21 minutes */
5675 else if (t <= (11 * 30 * 60))
5676 sc = (t - 1) / (30 * 60) + 241;
5680 cam_fill_ataio(&ccb->ataio,
5683 /*flags*/CAM_DIR_NONE,
5687 timeout ? timeout : 30 * 1000);
5688 ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
5690 /* Disable freezing the device queue */
5691 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5693 if (arglist & CAM_ARG_ERR_RECOVER)
5694 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5696 if (cam_send_ccb(device, ccb) < 0) {
5697 warn("error sending command");
5699 if (arglist & CAM_ARG_VERBOSE)
5700 cam_error_print(device, ccb, CAM_ESF_ALL,
5701 CAM_EPF_ALL, stderr);
5707 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5708 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5717 #endif /* MINIMALISTIC */
5722 fprintf(verbose ? stdout : stderr,
5723 "usage: camcontrol <command> [device id][generic args][command args]\n"
5724 " camcontrol devlist [-v]\n"
5725 #ifndef MINIMALISTIC
5726 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
5727 " camcontrol tur [dev_id][generic args]\n"
5728 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
5729 " camcontrol identify [dev_id][generic args] [-v]\n"
5730 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
5731 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
5733 " camcontrol start [dev_id][generic args]\n"
5734 " camcontrol stop [dev_id][generic args]\n"
5735 " camcontrol load [dev_id][generic args]\n"
5736 " camcontrol eject [dev_id][generic args]\n"
5737 #endif /* MINIMALISTIC */
5738 " camcontrol rescan <all | bus[:target:lun]>\n"
5739 " camcontrol reset <all | bus[:target:lun]>\n"
5740 #ifndef MINIMALISTIC
5741 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
5742 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
5743 " [-P pagectl][-e | -b][-d]\n"
5744 " camcontrol cmd [dev_id][generic args]\n"
5745 " <-a cmd [args] | -c cmd [args]>\n"
5746 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
5747 " camcontrol smpcmd [dev_id][generic args]\n"
5748 " <-r len fmt [args]> <-R len fmt [args]>\n"
5749 " camcontrol smprg [dev_id][generic args][-l]\n"
5750 " camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n"
5751 " [-o operation][-d name][-m rate][-M rate]\n"
5752 " [-T pp_timeout][-a enable|disable]\n"
5753 " [-A enable|disable][-s enable|disable]\n"
5754 " [-S enable|disable]\n"
5755 " camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
5756 " camcontrol smpmaninfo [dev_id][generic args][-l]\n"
5757 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
5758 " <all|bus[:target[:lun]]|off>\n"
5759 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
5760 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
5761 " [-D <enable|disable>][-M mode][-O offset]\n"
5762 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
5763 " [-U][-W bus_width]\n"
5764 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
5765 " camcontrol idle [dev_id][generic args][-t time]\n"
5766 " camcontrol standby [dev_id][generic args][-t time]\n"
5767 " camcontrol sleep [dev_id][generic args]\n"
5768 #endif /* MINIMALISTIC */
5769 " camcontrol help\n");
5772 #ifndef MINIMALISTIC
5774 "Specify one of the following options:\n"
5775 "devlist list all CAM devices\n"
5776 "periphlist list all CAM peripheral drivers attached to a device\n"
5777 "tur send a test unit ready to the named device\n"
5778 "inquiry send a SCSI inquiry command to the named device\n"
5779 "identify send a ATA identify command to the named device\n"
5780 "reportluns send a SCSI report luns command to the device\n"
5781 "readcap send a SCSI read capacity command to the device\n"
5782 "start send a Start Unit command to the device\n"
5783 "stop send a Stop Unit command to the device\n"
5784 "load send a Start Unit command to the device with the load bit set\n"
5785 "eject send a Stop Unit command to the device with the eject bit set\n"
5786 "rescan rescan all busses, the given bus, or bus:target:lun\n"
5787 "reset reset all busses, the given bus, or bus:target:lun\n"
5788 "defects read the defect list of the specified device\n"
5789 "modepage display or edit (-e) the given mode page\n"
5790 "cmd send the given SCSI command, may need -i or -o as well\n"
5791 "smpcmd send the given SMP command, requires -o and -i\n"
5792 "smprg send the SMP Report General command\n"
5793 "smppc send the SMP PHY Control command, requires -p\n"
5794 "smpphylist display phys attached to a SAS expander\n"
5795 "smpmaninfo send the SMP Report Manufacturer Info command\n"
5796 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
5797 "tags report or set the number of transaction slots for a device\n"
5798 "negotiate report or set device negotiation parameters\n"
5799 "format send the SCSI FORMAT UNIT command to the named device\n"
5800 "idle send the ATA IDLE command to the named device\n"
5801 "standby send the ATA STANDBY command to the named device\n"
5802 "sleep send the ATA SLEEP command to the named device\n"
5803 "help this message\n"
5804 "Device Identifiers:\n"
5805 "bus:target specify the bus and target, lun defaults to 0\n"
5806 "bus:target:lun specify the bus, target and lun\n"
5807 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
5808 "Generic arguments:\n"
5809 "-v be verbose, print out sense information\n"
5810 "-t timeout command timeout in seconds, overrides default timeout\n"
5811 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
5812 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
5813 "-E have the kernel attempt to perform SCSI error recovery\n"
5814 "-C count specify the SCSI command retry count (needs -E to work)\n"
5815 "modepage arguments:\n"
5816 "-l list all available mode pages\n"
5817 "-m page specify the mode page to view or edit\n"
5818 "-e edit the specified mode page\n"
5819 "-b force view to binary mode\n"
5820 "-d disable block descriptors for mode sense\n"
5821 "-P pgctl page control field 0-3\n"
5822 "defects arguments:\n"
5823 "-f format specify defect list format (block, bfi or phys)\n"
5824 "-G get the grown defect list\n"
5825 "-P get the permanant defect list\n"
5826 "inquiry arguments:\n"
5827 "-D get the standard inquiry data\n"
5828 "-S get the serial number\n"
5829 "-R get the transfer rate, etc.\n"
5830 "reportluns arguments:\n"
5831 "-c only report a count of available LUNs\n"
5832 "-l only print out luns, and not a count\n"
5833 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
5834 "readcap arguments\n"
5835 "-b only report the blocksize\n"
5836 "-h human readable device size, base 2\n"
5837 "-H human readable device size, base 10\n"
5838 "-N print the number of blocks instead of last block\n"
5839 "-q quiet, print numbers only\n"
5840 "-s only report the last block/device size\n"
5842 "-c cdb [args] specify the SCSI CDB\n"
5843 "-i len fmt specify input data and input data format\n"
5844 "-o len fmt [args] specify output data and output data fmt\n"
5845 "smpcmd arguments:\n"
5846 "-r len fmt [args] specify the SMP command to be sent\n"
5847 "-R len fmt [args] specify SMP response format\n"
5848 "smprg arguments:\n"
5849 "-l specify the long response format\n"
5850 "smppc arguments:\n"
5851 "-p phy specify the PHY to operate on\n"
5852 "-l specify the long request/response format\n"
5853 "-o operation specify the phy control operation\n"
5854 "-d name set the attached device name\n"
5855 "-m rate set the minimum physical link rate\n"
5856 "-M rate set the maximum physical link rate\n"
5857 "-T pp_timeout set the partial pathway timeout value\n"
5858 "-a enable|disable enable or disable SATA slumber\n"
5859 "-A enable|disable enable or disable SATA partial phy power\n"
5860 "-s enable|disable enable or disable SAS slumber\n"
5861 "-S enable|disable enable or disable SAS partial phy power\n"
5862 "smpphylist arguments:\n"
5863 "-l specify the long response format\n"
5864 "-q only print phys with attached devices\n"
5865 "smpmaninfo arguments:\n"
5866 "-l specify the long response format\n"
5867 "debug arguments:\n"
5868 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
5869 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
5870 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
5871 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
5873 "-N tags specify the number of tags to use for this device\n"
5874 "-q be quiet, don't report the number of tags\n"
5875 "-v report a number of tag-related parameters\n"
5876 "negotiate arguments:\n"
5877 "-a send a test unit ready after negotiation\n"
5878 "-c report/set current negotiation settings\n"
5879 "-D <arg> \"enable\" or \"disable\" disconnection\n"
5880 "-M mode set ATA mode\n"
5881 "-O offset set command delay offset\n"
5882 "-q be quiet, don't report anything\n"
5883 "-R syncrate synchronization rate in MHz\n"
5884 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
5885 "-U report/set user negotiation settings\n"
5886 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
5887 "-v also print a Path Inquiry CCB for the controller\n"
5888 "format arguments:\n"
5889 "-q be quiet, don't print status messages\n"
5890 "-r run in report only mode\n"
5891 "-w don't send immediate format command\n"
5892 "-y don't ask any questions\n"
5893 "idle/standby arguments:\n"
5894 "-t <arg> number of seconds before respective state.\n");
5895 #endif /* MINIMALISTIC */
5899 main(int argc, char **argv)
5902 char *device = NULL;
5904 struct cam_device *cam_dev = NULL;
5905 int timeout = 0, retry_count = 1;
5906 camcontrol_optret optreturn;
5908 const char *mainopt = "C:En:t:u:v";
5909 const char *subopt = NULL;
5910 char combinedopt[256];
5911 int error = 0, optstart = 2;
5913 #ifndef MINIMALISTIC
5914 int bus, target, lun;
5915 #endif /* MINIMALISTIC */
5917 cmdlist = CAM_CMD_NONE;
5918 arglist = CAM_ARG_NONE;
5926 * Get the base option.
5928 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
5930 if (optreturn == CC_OR_AMBIGUOUS) {
5931 warnx("ambiguous option %s", argv[1]);
5934 } else if (optreturn == CC_OR_NOT_FOUND) {
5935 warnx("option %s not found", argv[1]);
5941 * Ahh, getopt(3) is a pain.
5943 * This is a gross hack. There really aren't many other good
5944 * options (excuse the pun) for parsing options in a situation like
5945 * this. getopt is kinda braindead, so you end up having to run
5946 * through the options twice, and give each invocation of getopt
5947 * the option string for the other invocation.
5949 * You would think that you could just have two groups of options.
5950 * The first group would get parsed by the first invocation of
5951 * getopt, and the second group would get parsed by the second
5952 * invocation of getopt. It doesn't quite work out that way. When
5953 * the first invocation of getopt finishes, it leaves optind pointing
5954 * to the argument _after_ the first argument in the second group.
5955 * So when the second invocation of getopt comes around, it doesn't
5956 * recognize the first argument it gets and then bails out.
5958 * A nice alternative would be to have a flag for getopt that says
5959 * "just keep parsing arguments even when you encounter an unknown
5960 * argument", but there isn't one. So there's no real clean way to
5961 * easily parse two sets of arguments without having one invocation
5962 * of getopt know about the other.
5964 * Without this hack, the first invocation of getopt would work as
5965 * long as the generic arguments are first, but the second invocation
5966 * (in the subfunction) would fail in one of two ways. In the case
5967 * where you don't set optreset, it would fail because optind may be
5968 * pointing to the argument after the one it should be pointing at.
5969 * In the case where you do set optreset, and reset optind, it would
5970 * fail because getopt would run into the first set of options, which
5971 * it doesn't understand.
5973 * All of this would "sort of" work if you could somehow figure out
5974 * whether optind had been incremented one option too far. The
5975 * mechanics of that, however, are more daunting than just giving
5976 * both invocations all of the expect options for either invocation.
5978 * Needless to say, I wouldn't mind if someone invented a better
5979 * (non-GPL!) command line parsing interface than getopt. I
5980 * wouldn't mind if someone added more knobs to getopt to make it
5981 * work better. Who knows, I may talk myself into doing it someday,
5982 * if the standards weenies let me. As it is, it just leads to
5983 * hackery like this and causes people to avoid it in some cases.
5985 * KDM, September 8th, 1998
5988 sprintf(combinedopt, "%s%s", mainopt, subopt);
5990 sprintf(combinedopt, "%s", mainopt);
5993 * For these options we do not parse optional device arguments and
5994 * we do not open a passthrough device.
5996 if ((cmdlist == CAM_CMD_RESCAN)
5997 || (cmdlist == CAM_CMD_RESET)
5998 || (cmdlist == CAM_CMD_DEVTREE)
5999 || (cmdlist == CAM_CMD_USAGE)
6000 || (cmdlist == CAM_CMD_DEBUG))
6003 #ifndef MINIMALISTIC
6005 && (argc > 2 && argv[2][0] != '-')) {
6009 if (isdigit(argv[2][0])) {
6010 /* device specified as bus:target[:lun] */
6011 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
6013 errx(1, "numeric device specification must "
6014 "be either bus:target, or "
6016 /* default to 0 if lun was not specified */
6017 if ((arglist & CAM_ARG_LUN) == 0) {
6019 arglist |= CAM_ARG_LUN;
6023 if (cam_get_device(argv[2], name, sizeof name, &unit)
6025 errx(1, "%s", cam_errbuf);
6026 device = strdup(name);
6027 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
6031 #endif /* MINIMALISTIC */
6033 * Start getopt processing at argv[2/3], since we've already
6034 * accepted argv[1..2] as the command name, and as a possible
6040 * Now we run through the argument list looking for generic
6041 * options, and ignoring options that possibly belong to
6044 while ((c = getopt(argc, argv, combinedopt))!= -1){
6047 retry_count = strtol(optarg, NULL, 0);
6048 if (retry_count < 0)
6049 errx(1, "retry count %d is < 0",
6051 arglist |= CAM_ARG_RETRIES;
6054 arglist |= CAM_ARG_ERR_RECOVER;
6057 arglist |= CAM_ARG_DEVICE;
6059 while (isspace(*tstr) && (*tstr != '\0'))
6061 device = (char *)strdup(tstr);
6064 timeout = strtol(optarg, NULL, 0);
6066 errx(1, "invalid timeout %d", timeout);
6067 /* Convert the timeout from seconds to ms */
6069 arglist |= CAM_ARG_TIMEOUT;
6072 arglist |= CAM_ARG_UNIT;
6073 unit = strtol(optarg, NULL, 0);
6076 arglist |= CAM_ARG_VERBOSE;
6083 #ifndef MINIMALISTIC
6085 * For most commands we'll want to open the passthrough device
6086 * associated with the specified device. In the case of the rescan
6087 * commands, we don't use a passthrough device at all, just the
6088 * transport layer device.
6091 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
6092 && (((arglist & CAM_ARG_DEVICE) == 0)
6093 || ((arglist & CAM_ARG_UNIT) == 0))) {
6094 errx(1, "subcommand \"%s\" requires a valid device "
6095 "identifier", argv[1]);
6098 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
6099 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
6100 cam_open_spec_device(device,unit,O_RDWR,NULL)))
6102 errx(1,"%s", cam_errbuf);
6104 #endif /* MINIMALISTIC */
6107 * Reset optind to 2, and reset getopt, so these routines can parse
6108 * the arguments again.
6114 #ifndef MINIMALISTIC
6115 case CAM_CMD_DEVLIST:
6116 error = getdevlist(cam_dev);
6118 #endif /* MINIMALISTIC */
6119 case CAM_CMD_DEVTREE:
6120 error = getdevtree();
6122 #ifndef MINIMALISTIC
6124 error = testunitready(cam_dev, retry_count, timeout, 0);
6126 case CAM_CMD_INQUIRY:
6127 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
6128 retry_count, timeout);
6130 case CAM_CMD_IDENTIFY:
6131 error = ataidentify(cam_dev, retry_count, timeout);
6133 case CAM_CMD_STARTSTOP:
6134 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
6135 arglist & CAM_ARG_EJECT, retry_count,
6138 #endif /* MINIMALISTIC */
6139 case CAM_CMD_RESCAN:
6140 error = dorescan_or_reset(argc, argv, 1);
6143 error = dorescan_or_reset(argc, argv, 0);
6145 #ifndef MINIMALISTIC
6146 case CAM_CMD_READ_DEFECTS:
6147 error = readdefects(cam_dev, argc, argv, combinedopt,
6148 retry_count, timeout);
6150 case CAM_CMD_MODE_PAGE:
6151 modepage(cam_dev, argc, argv, combinedopt,
6152 retry_count, timeout);
6154 case CAM_CMD_SCSI_CMD:
6155 error = scsicmd(cam_dev, argc, argv, combinedopt,
6156 retry_count, timeout);
6158 case CAM_CMD_SMP_CMD:
6159 error = smpcmd(cam_dev, argc, argv, combinedopt,
6160 retry_count, timeout);
6162 case CAM_CMD_SMP_RG:
6163 error = smpreportgeneral(cam_dev, argc, argv,
6164 combinedopt, retry_count,
6167 case CAM_CMD_SMP_PC:
6168 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
6169 retry_count, timeout);
6171 case CAM_CMD_SMP_PHYLIST:
6172 error = smpphylist(cam_dev, argc, argv, combinedopt,
6173 retry_count, timeout);
6175 case CAM_CMD_SMP_MANINFO:
6176 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
6177 retry_count, timeout);
6180 error = camdebug(argc, argv, combinedopt);
6183 error = tagcontrol(cam_dev, argc, argv, combinedopt);
6186 error = ratecontrol(cam_dev, retry_count, timeout,
6187 argc, argv, combinedopt);
6189 case CAM_CMD_FORMAT:
6190 error = scsiformat(cam_dev, argc, argv,
6191 combinedopt, retry_count, timeout);
6193 case CAM_CMD_REPORTLUNS:
6194 error = scsireportluns(cam_dev, argc, argv,
6195 combinedopt, retry_count,
6198 case CAM_CMD_READCAP:
6199 error = scsireadcapacity(cam_dev, argc, argv,
6200 combinedopt, retry_count,
6204 case CAM_CMD_STANDBY:
6206 error = atapm(cam_dev, argc, argv,
6207 combinedopt, retry_count,
6210 #endif /* MINIMALISTIC */
6220 if (cam_dev != NULL)
6221 cam_close_device(cam_dev);