2 * Copyright (c) 1997-2007 Kenneth D. Merry
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/ioctl.h>
33 #include <sys/stdint.h>
34 #include <sys/types.h>
35 #include <sys/endian.h>
50 #include <cam/cam_debug.h>
51 #include <cam/cam_ccb.h>
52 #include <cam/scsi/scsi_all.h>
53 #include <cam/scsi/scsi_da.h>
54 #include <cam/scsi/scsi_pass.h>
55 #include <cam/scsi/scsi_message.h>
56 #include <cam/scsi/smp_all.h>
57 #include <cam/ata/ata_all.h>
59 #include "camcontrol.h"
62 CAM_CMD_NONE = 0x00000000,
63 CAM_CMD_DEVLIST = 0x00000001,
64 CAM_CMD_TUR = 0x00000002,
65 CAM_CMD_INQUIRY = 0x00000003,
66 CAM_CMD_STARTSTOP = 0x00000004,
67 CAM_CMD_RESCAN = 0x00000005,
68 CAM_CMD_READ_DEFECTS = 0x00000006,
69 CAM_CMD_MODE_PAGE = 0x00000007,
70 CAM_CMD_SCSI_CMD = 0x00000008,
71 CAM_CMD_DEVTREE = 0x00000009,
72 CAM_CMD_USAGE = 0x0000000a,
73 CAM_CMD_DEBUG = 0x0000000b,
74 CAM_CMD_RESET = 0x0000000c,
75 CAM_CMD_FORMAT = 0x0000000d,
76 CAM_CMD_TAG = 0x0000000e,
77 CAM_CMD_RATE = 0x0000000f,
78 CAM_CMD_DETACH = 0x00000010,
79 CAM_CMD_REPORTLUNS = 0x00000011,
80 CAM_CMD_READCAP = 0x00000012,
81 CAM_CMD_IDENTIFY = 0x00000013,
82 CAM_CMD_IDLE = 0x00000014,
83 CAM_CMD_STANDBY = 0x00000015,
84 CAM_CMD_SLEEP = 0x00000016,
85 CAM_CMD_SMP_CMD = 0x00000017,
86 CAM_CMD_SMP_RG = 0x00000018,
87 CAM_CMD_SMP_PC = 0x00000019,
88 CAM_CMD_SMP_PHYLIST = 0x0000001a,
89 CAM_CMD_SMP_MANINFO = 0x0000001b
93 CAM_ARG_NONE = 0x00000000,
94 CAM_ARG_VERBOSE = 0x00000001,
95 CAM_ARG_DEVICE = 0x00000002,
96 CAM_ARG_BUS = 0x00000004,
97 CAM_ARG_TARGET = 0x00000008,
98 CAM_ARG_LUN = 0x00000010,
99 CAM_ARG_EJECT = 0x00000020,
100 CAM_ARG_UNIT = 0x00000040,
101 CAM_ARG_FORMAT_BLOCK = 0x00000080,
102 CAM_ARG_FORMAT_BFI = 0x00000100,
103 CAM_ARG_FORMAT_PHYS = 0x00000200,
104 CAM_ARG_PLIST = 0x00000400,
105 CAM_ARG_GLIST = 0x00000800,
106 CAM_ARG_GET_SERIAL = 0x00001000,
107 CAM_ARG_GET_STDINQ = 0x00002000,
108 CAM_ARG_GET_XFERRATE = 0x00004000,
109 CAM_ARG_INQ_MASK = 0x00007000,
110 CAM_ARG_MODE_EDIT = 0x00008000,
111 CAM_ARG_PAGE_CNTL = 0x00010000,
112 CAM_ARG_TIMEOUT = 0x00020000,
113 CAM_ARG_CMD_IN = 0x00040000,
114 CAM_ARG_CMD_OUT = 0x00080000,
115 CAM_ARG_DBD = 0x00100000,
116 CAM_ARG_ERR_RECOVER = 0x00200000,
117 CAM_ARG_RETRIES = 0x00400000,
118 CAM_ARG_START_UNIT = 0x00800000,
119 CAM_ARG_DEBUG_INFO = 0x01000000,
120 CAM_ARG_DEBUG_TRACE = 0x02000000,
121 CAM_ARG_DEBUG_SUBTRACE = 0x04000000,
122 CAM_ARG_DEBUG_CDB = 0x08000000,
123 CAM_ARG_DEBUG_XPT = 0x10000000,
124 CAM_ARG_DEBUG_PERIPH = 0x20000000,
127 struct camcontrol_opts {
135 static const char scsicmd_opts[] = "a:c:dfi:o:r";
136 static const char readdefect_opts[] = "f:GP";
137 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
138 static const char smprg_opts[] = "l";
139 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
140 static const char smpphylist_opts[] = "lq";
143 struct camcontrol_opts option_table[] = {
145 {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
146 {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
147 {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
148 {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
149 {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
150 {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
151 {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
152 {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
153 {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
154 #endif /* MINIMALISTIC */
155 {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
156 {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
158 {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
159 {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
160 {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
161 {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
162 {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
163 {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
164 {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
165 {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
166 {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
167 {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
168 {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
169 {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
170 #endif /* MINIMALISTIC */
171 {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
173 {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
174 {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
175 {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
176 {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
177 {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
178 {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
179 {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
180 {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
181 {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
182 {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
183 #endif /* MINIMALISTIC */
184 {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
185 {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
186 {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
197 struct device_match_result dev_match;
199 struct periph_match_result *periph_matches;
200 struct scsi_vpd_device_id *device_id;
202 STAILQ_ENTRY(cam_devitem) links;
206 STAILQ_HEAD(, cam_devitem) dev_queue;
213 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
214 uint32_t *cmdnum, cam_argmask *argnum,
215 const char **subopt);
217 static int getdevlist(struct cam_device *device);
218 #endif /* MINIMALISTIC */
219 static int getdevtree(void);
221 static int testunitready(struct cam_device *device, int retry_count,
222 int timeout, int quiet);
223 static int scsistart(struct cam_device *device, int startstop, int loadeject,
224 int retry_count, int timeout);
225 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
226 char *combinedopt, int retry_count, int timeout);
227 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
228 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
229 static int camxferrate(struct cam_device *device);
230 #endif /* MINIMALISTIC */
231 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
232 cam_argmask *arglst);
233 static int dorescan_or_reset(int argc, char **argv, int rescan);
234 static int rescan_or_reset_bus(int bus, int rescan);
235 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
237 static int readdefects(struct cam_device *device, int argc, char **argv,
238 char *combinedopt, int retry_count, int timeout);
239 static void modepage(struct cam_device *device, int argc, char **argv,
240 char *combinedopt, int retry_count, int timeout);
241 static int scsicmd(struct cam_device *device, int argc, char **argv,
242 char *combinedopt, int retry_count, int timeout);
243 static int smpcmd(struct cam_device *device, int argc, char **argv,
244 char *combinedopt, int retry_count, int timeout);
245 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
246 char *combinedopt, int retry_count, int timeout);
247 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
248 char *combinedopt, int retry_count, int timeout);
249 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
250 char *combinedopt, int retry_count, int timeout);
251 static int getdevid(struct cam_devitem *item);
252 static int buildbusdevlist(struct cam_devlist *devlist);
253 static void freebusdevlist(struct cam_devlist *devlist);
254 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
256 static int smpphylist(struct cam_device *device, int argc, char **argv,
257 char *combinedopt, int retry_count, int timeout);
258 static int tagcontrol(struct cam_device *device, int argc, char **argv,
260 static void cts_print(struct cam_device *device,
261 struct ccb_trans_settings *cts);
262 static void cpi_print(struct ccb_pathinq *cpi);
263 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
264 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
265 static int get_print_cts(struct cam_device *device, int user_settings,
266 int quiet, struct ccb_trans_settings *cts);
267 static int ratecontrol(struct cam_device *device, int retry_count,
268 int timeout, int argc, char **argv, char *combinedopt);
269 static int scsiformat(struct cam_device *device, int argc, char **argv,
270 char *combinedopt, int retry_count, int timeout);
271 static int scsireportluns(struct cam_device *device, int argc, char **argv,
272 char *combinedopt, int retry_count, int timeout);
273 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
274 char *combinedopt, int retry_count, int timeout);
275 static int atapm(struct cam_device *device, int argc, char **argv,
276 char *combinedopt, int retry_count, int timeout);
277 #endif /* MINIMALISTIC */
279 #define min(a,b) (((a)<(b))?(a):(b))
282 #define max(a,b) (((a)>(b))?(a):(b))
286 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
287 cam_argmask *argnum, const char **subopt)
289 struct camcontrol_opts *opts;
292 for (opts = table; (opts != NULL) && (opts->optname != NULL);
294 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
295 *cmdnum = opts->cmdnum;
296 *argnum = opts->argnum;
297 *subopt = opts->subopt;
298 if (++num_matches > 1)
299 return(CC_OR_AMBIGUOUS);
306 return(CC_OR_NOT_FOUND);
311 getdevlist(struct cam_device *device)
317 ccb = cam_getccb(device);
319 ccb->ccb_h.func_code = XPT_GDEVLIST;
320 ccb->ccb_h.flags = CAM_DIR_NONE;
321 ccb->ccb_h.retry_count = 1;
323 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
324 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
325 if (cam_send_ccb(device, ccb) < 0) {
326 perror("error getting device list");
333 switch (ccb->cgdl.status) {
334 case CAM_GDEVLIST_MORE_DEVS:
335 strcpy(status, "MORE");
337 case CAM_GDEVLIST_LAST_DEVICE:
338 strcpy(status, "LAST");
340 case CAM_GDEVLIST_LIST_CHANGED:
341 strcpy(status, "CHANGED");
343 case CAM_GDEVLIST_ERROR:
344 strcpy(status, "ERROR");
349 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
350 ccb->cgdl.periph_name,
351 ccb->cgdl.unit_number,
352 ccb->cgdl.generation,
357 * If the list has changed, we need to start over from the
360 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
368 #endif /* MINIMALISTIC */
380 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
381 warn("couldn't open %s", XPT_DEVICE);
385 bzero(&ccb, sizeof(union ccb));
387 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
388 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
389 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
391 ccb.ccb_h.func_code = XPT_DEV_MATCH;
392 bufsize = sizeof(struct dev_match_result) * 100;
393 ccb.cdm.match_buf_len = bufsize;
394 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
395 if (ccb.cdm.matches == NULL) {
396 warnx("can't malloc memory for matches");
400 ccb.cdm.num_matches = 0;
403 * We fetch all nodes, since we display most of them in the default
404 * case, and all in the verbose case.
406 ccb.cdm.num_patterns = 0;
407 ccb.cdm.pattern_buf_len = 0;
410 * We do the ioctl multiple times if necessary, in case there are
411 * more than 100 nodes in the EDT.
414 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
415 warn("error sending CAMIOCOMMAND ioctl");
420 if ((ccb.ccb_h.status != CAM_REQ_CMP)
421 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
422 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
423 warnx("got CAM error %#x, CDM error %d\n",
424 ccb.ccb_h.status, ccb.cdm.status);
429 for (i = 0; i < ccb.cdm.num_matches; i++) {
430 switch (ccb.cdm.matches[i].type) {
431 case DEV_MATCH_BUS: {
432 struct bus_match_result *bus_result;
435 * Only print the bus information if the
436 * user turns on the verbose flag.
438 if ((arglist & CAM_ARG_VERBOSE) == 0)
442 &ccb.cdm.matches[i].result.bus_result;
445 fprintf(stdout, ")\n");
449 fprintf(stdout, "scbus%d on %s%d bus %d:\n",
451 bus_result->dev_name,
452 bus_result->unit_number,
456 case DEV_MATCH_DEVICE: {
457 struct device_match_result *dev_result;
458 char vendor[16], product[48], revision[16];
462 &ccb.cdm.matches[i].result.device_result;
464 if ((dev_result->flags
465 & DEV_RESULT_UNCONFIGURED)
466 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
472 if (dev_result->protocol == PROTO_SCSI) {
473 cam_strvis(vendor, dev_result->inq_data.vendor,
474 sizeof(dev_result->inq_data.vendor),
477 dev_result->inq_data.product,
478 sizeof(dev_result->inq_data.product),
481 dev_result->inq_data.revision,
482 sizeof(dev_result->inq_data.revision),
484 sprintf(tmpstr, "<%s %s %s>", vendor, product,
486 } else if (dev_result->protocol == PROTO_ATA ||
487 dev_result->protocol == PROTO_SATAPM) {
489 dev_result->ident_data.model,
490 sizeof(dev_result->ident_data.model),
493 dev_result->ident_data.revision,
494 sizeof(dev_result->ident_data.revision),
496 sprintf(tmpstr, "<%s %s>", product,
499 sprintf(tmpstr, "<>");
502 fprintf(stdout, ")\n");
506 fprintf(stdout, "%-33s at scbus%d "
507 "target %d lun %d (",
510 dev_result->target_id,
511 dev_result->target_lun);
517 case DEV_MATCH_PERIPH: {
518 struct periph_match_result *periph_result;
521 &ccb.cdm.matches[i].result.periph_result;
523 if (skip_device != 0)
527 fprintf(stdout, ",");
529 fprintf(stdout, "%s%d",
530 periph_result->periph_name,
531 periph_result->unit_number);
537 fprintf(stdout, "unknown match type\n");
542 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
543 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
546 fprintf(stdout, ")\n");
555 testunitready(struct cam_device *device, int retry_count, int timeout,
561 ccb = cam_getccb(device);
563 scsi_test_unit_ready(&ccb->csio,
564 /* retries */ retry_count,
566 /* tag_action */ MSG_SIMPLE_Q_TAG,
567 /* sense_len */ SSD_FULL_SIZE,
568 /* timeout */ timeout ? timeout : 5000);
570 /* Disable freezing the device queue */
571 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
573 if (arglist & CAM_ARG_ERR_RECOVER)
574 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
576 if (cam_send_ccb(device, ccb) < 0) {
578 perror("error sending test unit ready");
580 if (arglist & CAM_ARG_VERBOSE) {
581 cam_error_print(device, ccb, CAM_ESF_ALL,
582 CAM_EPF_ALL, stderr);
589 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
591 fprintf(stdout, "Unit is ready\n");
594 fprintf(stdout, "Unit is not ready\n");
597 if (arglist & CAM_ARG_VERBOSE) {
598 cam_error_print(device, ccb, CAM_ESF_ALL,
599 CAM_EPF_ALL, stderr);
609 scsistart(struct cam_device *device, int startstop, int loadeject,
610 int retry_count, int timeout)
615 ccb = cam_getccb(device);
618 * If we're stopping, send an ordered tag so the drive in question
619 * will finish any previously queued writes before stopping. If
620 * the device isn't capable of tagged queueing, or if tagged
621 * queueing is turned off, the tag action is a no-op.
623 scsi_start_stop(&ccb->csio,
624 /* retries */ retry_count,
626 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
628 /* start/stop */ startstop,
629 /* load_eject */ loadeject,
631 /* sense_len */ SSD_FULL_SIZE,
632 /* timeout */ timeout ? timeout : 120000);
634 /* Disable freezing the device queue */
635 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
637 if (arglist & CAM_ARG_ERR_RECOVER)
638 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
640 if (cam_send_ccb(device, ccb) < 0) {
641 perror("error sending start unit");
643 if (arglist & CAM_ARG_VERBOSE) {
644 cam_error_print(device, ccb, CAM_ESF_ALL,
645 CAM_EPF_ALL, stderr);
652 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
654 fprintf(stdout, "Unit started successfully");
656 fprintf(stdout,", Media loaded\n");
658 fprintf(stdout,"\n");
660 fprintf(stdout, "Unit stopped successfully");
662 fprintf(stdout, ", Media ejected\n");
664 fprintf(stdout, "\n");
670 "Error received from start unit command\n");
673 "Error received from stop unit command\n");
675 if (arglist & CAM_ARG_VERBOSE) {
676 cam_error_print(device, ccb, CAM_ESF_ALL,
677 CAM_EPF_ALL, stderr);
687 scsidoinquiry(struct cam_device *device, int argc, char **argv,
688 char *combinedopt, int retry_count, int timeout)
693 while ((c = getopt(argc, argv, combinedopt)) != -1) {
696 arglist |= CAM_ARG_GET_STDINQ;
699 arglist |= CAM_ARG_GET_XFERRATE;
702 arglist |= CAM_ARG_GET_SERIAL;
710 * If the user didn't specify any inquiry options, he wants all of
713 if ((arglist & CAM_ARG_INQ_MASK) == 0)
714 arglist |= CAM_ARG_INQ_MASK;
716 if (arglist & CAM_ARG_GET_STDINQ)
717 error = scsiinquiry(device, retry_count, timeout);
722 if (arglist & CAM_ARG_GET_SERIAL)
723 scsiserial(device, retry_count, timeout);
728 if (arglist & CAM_ARG_GET_XFERRATE)
729 error = camxferrate(device);
735 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
738 struct scsi_inquiry_data *inq_buf;
741 ccb = cam_getccb(device);
744 warnx("couldn't allocate CCB");
748 /* cam_getccb cleans up the header, caller has to zero the payload */
749 bzero(&(&ccb->ccb_h)[1],
750 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
752 inq_buf = (struct scsi_inquiry_data *)malloc(
753 sizeof(struct scsi_inquiry_data));
755 if (inq_buf == NULL) {
757 warnx("can't malloc memory for inquiry\n");
760 bzero(inq_buf, sizeof(*inq_buf));
763 * Note that although the size of the inquiry buffer is the full
764 * 256 bytes specified in the SCSI spec, we only tell the device
765 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
766 * two reasons for this:
768 * - The SCSI spec says that when a length field is only 1 byte,
769 * a value of 0 will be interpreted as 256. Therefore
770 * scsi_inquiry() will convert an inq_len (which is passed in as
771 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
772 * to 0. Evidently, very few devices meet the spec in that
773 * regard. Some devices, like many Seagate disks, take the 0 as
774 * 0, and don't return any data. One Pioneer DVD-R drive
775 * returns more data than the command asked for.
777 * So, since there are numerous devices that just don't work
778 * right with the full inquiry size, we don't send the full size.
780 * - The second reason not to use the full inquiry data length is
781 * that we don't need it here. The only reason we issue a
782 * standard inquiry is to get the vendor name, device name,
783 * and revision so scsi_print_inquiry() can print them.
785 * If, at some point in the future, more inquiry data is needed for
786 * some reason, this code should use a procedure similar to the
787 * probe code. i.e., issue a short inquiry, and determine from
788 * the additional length passed back from the device how much
789 * inquiry data the device supports. Once the amount the device
790 * supports is determined, issue an inquiry for that amount and no
795 scsi_inquiry(&ccb->csio,
796 /* retries */ retry_count,
798 /* tag_action */ MSG_SIMPLE_Q_TAG,
799 /* inq_buf */ (u_int8_t *)inq_buf,
800 /* inq_len */ SHORT_INQUIRY_LENGTH,
803 /* sense_len */ SSD_FULL_SIZE,
804 /* timeout */ timeout ? timeout : 5000);
806 /* Disable freezing the device queue */
807 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
809 if (arglist & CAM_ARG_ERR_RECOVER)
810 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
812 if (cam_send_ccb(device, ccb) < 0) {
813 perror("error sending SCSI inquiry");
815 if (arglist & CAM_ARG_VERBOSE) {
816 cam_error_print(device, ccb, CAM_ESF_ALL,
817 CAM_EPF_ALL, stderr);
824 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
827 if (arglist & CAM_ARG_VERBOSE) {
828 cam_error_print(device, ccb, CAM_ESF_ALL,
829 CAM_EPF_ALL, stderr);
840 fprintf(stdout, "%s%d: ", device->device_name,
841 device->dev_unit_num);
842 scsi_print_inquiry(inq_buf);
850 scsiserial(struct cam_device *device, int retry_count, int timeout)
853 struct scsi_vpd_unit_serial_number *serial_buf;
854 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
857 ccb = cam_getccb(device);
860 warnx("couldn't allocate CCB");
864 /* cam_getccb cleans up the header, caller has to zero the payload */
865 bzero(&(&ccb->ccb_h)[1],
866 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
868 serial_buf = (struct scsi_vpd_unit_serial_number *)
869 malloc(sizeof(*serial_buf));
871 if (serial_buf == NULL) {
873 warnx("can't malloc memory for serial number");
877 scsi_inquiry(&ccb->csio,
878 /*retries*/ retry_count,
880 /* tag_action */ MSG_SIMPLE_Q_TAG,
881 /* inq_buf */ (u_int8_t *)serial_buf,
882 /* inq_len */ sizeof(*serial_buf),
884 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
885 /* sense_len */ SSD_FULL_SIZE,
886 /* timeout */ timeout ? timeout : 5000);
888 /* Disable freezing the device queue */
889 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
891 if (arglist & CAM_ARG_ERR_RECOVER)
892 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
894 if (cam_send_ccb(device, ccb) < 0) {
895 warn("error getting serial number");
897 if (arglist & CAM_ARG_VERBOSE) {
898 cam_error_print(device, ccb, CAM_ESF_ALL,
899 CAM_EPF_ALL, stderr);
907 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
910 if (arglist & CAM_ARG_VERBOSE) {
911 cam_error_print(device, ccb, CAM_ESF_ALL,
912 CAM_EPF_ALL, stderr);
923 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
924 serial_num[serial_buf->length] = '\0';
926 if ((arglist & CAM_ARG_GET_STDINQ)
927 || (arglist & CAM_ARG_GET_XFERRATE))
928 fprintf(stdout, "%s%d: Serial Number ",
929 device->device_name, device->dev_unit_num);
931 fprintf(stdout, "%.60s\n", serial_num);
939 camxferrate(struct cam_device *device)
941 struct ccb_pathinq cpi;
948 if ((retval = get_cpi(device, &cpi)) != 0)
951 ccb = cam_getccb(device);
954 warnx("couldn't allocate CCB");
958 bzero(&(&ccb->ccb_h)[1],
959 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
961 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
962 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
964 if (((retval = cam_send_ccb(device, ccb)) < 0)
965 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
966 const char error_string[] = "error getting transfer settings";
973 if (arglist & CAM_ARG_VERBOSE)
974 cam_error_print(device, ccb, CAM_ESF_ALL,
975 CAM_EPF_ALL, stderr);
979 goto xferrate_bailout;
983 speed = cpi.base_transfer_speed;
985 if (ccb->cts.transport == XPORT_SPI) {
986 struct ccb_trans_settings_spi *spi =
987 &ccb->cts.xport_specific.spi;
989 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
990 freq = scsi_calc_syncsrate(spi->sync_period);
993 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
994 speed *= (0x01 << spi->bus_width);
996 } else if (ccb->cts.transport == XPORT_FC) {
997 struct ccb_trans_settings_fc *fc =
998 &ccb->cts.xport_specific.fc;
1000 if (fc->valid & CTS_FC_VALID_SPEED)
1001 speed = fc->bitrate;
1002 } else if (ccb->cts.transport == XPORT_SAS) {
1003 struct ccb_trans_settings_sas *sas =
1004 &ccb->cts.xport_specific.sas;
1006 if (sas->valid & CTS_SAS_VALID_SPEED)
1007 speed = sas->bitrate;
1008 } else if (ccb->cts.transport == XPORT_ATA) {
1009 struct ccb_trans_settings_ata *ata =
1010 &ccb->cts.xport_specific.ata;
1012 if (ata->valid & CTS_ATA_VALID_MODE)
1013 speed = ata_mode2speed(ata->mode);
1014 } else if (ccb->cts.transport == XPORT_SATA) {
1015 struct ccb_trans_settings_sata *sata =
1016 &ccb->cts.xport_specific.sata;
1018 if (sata->valid & CTS_SATA_VALID_REVISION)
1019 speed = ata_revision2speed(sata->revision);
1024 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1025 device->device_name, device->dev_unit_num,
1028 fprintf(stdout, "%s%d: %dKB/s transfers",
1029 device->device_name, device->dev_unit_num,
1033 if (ccb->cts.transport == XPORT_SPI) {
1034 struct ccb_trans_settings_spi *spi =
1035 &ccb->cts.xport_specific.spi;
1037 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1038 && (spi->sync_offset != 0))
1039 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1040 freq % 1000, spi->sync_offset);
1042 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1043 && (spi->bus_width > 0)) {
1044 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1045 && (spi->sync_offset != 0)) {
1046 fprintf(stdout, ", ");
1048 fprintf(stdout, " (");
1050 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1051 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1052 && (spi->sync_offset != 0)) {
1053 fprintf(stdout, ")");
1055 } else if (ccb->cts.transport == XPORT_ATA) {
1056 struct ccb_trans_settings_ata *ata =
1057 &ccb->cts.xport_specific.ata;
1060 if (ata->valid & CTS_ATA_VALID_MODE)
1061 printf("%s, ", ata_mode2string(ata->mode));
1062 if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0)
1063 printf("ATAPI %dbytes, ", ata->atapi);
1064 if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
1065 printf("PIO %dbytes", ata->bytecount);
1067 } else if (ccb->cts.transport == XPORT_SATA) {
1068 struct ccb_trans_settings_sata *sata =
1069 &ccb->cts.xport_specific.sata;
1072 if (sata->valid & CTS_SATA_VALID_REVISION)
1073 printf("SATA %d.x, ", sata->revision);
1076 if (sata->valid & CTS_SATA_VALID_MODE)
1077 printf("%s, ", ata_mode2string(sata->mode));
1078 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1079 printf("ATAPI %dbytes, ", sata->atapi);
1080 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1081 printf("PIO %dbytes", sata->bytecount);
1085 if (ccb->cts.protocol == PROTO_SCSI) {
1086 struct ccb_trans_settings_scsi *scsi =
1087 &ccb->cts.proto_specific.scsi;
1088 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1089 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1090 fprintf(stdout, ", Command Queueing Enabled");
1095 fprintf(stdout, "\n");
1105 atacapprint(struct ata_params *parm)
1107 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1108 ((u_int32_t)parm->lba_size_2 << 16);
1110 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1111 ((u_int64_t)parm->lba_size48_2 << 16) |
1112 ((u_int64_t)parm->lba_size48_3 << 32) |
1113 ((u_int64_t)parm->lba_size48_4 << 48);
1116 printf("protocol ");
1117 printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1118 if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1119 if (parm->satacapabilities & ATA_SATA_GEN3)
1120 printf(" SATA 3.x\n");
1121 else if (parm->satacapabilities & ATA_SATA_GEN2)
1122 printf(" SATA 2.x\n");
1123 else if (parm->satacapabilities & ATA_SATA_GEN1)
1124 printf(" SATA 1.x\n");
1130 printf("device model %.40s\n", parm->model);
1131 printf("firmware revision %.8s\n", parm->revision);
1132 printf("serial number %.20s\n", parm->serial);
1133 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1134 printf("WWN %02x%02x%02x%02x\n",
1135 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1137 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1138 printf("media serial number %.30s\n",
1139 parm->media_serial);
1142 printf("cylinders %d\n", parm->cylinders);
1143 printf("heads %d\n", parm->heads);
1144 printf("sectors/track %d\n", parm->sectors);
1145 printf("sector size logical %u, physical %lu, offset %lu\n",
1146 ata_logical_sector_size(parm),
1147 (unsigned long)ata_physical_sector_size(parm),
1148 (unsigned long)ata_logical_sector_offset(parm));
1150 if (parm->config == ATA_PROTO_CFA ||
1151 (parm->support.command2 & ATA_SUPPORT_CFA))
1152 printf("CFA supported\n");
1154 printf("LBA%ssupported ",
1155 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1157 printf("%d sectors\n", lbasize);
1161 printf("LBA48%ssupported ",
1162 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1164 printf("%ju sectors\n", (uintmax_t)lbasize48);
1168 printf("PIO supported PIO");
1169 switch (ata_max_pmode(parm)) {
1185 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1186 printf(" w/o IORDY");
1189 printf("DMA%ssupported ",
1190 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1191 if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1192 if (parm->mwdmamodes & 0xff) {
1194 if (parm->mwdmamodes & 0x04)
1196 else if (parm->mwdmamodes & 0x02)
1198 else if (parm->mwdmamodes & 0x01)
1202 if ((parm->atavalid & ATA_FLAG_88) &&
1203 (parm->udmamodes & 0xff)) {
1205 if (parm->udmamodes & 0x40)
1207 else if (parm->udmamodes & 0x20)
1209 else if (parm->udmamodes & 0x10)
1211 else if (parm->udmamodes & 0x08)
1213 else if (parm->udmamodes & 0x04)
1215 else if (parm->udmamodes & 0x02)
1217 else if (parm->udmamodes & 0x01)
1224 if (parm->media_rotation_rate == 1) {
1225 printf("media RPM non-rotating\n");
1226 } else if (parm->media_rotation_rate >= 0x0401 &&
1227 parm->media_rotation_rate <= 0xFFFE) {
1228 printf("media RPM %d\n",
1229 parm->media_rotation_rate);
1233 "Support Enabled Value Vendor\n");
1234 printf("read ahead %s %s\n",
1235 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1236 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1237 printf("write cache %s %s\n",
1238 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1239 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1240 printf("flush cache %s %s\n",
1241 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1242 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1243 printf("overlap %s\n",
1244 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1245 printf("Tagged Command Queuing (TCQ) %s %s",
1246 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1247 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1248 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1249 printf(" %d tags\n",
1250 ATA_QUEUE_LEN(parm->queue) + 1);
1253 printf("Native Command Queuing (NCQ) ");
1254 if (parm->satacapabilities != 0xffff &&
1255 (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1256 printf("yes %d tags\n",
1257 ATA_QUEUE_LEN(parm->queue) + 1);
1260 printf("SMART %s %s\n",
1261 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1262 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1263 printf("microcode download %s %s\n",
1264 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1265 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1266 printf("security %s %s\n",
1267 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1268 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1269 printf("power management %s %s\n",
1270 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1271 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1272 printf("advanced power management %s %s",
1273 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1274 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1275 if (parm->support.command2 & ATA_SUPPORT_APM) {
1276 printf(" %d/0x%02X\n",
1277 parm->apm_value, parm->apm_value);
1280 printf("automatic acoustic management %s %s",
1281 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1282 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1283 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1284 printf(" %d/0x%02X %d/0x%02X\n",
1285 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1286 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1287 ATA_ACOUSTIC_VENDOR(parm->acoustic),
1288 ATA_ACOUSTIC_VENDOR(parm->acoustic));
1291 printf("media status notification %s %s\n",
1292 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1293 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1294 printf("power-up in Standby %s %s\n",
1295 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1296 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1297 printf("write-read-verify %s %s",
1298 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1299 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1300 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1301 printf(" %d/0x%x\n",
1302 parm->wrv_mode, parm->wrv_mode);
1305 printf("unload %s %s\n",
1306 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1307 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1308 printf("free-fall %s %s\n",
1309 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1310 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1311 printf("data set management (TRIM) %s\n",
1312 parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1316 ataidentify(struct cam_device *device, int retry_count, int timeout)
1319 struct ata_params *ident_buf;
1320 struct ccb_getdev cgd;
1324 if (get_cgd(device, &cgd) != 0) {
1325 warnx("couldn't get CGD");
1328 ccb = cam_getccb(device);
1331 warnx("couldn't allocate CCB");
1335 /* cam_getccb cleans up the header, caller has to zero the payload */
1336 bzero(&(&ccb->ccb_h)[1],
1337 sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1339 ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1343 warnx("can't malloc memory for identify\n");
1346 bzero(ptr, sizeof(struct ata_params));
1348 cam_fill_ataio(&ccb->ataio,
1351 /*flags*/CAM_DIR_IN,
1353 /*data_ptr*/(u_int8_t *)ptr,
1354 /*dxfer_len*/sizeof(struct ata_params),
1355 timeout ? timeout : 30 * 1000);
1356 if (cgd.protocol == PROTO_ATA)
1357 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1359 ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1361 /* Disable freezing the device queue */
1362 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1364 if (arglist & CAM_ARG_ERR_RECOVER)
1365 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1367 if (cam_send_ccb(device, ccb) < 0) {
1368 perror("error sending ATA identify");
1370 if (arglist & CAM_ARG_VERBOSE) {
1371 cam_error_print(device, ccb, CAM_ESF_ALL,
1372 CAM_EPF_ALL, stderr);
1380 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1383 if (arglist & CAM_ARG_VERBOSE) {
1384 cam_error_print(device, ccb, CAM_ESF_ALL,
1385 CAM_EPF_ALL, stderr);
1396 for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1397 ptr[i] = le16toh(ptr[i]);
1398 if (arglist & CAM_ARG_VERBOSE) {
1399 fprintf(stdout, "%s%d: Raw identify data:\n",
1400 device->device_name, device->dev_unit_num);
1401 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1403 fprintf(stdout, " %3d: ", i);
1404 fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1406 fprintf(stdout, "\n");
1409 ident_buf = (struct ata_params *)ptr;
1410 if (strncmp(ident_buf->model, "FX", 2) &&
1411 strncmp(ident_buf->model, "NEC", 3) &&
1412 strncmp(ident_buf->model, "Pioneer", 7) &&
1413 strncmp(ident_buf->model, "SHARP", 5)) {
1414 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1415 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1416 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1417 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1419 ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1420 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1421 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1422 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1423 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1424 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1425 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1426 ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1427 sizeof(ident_buf->media_serial));
1429 fprintf(stdout, "%s%d: ", device->device_name,
1430 device->dev_unit_num);
1431 ata_print_ident(ident_buf);
1432 camxferrate(device);
1433 atacapprint(ident_buf);
1439 #endif /* MINIMALISTIC */
1442 * Parse out a bus, or a bus, target and lun in the following
1448 * Returns the number of parsed components, or 0.
1451 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1456 while (isspace(*tstr) && (*tstr != '\0'))
1459 tmpstr = (char *)strtok(tstr, ":");
1460 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1461 *bus = strtol(tmpstr, NULL, 0);
1462 *arglst |= CAM_ARG_BUS;
1464 tmpstr = (char *)strtok(NULL, ":");
1465 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1466 *target = strtol(tmpstr, NULL, 0);
1467 *arglst |= CAM_ARG_TARGET;
1469 tmpstr = (char *)strtok(NULL, ":");
1470 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1471 *lun = strtol(tmpstr, NULL, 0);
1472 *arglst |= CAM_ARG_LUN;
1482 dorescan_or_reset(int argc, char **argv, int rescan)
1484 static const char must[] =
1485 "you must specify \"all\", a bus, or a bus:target:lun to %s";
1487 int bus = -1, target = -1, lun = -1;
1491 warnx(must, rescan? "rescan" : "reset");
1495 tstr = argv[optind];
1496 while (isspace(*tstr) && (*tstr != '\0'))
1498 if (strncasecmp(tstr, "all", strlen("all")) == 0)
1499 arglist |= CAM_ARG_BUS;
1501 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1502 if (rv != 1 && rv != 3) {
1503 warnx(must, rescan? "rescan" : "reset");
1508 if ((arglist & CAM_ARG_BUS)
1509 && (arglist & CAM_ARG_TARGET)
1510 && (arglist & CAM_ARG_LUN))
1511 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1513 error = rescan_or_reset_bus(bus, rescan);
1519 rescan_or_reset_bus(int bus, int rescan)
1521 union ccb ccb, matchccb;
1527 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1528 warnx("error opening transport layer device %s", XPT_DEVICE);
1529 warn("%s", XPT_DEVICE);
1534 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1535 ccb.ccb_h.path_id = bus;
1536 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1537 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1538 ccb.crcn.flags = CAM_FLAG_NONE;
1540 /* run this at a low priority */
1541 ccb.ccb_h.pinfo.priority = 5;
1543 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1544 warn("CAMIOCOMMAND ioctl failed");
1549 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1550 fprintf(stdout, "%s of bus %d was successful\n",
1551 rescan ? "Re-scan" : "Reset", bus);
1553 fprintf(stdout, "%s of bus %d returned error %#x\n",
1554 rescan ? "Re-scan" : "Reset", bus,
1555 ccb.ccb_h.status & CAM_STATUS_MASK);
1566 * The right way to handle this is to modify the xpt so that it can
1567 * handle a wildcarded bus in a rescan or reset CCB. At the moment
1568 * that isn't implemented, so instead we enumerate the busses and
1569 * send the rescan or reset to those busses in the case where the
1570 * given bus is -1 (wildcard). We don't send a rescan or reset
1571 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1572 * no-op, sending a rescan to the xpt bus would result in a status of
1575 bzero(&(&matchccb.ccb_h)[1],
1576 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1577 matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1578 matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
1579 bufsize = sizeof(struct dev_match_result) * 20;
1580 matchccb.cdm.match_buf_len = bufsize;
1581 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1582 if (matchccb.cdm.matches == NULL) {
1583 warnx("can't malloc memory for matches");
1587 matchccb.cdm.num_matches = 0;
1589 matchccb.cdm.num_patterns = 1;
1590 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1592 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1593 matchccb.cdm.pattern_buf_len);
1594 if (matchccb.cdm.patterns == NULL) {
1595 warnx("can't malloc memory for patterns");
1599 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1600 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1605 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1606 warn("CAMIOCOMMAND ioctl failed");
1611 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1612 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1613 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1614 warnx("got CAM error %#x, CDM error %d\n",
1615 matchccb.ccb_h.status, matchccb.cdm.status);
1620 for (i = 0; i < matchccb.cdm.num_matches; i++) {
1621 struct bus_match_result *bus_result;
1623 /* This shouldn't happen. */
1624 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1627 bus_result = &matchccb.cdm.matches[i].result.bus_result;
1630 * We don't want to rescan or reset the xpt bus.
1633 if ((int)bus_result->path_id == -1)
1636 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1638 ccb.ccb_h.path_id = bus_result->path_id;
1639 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1640 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1641 ccb.crcn.flags = CAM_FLAG_NONE;
1643 /* run this at a low priority */
1644 ccb.ccb_h.pinfo.priority = 5;
1646 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1647 warn("CAMIOCOMMAND ioctl failed");
1652 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1653 fprintf(stdout, "%s of bus %d was successful\n",
1654 rescan? "Re-scan" : "Reset",
1655 bus_result->path_id);
1658 * Don't bail out just yet, maybe the other
1659 * rescan or reset commands will complete
1662 fprintf(stderr, "%s of bus %d returned error "
1663 "%#x\n", rescan? "Re-scan" : "Reset",
1664 bus_result->path_id,
1665 ccb.ccb_h.status & CAM_STATUS_MASK);
1669 } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1670 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1677 if (matchccb.cdm.patterns != NULL)
1678 free(matchccb.cdm.patterns);
1679 if (matchccb.cdm.matches != NULL)
1680 free(matchccb.cdm.matches);
1686 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1689 struct cam_device *device;
1695 warnx("invalid bus number %d", bus);
1700 warnx("invalid target number %d", target);
1705 warnx("invalid lun number %d", lun);
1711 bzero(&ccb, sizeof(union ccb));
1714 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1715 warnx("error opening transport layer device %s\n",
1717 warn("%s", XPT_DEVICE);
1721 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1722 if (device == NULL) {
1723 warnx("%s", cam_errbuf);
1728 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1729 ccb.ccb_h.path_id = bus;
1730 ccb.ccb_h.target_id = target;
1731 ccb.ccb_h.target_lun = lun;
1732 ccb.ccb_h.timeout = 5000;
1733 ccb.crcn.flags = CAM_FLAG_NONE;
1735 /* run this at a low priority */
1736 ccb.ccb_h.pinfo.priority = 5;
1739 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1740 warn("CAMIOCOMMAND ioctl failed");
1745 if (cam_send_ccb(device, &ccb) < 0) {
1746 warn("error sending XPT_RESET_DEV CCB");
1747 cam_close_device(device);
1755 cam_close_device(device);
1758 * An error code of CAM_BDR_SENT is normal for a BDR request.
1760 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1762 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1763 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1764 scan? "Re-scan" : "Reset", bus, target, lun);
1767 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1768 scan? "Re-scan" : "Reset", bus, target, lun,
1769 ccb.ccb_h.status & CAM_STATUS_MASK);
1774 #ifndef MINIMALISTIC
1776 readdefects(struct cam_device *device, int argc, char **argv,
1777 char *combinedopt, int retry_count, int timeout)
1779 union ccb *ccb = NULL;
1780 struct scsi_read_defect_data_10 *rdd_cdb;
1781 u_int8_t *defect_list = NULL;
1782 u_int32_t dlist_length = 65000;
1783 u_int32_t returned_length = 0;
1784 u_int32_t num_returned = 0;
1785 u_int8_t returned_format;
1788 int lists_specified = 0;
1790 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1796 while (isspace(*tstr) && (*tstr != '\0'))
1798 if (strcmp(tstr, "block") == 0)
1799 arglist |= CAM_ARG_FORMAT_BLOCK;
1800 else if (strcmp(tstr, "bfi") == 0)
1801 arglist |= CAM_ARG_FORMAT_BFI;
1802 else if (strcmp(tstr, "phys") == 0)
1803 arglist |= CAM_ARG_FORMAT_PHYS;
1806 warnx("invalid defect format %s", tstr);
1807 goto defect_bailout;
1812 arglist |= CAM_ARG_GLIST;
1815 arglist |= CAM_ARG_PLIST;
1822 ccb = cam_getccb(device);
1825 * Hopefully 65000 bytes is enough to hold the defect list. If it
1826 * isn't, the disk is probably dead already. We'd have to go with
1827 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1830 defect_list = malloc(dlist_length);
1831 if (defect_list == NULL) {
1832 warnx("can't malloc memory for defect list");
1834 goto defect_bailout;
1837 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1840 * cam_getccb() zeros the CCB header only. So we need to zero the
1841 * payload portion of the ccb.
1843 bzero(&(&ccb->ccb_h)[1],
1844 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1846 cam_fill_csio(&ccb->csio,
1847 /*retries*/ retry_count,
1849 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1850 CAM_PASS_ERR_RECOVER : 0),
1851 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1852 /*data_ptr*/ defect_list,
1853 /*dxfer_len*/ dlist_length,
1854 /*sense_len*/ SSD_FULL_SIZE,
1855 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1856 /*timeout*/ timeout ? timeout : 5000);
1858 rdd_cdb->opcode = READ_DEFECT_DATA_10;
1859 if (arglist & CAM_ARG_FORMAT_BLOCK)
1860 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1861 else if (arglist & CAM_ARG_FORMAT_BFI)
1862 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1863 else if (arglist & CAM_ARG_FORMAT_PHYS)
1864 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1867 warnx("no defect list format specified");
1868 goto defect_bailout;
1870 if (arglist & CAM_ARG_PLIST) {
1871 rdd_cdb->format |= SRDD10_PLIST;
1875 if (arglist & CAM_ARG_GLIST) {
1876 rdd_cdb->format |= SRDD10_GLIST;
1880 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1882 /* Disable freezing the device queue */
1883 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1885 if (cam_send_ccb(device, ccb) < 0) {
1886 perror("error reading defect list");
1888 if (arglist & CAM_ARG_VERBOSE) {
1889 cam_error_print(device, ccb, CAM_ESF_ALL,
1890 CAM_EPF_ALL, stderr);
1894 goto defect_bailout;
1897 returned_length = scsi_2btoul(((struct
1898 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1900 returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1901 defect_list)->format;
1903 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1904 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1905 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1906 struct scsi_sense_data *sense;
1907 int error_code, sense_key, asc, ascq;
1909 sense = &ccb->csio.sense_data;
1910 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1913 * According to the SCSI spec, if the disk doesn't support
1914 * the requested format, it will generally return a sense
1915 * key of RECOVERED ERROR, and an additional sense code
1916 * of "DEFECT LIST NOT FOUND". So, we check for that, and
1917 * also check to make sure that the returned length is
1918 * greater than 0, and then print out whatever format the
1921 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1922 && (asc == 0x1c) && (ascq == 0x00)
1923 && (returned_length > 0)) {
1924 warnx("requested defect format not available");
1925 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1926 case SRDD10_BLOCK_FORMAT:
1927 warnx("Device returned block format");
1929 case SRDD10_BYTES_FROM_INDEX_FORMAT:
1930 warnx("Device returned bytes from index"
1933 case SRDD10_PHYSICAL_SECTOR_FORMAT:
1934 warnx("Device returned physical sector format");
1938 warnx("Device returned unknown defect"
1939 " data format %#x", returned_format);
1940 goto defect_bailout;
1941 break; /* NOTREACHED */
1945 warnx("Error returned from read defect data command");
1946 if (arglist & CAM_ARG_VERBOSE)
1947 cam_error_print(device, ccb, CAM_ESF_ALL,
1948 CAM_EPF_ALL, stderr);
1949 goto defect_bailout;
1951 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1953 warnx("Error returned from read defect data command");
1954 if (arglist & CAM_ARG_VERBOSE)
1955 cam_error_print(device, ccb, CAM_ESF_ALL,
1956 CAM_EPF_ALL, stderr);
1957 goto defect_bailout;
1961 * XXX KDM I should probably clean up the printout format for the
1964 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1965 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1967 struct scsi_defect_desc_phys_sector *dlist;
1969 dlist = (struct scsi_defect_desc_phys_sector *)
1971 sizeof(struct scsi_read_defect_data_hdr_10));
1973 num_returned = returned_length /
1974 sizeof(struct scsi_defect_desc_phys_sector);
1976 fprintf(stderr, "Got %d defect", num_returned);
1978 if ((lists_specified == 0) || (num_returned == 0)) {
1979 fprintf(stderr, "s.\n");
1981 } else if (num_returned == 1)
1982 fprintf(stderr, ":\n");
1984 fprintf(stderr, "s:\n");
1986 for (i = 0; i < num_returned; i++) {
1987 fprintf(stdout, "%d:%d:%d\n",
1988 scsi_3btoul(dlist[i].cylinder),
1990 scsi_4btoul(dlist[i].sector));
1994 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1996 struct scsi_defect_desc_bytes_from_index *dlist;
1998 dlist = (struct scsi_defect_desc_bytes_from_index *)
2000 sizeof(struct scsi_read_defect_data_hdr_10));
2002 num_returned = returned_length /
2003 sizeof(struct scsi_defect_desc_bytes_from_index);
2005 fprintf(stderr, "Got %d defect", num_returned);
2007 if ((lists_specified == 0) || (num_returned == 0)) {
2008 fprintf(stderr, "s.\n");
2010 } else if (num_returned == 1)
2011 fprintf(stderr, ":\n");
2013 fprintf(stderr, "s:\n");
2015 for (i = 0; i < num_returned; i++) {
2016 fprintf(stdout, "%d:%d:%d\n",
2017 scsi_3btoul(dlist[i].cylinder),
2019 scsi_4btoul(dlist[i].bytes_from_index));
2023 case SRDDH10_BLOCK_FORMAT:
2025 struct scsi_defect_desc_block *dlist;
2027 dlist = (struct scsi_defect_desc_block *)(defect_list +
2028 sizeof(struct scsi_read_defect_data_hdr_10));
2030 num_returned = returned_length /
2031 sizeof(struct scsi_defect_desc_block);
2033 fprintf(stderr, "Got %d defect", num_returned);
2035 if ((lists_specified == 0) || (num_returned == 0)) {
2036 fprintf(stderr, "s.\n");
2038 } else if (num_returned == 1)
2039 fprintf(stderr, ":\n");
2041 fprintf(stderr, "s:\n");
2043 for (i = 0; i < num_returned; i++)
2044 fprintf(stdout, "%u\n",
2045 scsi_4btoul(dlist[i].address));
2049 fprintf(stderr, "Unknown defect format %d\n",
2050 returned_format & SRDDH10_DLIST_FORMAT_MASK);
2056 if (defect_list != NULL)
2064 #endif /* MINIMALISTIC */
2068 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2072 ccb = cam_getccb(device);
2078 #ifndef MINIMALISTIC
2080 mode_sense(struct cam_device *device, int mode_page, int page_control,
2081 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2086 ccb = cam_getccb(device);
2089 errx(1, "mode_sense: couldn't allocate CCB");
2091 bzero(&(&ccb->ccb_h)[1],
2092 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2094 scsi_mode_sense(&ccb->csio,
2095 /* retries */ retry_count,
2097 /* tag_action */ MSG_SIMPLE_Q_TAG,
2099 /* page_code */ page_control << 6,
2100 /* page */ mode_page,
2101 /* param_buf */ data,
2102 /* param_len */ datalen,
2103 /* sense_len */ SSD_FULL_SIZE,
2104 /* timeout */ timeout ? timeout : 5000);
2106 if (arglist & CAM_ARG_ERR_RECOVER)
2107 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2109 /* Disable freezing the device queue */
2110 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2112 if (((retval = cam_send_ccb(device, ccb)) < 0)
2113 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2114 if (arglist & CAM_ARG_VERBOSE) {
2115 cam_error_print(device, ccb, CAM_ESF_ALL,
2116 CAM_EPF_ALL, stderr);
2119 cam_close_device(device);
2121 err(1, "error sending mode sense command");
2123 errx(1, "error sending mode sense command");
2130 mode_select(struct cam_device *device, int save_pages, int retry_count,
2131 int timeout, u_int8_t *data, int datalen)
2136 ccb = cam_getccb(device);
2139 errx(1, "mode_select: couldn't allocate CCB");
2141 bzero(&(&ccb->ccb_h)[1],
2142 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2144 scsi_mode_select(&ccb->csio,
2145 /* retries */ retry_count,
2147 /* tag_action */ MSG_SIMPLE_Q_TAG,
2148 /* scsi_page_fmt */ 1,
2149 /* save_pages */ save_pages,
2150 /* param_buf */ data,
2151 /* param_len */ datalen,
2152 /* sense_len */ SSD_FULL_SIZE,
2153 /* timeout */ timeout ? timeout : 5000);
2155 if (arglist & CAM_ARG_ERR_RECOVER)
2156 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2158 /* Disable freezing the device queue */
2159 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2161 if (((retval = cam_send_ccb(device, ccb)) < 0)
2162 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2163 if (arglist & CAM_ARG_VERBOSE) {
2164 cam_error_print(device, ccb, CAM_ESF_ALL,
2165 CAM_EPF_ALL, stderr);
2168 cam_close_device(device);
2171 err(1, "error sending mode select command");
2173 errx(1, "error sending mode select command");
2181 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2182 int retry_count, int timeout)
2184 int c, mode_page = -1, page_control = 0;
2185 int binary = 0, list = 0;
2187 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2193 arglist |= CAM_ARG_DBD;
2196 arglist |= CAM_ARG_MODE_EDIT;
2202 mode_page = strtol(optarg, NULL, 0);
2204 errx(1, "invalid mode page %d", mode_page);
2207 page_control = strtol(optarg, NULL, 0);
2208 if ((page_control < 0) || (page_control > 3))
2209 errx(1, "invalid page control field %d",
2211 arglist |= CAM_ARG_PAGE_CNTL;
2218 if (mode_page == -1 && list == 0)
2219 errx(1, "you must specify a mode page!");
2222 mode_list(device, page_control, arglist & CAM_ARG_DBD,
2223 retry_count, timeout);
2225 mode_edit(device, mode_page, page_control,
2226 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2227 retry_count, timeout);
2232 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2233 int retry_count, int timeout)
2236 u_int32_t flags = CAM_DIR_NONE;
2237 u_int8_t *data_ptr = NULL;
2239 u_int8_t atacmd[12];
2240 struct get_hook hook;
2241 int c, data_bytes = 0;
2247 char *datastr = NULL, *tstr, *resstr = NULL;
2249 int fd_data = 0, fd_res = 0;
2252 ccb = cam_getccb(device);
2255 warnx("scsicmd: error allocating ccb");
2259 bzero(&(&ccb->ccb_h)[1],
2260 sizeof(union ccb) - sizeof(struct ccb_hdr));
2262 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2266 while (isspace(*tstr) && (*tstr != '\0'))
2268 hook.argc = argc - optind;
2269 hook.argv = argv + optind;
2271 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2274 * Increment optind by the number of arguments the
2275 * encoding routine processed. After each call to
2276 * getopt(3), optind points to the argument that
2277 * getopt should process _next_. In this case,
2278 * that means it points to the first command string
2279 * argument, if there is one. Once we increment
2280 * this, it should point to either the next command
2281 * line argument, or it should be past the end of
2288 while (isspace(*tstr) && (*tstr != '\0'))
2290 hook.argc = argc - optind;
2291 hook.argv = argv + optind;
2293 cdb_len = buff_encode_visit(cdb, sizeof(cdb), 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
2315 if (arglist & CAM_ARG_CMD_OUT) {
2316 warnx("command must either be "
2317 "read or write, not both");
2319 goto scsicmd_bailout;
2321 arglist |= CAM_ARG_CMD_IN;
2323 data_bytes = strtol(optarg, NULL, 0);
2324 if (data_bytes <= 0) {
2325 warnx("invalid number of input bytes %d",
2328 goto scsicmd_bailout;
2330 hook.argc = argc - optind;
2331 hook.argv = argv + optind;
2334 datastr = cget(&hook, NULL);
2336 * If the user supplied "-" instead of a format, he
2337 * wants the data to be written to stdout.
2339 if ((datastr != NULL)
2340 && (datastr[0] == '-'))
2343 data_ptr = (u_int8_t *)malloc(data_bytes);
2344 if (data_ptr == NULL) {
2345 warnx("can't malloc memory for data_ptr");
2347 goto scsicmd_bailout;
2351 if (arglist & CAM_ARG_CMD_IN) {
2352 warnx("command must either be "
2353 "read or write, not both");
2355 goto scsicmd_bailout;
2357 arglist |= CAM_ARG_CMD_OUT;
2358 flags = CAM_DIR_OUT;
2359 data_bytes = strtol(optarg, NULL, 0);
2360 if (data_bytes <= 0) {
2361 warnx("invalid number of output bytes %d",
2364 goto scsicmd_bailout;
2366 hook.argc = argc - optind;
2367 hook.argv = argv + optind;
2369 datastr = cget(&hook, NULL);
2370 data_ptr = (u_int8_t *)malloc(data_bytes);
2371 if (data_ptr == NULL) {
2372 warnx("can't malloc memory for data_ptr");
2374 goto scsicmd_bailout;
2376 bzero(data_ptr, data_bytes);
2378 * If the user supplied "-" instead of a format, he
2379 * wants the data to be read from stdin.
2381 if ((datastr != NULL)
2382 && (datastr[0] == '-'))
2385 buff_encode_visit(data_ptr, data_bytes, datastr,
2391 hook.argc = argc - optind;
2392 hook.argv = argv + optind;
2394 resstr = cget(&hook, NULL);
2395 if ((resstr != NULL) && (resstr[0] == '-'))
2405 * If fd_data is set, and we're writing to the device, we need to
2406 * read the data the user wants written from stdin.
2408 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2410 int amt_to_read = data_bytes;
2411 u_int8_t *buf_ptr = data_ptr;
2413 for (amt_read = 0; amt_to_read > 0;
2414 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2415 if (amt_read == -1) {
2416 warn("error reading data from stdin");
2418 goto scsicmd_bailout;
2420 amt_to_read -= amt_read;
2421 buf_ptr += amt_read;
2425 if (arglist & CAM_ARG_ERR_RECOVER)
2426 flags |= CAM_PASS_ERR_RECOVER;
2428 /* Disable freezing the device queue */
2429 flags |= CAM_DEV_QFRZDIS;
2433 * This is taken from the SCSI-3 draft spec.
2434 * (T10/1157D revision 0.3)
2435 * The top 3 bits of an opcode are the group code.
2436 * The next 5 bits are the command code.
2437 * Group 0: six byte commands
2438 * Group 1: ten byte commands
2439 * Group 2: ten byte commands
2441 * Group 4: sixteen byte commands
2442 * Group 5: twelve byte commands
2443 * Group 6: vendor specific
2444 * Group 7: vendor specific
2446 switch((cdb[0] >> 5) & 0x7) {
2457 /* computed by buff_encode_visit */
2468 * We should probably use csio_build_visit or something like that
2469 * here, but it's easier to encode arguments as you go. The
2470 * alternative would be skipping the CDB argument and then encoding
2471 * it here, since we've got the data buffer argument by now.
2473 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2475 cam_fill_csio(&ccb->csio,
2476 /*retries*/ retry_count,
2479 /*tag_action*/ MSG_SIMPLE_Q_TAG,
2480 /*data_ptr*/ data_ptr,
2481 /*dxfer_len*/ data_bytes,
2482 /*sense_len*/ SSD_FULL_SIZE,
2483 /*cdb_len*/ cdb_len,
2484 /*timeout*/ timeout ? timeout : 5000);
2487 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2489 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2491 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2493 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2495 cam_fill_ataio(&ccb->ataio,
2496 /*retries*/ retry_count,
2500 /*data_ptr*/ data_ptr,
2501 /*dxfer_len*/ data_bytes,
2502 /*timeout*/ timeout ? timeout : 5000);
2505 if (((retval = cam_send_ccb(device, ccb)) < 0)
2506 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2507 const char *warnstr = "error sending command";
2514 if (arglist & CAM_ARG_VERBOSE) {
2515 cam_error_print(device, ccb, CAM_ESF_ALL,
2516 CAM_EPF_ALL, stderr);
2520 goto scsicmd_bailout;
2523 if (atacmd_len && need_res) {
2525 buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2527 fprintf(stdout, "\n");
2530 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2531 ccb->ataio.res.status,
2532 ccb->ataio.res.error,
2533 ccb->ataio.res.lba_low,
2534 ccb->ataio.res.lba_mid,
2535 ccb->ataio.res.lba_high,
2536 ccb->ataio.res.device,
2537 ccb->ataio.res.lba_low_exp,
2538 ccb->ataio.res.lba_mid_exp,
2539 ccb->ataio.res.lba_high_exp,
2540 ccb->ataio.res.sector_count,
2541 ccb->ataio.res.sector_count_exp);
2546 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2547 && (arglist & CAM_ARG_CMD_IN)
2548 && (data_bytes > 0)) {
2550 buff_decode_visit(data_ptr, data_bytes, datastr,
2552 fprintf(stdout, "\n");
2554 ssize_t amt_written;
2555 int amt_to_write = data_bytes;
2556 u_int8_t *buf_ptr = data_ptr;
2558 for (amt_written = 0; (amt_to_write > 0) &&
2559 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2560 amt_to_write -= amt_written;
2561 buf_ptr += amt_written;
2563 if (amt_written == -1) {
2564 warn("error writing data to stdout");
2566 goto scsicmd_bailout;
2567 } else if ((amt_written == 0)
2568 && (amt_to_write > 0)) {
2569 warnx("only wrote %u bytes out of %u",
2570 data_bytes - amt_to_write, data_bytes);
2577 if ((data_bytes > 0) && (data_ptr != NULL))
2586 camdebug(int argc, char **argv, char *combinedopt)
2589 int bus = -1, target = -1, lun = -1;
2590 char *tstr, *tmpstr = NULL;
2594 bzero(&ccb, sizeof(union ccb));
2596 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2599 arglist |= CAM_ARG_DEBUG_INFO;
2600 ccb.cdbg.flags |= CAM_DEBUG_INFO;
2603 arglist |= CAM_ARG_DEBUG_PERIPH;
2604 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2607 arglist |= CAM_ARG_DEBUG_SUBTRACE;
2608 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2611 arglist |= CAM_ARG_DEBUG_TRACE;
2612 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2615 arglist |= CAM_ARG_DEBUG_XPT;
2616 ccb.cdbg.flags |= CAM_DEBUG_XPT;
2619 arglist |= CAM_ARG_DEBUG_CDB;
2620 ccb.cdbg.flags |= CAM_DEBUG_CDB;
2627 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2628 warnx("error opening transport layer device %s", XPT_DEVICE);
2629 warn("%s", XPT_DEVICE);
2636 warnx("you must specify \"off\", \"all\" or a bus,");
2637 warnx("bus:target, or bus:target:lun");
2644 while (isspace(*tstr) && (*tstr != '\0'))
2647 if (strncmp(tstr, "off", 3) == 0) {
2648 ccb.cdbg.flags = CAM_DEBUG_NONE;
2649 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2650 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2652 } else if (strncmp(tstr, "all", 3) != 0) {
2653 tmpstr = (char *)strtok(tstr, ":");
2654 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2655 bus = strtol(tmpstr, NULL, 0);
2656 arglist |= CAM_ARG_BUS;
2657 tmpstr = (char *)strtok(NULL, ":");
2658 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2659 target = strtol(tmpstr, NULL, 0);
2660 arglist |= CAM_ARG_TARGET;
2661 tmpstr = (char *)strtok(NULL, ":");
2662 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2663 lun = strtol(tmpstr, NULL, 0);
2664 arglist |= CAM_ARG_LUN;
2669 warnx("you must specify \"all\", \"off\", or a bus,");
2670 warnx("bus:target, or bus:target:lun to debug");
2676 ccb.ccb_h.func_code = XPT_DEBUG;
2677 ccb.ccb_h.path_id = bus;
2678 ccb.ccb_h.target_id = target;
2679 ccb.ccb_h.target_lun = lun;
2681 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2682 warn("CAMIOCOMMAND ioctl failed");
2687 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2688 CAM_FUNC_NOTAVAIL) {
2689 warnx("CAM debugging not available");
2690 warnx("you need to put options CAMDEBUG in"
2691 " your kernel config file!");
2693 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2695 warnx("XPT_DEBUG CCB failed with status %#x",
2699 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2701 "Debugging turned off\n");
2704 "Debugging enabled for "
2717 tagcontrol(struct cam_device *device, int argc, char **argv,
2727 ccb = cam_getccb(device);
2730 warnx("tagcontrol: error allocating ccb");
2734 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2737 numtags = strtol(optarg, NULL, 0);
2739 warnx("tag count %d is < 0", numtags);
2741 goto tagcontrol_bailout;
2752 cam_path_string(device, pathstr, sizeof(pathstr));
2755 bzero(&(&ccb->ccb_h)[1],
2756 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2757 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2758 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
2759 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2760 ccb->crs.openings = numtags;
2763 if (cam_send_ccb(device, ccb) < 0) {
2764 perror("error sending XPT_REL_SIMQ CCB");
2766 goto tagcontrol_bailout;
2769 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2770 warnx("XPT_REL_SIMQ CCB failed");
2771 cam_error_print(device, ccb, CAM_ESF_ALL,
2772 CAM_EPF_ALL, stderr);
2774 goto tagcontrol_bailout;
2779 fprintf(stdout, "%stagged openings now %d\n",
2780 pathstr, ccb->crs.openings);
2783 bzero(&(&ccb->ccb_h)[1],
2784 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2786 ccb->ccb_h.func_code = XPT_GDEV_STATS;
2788 if (cam_send_ccb(device, ccb) < 0) {
2789 perror("error sending XPT_GDEV_STATS CCB");
2791 goto tagcontrol_bailout;
2794 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2795 warnx("XPT_GDEV_STATS CCB failed");
2796 cam_error_print(device, ccb, CAM_ESF_ALL,
2797 CAM_EPF_ALL, stderr);
2799 goto tagcontrol_bailout;
2802 if (arglist & CAM_ARG_VERBOSE) {
2803 fprintf(stdout, "%s", pathstr);
2804 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
2805 fprintf(stdout, "%s", pathstr);
2806 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
2807 fprintf(stdout, "%s", pathstr);
2808 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2809 fprintf(stdout, "%s", pathstr);
2810 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued);
2811 fprintf(stdout, "%s", pathstr);
2812 fprintf(stdout, "held %d\n", ccb->cgds.held);
2813 fprintf(stdout, "%s", pathstr);
2814 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
2815 fprintf(stdout, "%s", pathstr);
2816 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
2819 fprintf(stdout, "%s", pathstr);
2820 fprintf(stdout, "device openings: ");
2822 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2823 ccb->cgds.dev_active);
2833 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2837 cam_path_string(device, pathstr, sizeof(pathstr));
2839 if (cts->transport == XPORT_SPI) {
2840 struct ccb_trans_settings_spi *spi =
2841 &cts->xport_specific.spi;
2843 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2845 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2848 if (spi->sync_offset != 0) {
2851 freq = scsi_calc_syncsrate(spi->sync_period);
2852 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2853 pathstr, freq / 1000, freq % 1000);
2857 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2858 fprintf(stdout, "%soffset: %d\n", pathstr,
2862 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2863 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2864 (0x01 << spi->bus_width) * 8);
2867 if (spi->valid & CTS_SPI_VALID_DISC) {
2868 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2869 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2870 "enabled" : "disabled");
2873 if (cts->transport == XPORT_ATA) {
2874 struct ccb_trans_settings_ata *ata =
2875 &cts->xport_specific.ata;
2877 if ((ata->valid & CTS_ATA_VALID_MODE) != 0) {
2878 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2879 ata_mode2string(ata->mode));
2881 if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2882 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2885 if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2886 fprintf(stdout, "%sPIO transaction length: %d\n",
2887 pathstr, ata->bytecount);
2890 if (cts->transport == XPORT_SATA) {
2891 struct ccb_trans_settings_sata *sata =
2892 &cts->xport_specific.sata;
2894 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2895 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2898 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2899 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2900 ata_mode2string(sata->mode));
2902 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2903 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2906 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2907 fprintf(stdout, "%sPIO transaction length: %d\n",
2908 pathstr, sata->bytecount);
2910 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2911 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2914 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2915 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2918 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2919 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2923 if (cts->protocol == PROTO_SCSI) {
2924 struct ccb_trans_settings_scsi *scsi=
2925 &cts->proto_specific.scsi;
2927 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2928 fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2929 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2930 "enabled" : "disabled");
2937 * Get a path inquiry CCB for the specified device.
2940 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2945 ccb = cam_getccb(device);
2947 warnx("get_cpi: couldn't allocate CCB");
2950 bzero(&(&ccb->ccb_h)[1],
2951 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2952 ccb->ccb_h.func_code = XPT_PATH_INQ;
2953 if (cam_send_ccb(device, ccb) < 0) {
2954 warn("get_cpi: error sending Path Inquiry CCB");
2955 if (arglist & CAM_ARG_VERBOSE)
2956 cam_error_print(device, ccb, CAM_ESF_ALL,
2957 CAM_EPF_ALL, stderr);
2959 goto get_cpi_bailout;
2961 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2962 if (arglist & CAM_ARG_VERBOSE)
2963 cam_error_print(device, ccb, CAM_ESF_ALL,
2964 CAM_EPF_ALL, stderr);
2966 goto get_cpi_bailout;
2968 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2976 * Get a get device CCB for the specified device.
2979 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
2984 ccb = cam_getccb(device);
2986 warnx("get_cgd: couldn't allocate CCB");
2989 bzero(&(&ccb->ccb_h)[1],
2990 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2991 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
2992 if (cam_send_ccb(device, ccb) < 0) {
2993 warn("get_cgd: error sending Path Inquiry CCB");
2994 if (arglist & CAM_ARG_VERBOSE)
2995 cam_error_print(device, ccb, CAM_ESF_ALL,
2996 CAM_EPF_ALL, stderr);
2998 goto get_cgd_bailout;
3000 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3001 if (arglist & CAM_ARG_VERBOSE)
3002 cam_error_print(device, ccb, CAM_ESF_ALL,
3003 CAM_EPF_ALL, stderr);
3005 goto get_cgd_bailout;
3007 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3015 cpi_print(struct ccb_pathinq *cpi)
3017 char adapter_str[1024];
3020 snprintf(adapter_str, sizeof(adapter_str),
3021 "%s%d:", cpi->dev_name, cpi->unit_number);
3023 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3026 for (i = 1; i < 0xff; i = i << 1) {
3029 if ((i & cpi->hba_inquiry) == 0)
3032 fprintf(stdout, "%s supports ", adapter_str);
3036 str = "MDP message";
3039 str = "32 bit wide SCSI";
3042 str = "16 bit wide SCSI";
3045 str = "SDTR message";
3048 str = "linked CDBs";
3051 str = "tag queue messages";
3054 str = "soft reset alternative";
3057 str = "SATA Port Multiplier";
3060 str = "unknown PI bit set";
3063 fprintf(stdout, "%s\n", str);
3066 for (i = 1; i < 0xff; i = i << 1) {
3069 if ((i & cpi->hba_misc) == 0)
3072 fprintf(stdout, "%s ", adapter_str);
3076 str = "bus scans from high ID to low ID";
3079 str = "removable devices not included in scan";
3081 case PIM_NOINITIATOR:
3082 str = "initiator role not supported";
3084 case PIM_NOBUSRESET:
3085 str = "user has disabled initial BUS RESET or"
3086 " controller is in target/mixed mode";
3089 str = "do not send 6-byte commands";
3092 str = "scan bus sequentially";
3095 str = "unknown PIM bit set";
3098 fprintf(stdout, "%s\n", str);
3101 for (i = 1; i < 0xff; i = i << 1) {
3104 if ((i & cpi->target_sprt) == 0)
3107 fprintf(stdout, "%s supports ", adapter_str);
3110 str = "target mode processor mode";
3113 str = "target mode phase cog. mode";
3115 case PIT_DISCONNECT:
3116 str = "disconnects in target mode";
3119 str = "terminate I/O message in target mode";
3122 str = "group 6 commands in target mode";
3125 str = "group 7 commands in target mode";
3128 str = "unknown PIT bit set";
3132 fprintf(stdout, "%s\n", str);
3134 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3136 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3138 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3140 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3141 adapter_str, cpi->hpath_id);
3142 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3144 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3145 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3146 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
3147 adapter_str, cpi->hba_vendor);
3148 fprintf(stdout, "%s HBA device ID: 0x%04x\n",
3149 adapter_str, cpi->hba_device);
3150 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
3151 adapter_str, cpi->hba_subvendor);
3152 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
3153 adapter_str, cpi->hba_subdevice);
3154 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3155 fprintf(stdout, "%s base transfer speed: ", adapter_str);
3156 if (cpi->base_transfer_speed > 1000)
3157 fprintf(stdout, "%d.%03dMB/sec\n",
3158 cpi->base_transfer_speed / 1000,
3159 cpi->base_transfer_speed % 1000);
3161 fprintf(stdout, "%dKB/sec\n",
3162 (cpi->base_transfer_speed % 1000) * 1000);
3163 fprintf(stdout, "%s maximum transfer size: %u bytes\n",
3164 adapter_str, cpi->maxio);
3168 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3169 struct ccb_trans_settings *cts)
3175 ccb = cam_getccb(device);
3178 warnx("get_print_cts: error allocating ccb");
3182 bzero(&(&ccb->ccb_h)[1],
3183 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3185 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3187 if (user_settings == 0)
3188 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3190 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3192 if (cam_send_ccb(device, ccb) < 0) {
3193 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3194 if (arglist & CAM_ARG_VERBOSE)
3195 cam_error_print(device, ccb, CAM_ESF_ALL,
3196 CAM_EPF_ALL, stderr);
3198 goto get_print_cts_bailout;
3201 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3202 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3203 if (arglist & CAM_ARG_VERBOSE)
3204 cam_error_print(device, ccb, CAM_ESF_ALL,
3205 CAM_EPF_ALL, stderr);
3207 goto get_print_cts_bailout;
3211 cts_print(device, &ccb->cts);
3214 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3216 get_print_cts_bailout:
3224 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3225 int argc, char **argv, char *combinedopt)
3229 int user_settings = 0;
3231 int disc_enable = -1, tag_enable = -1;
3234 double syncrate = -1;
3237 int change_settings = 0, send_tur = 0;
3238 struct ccb_pathinq cpi;
3240 ccb = cam_getccb(device);
3242 warnx("ratecontrol: error allocating ccb");
3245 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3254 if (strncasecmp(optarg, "enable", 6) == 0)
3256 else if (strncasecmp(optarg, "disable", 7) == 0)
3259 warnx("-D argument \"%s\" is unknown", optarg);
3261 goto ratecontrol_bailout;
3263 change_settings = 1;
3266 mode = ata_string2mode(optarg);
3268 warnx("unknown mode '%s'", optarg);
3270 goto ratecontrol_bailout;
3272 change_settings = 1;
3275 offset = strtol(optarg, NULL, 0);
3277 warnx("offset value %d is < 0", offset);
3279 goto ratecontrol_bailout;
3281 change_settings = 1;
3287 syncrate = atof(optarg);
3289 warnx("sync rate %f is < 0", syncrate);
3291 goto ratecontrol_bailout;
3293 change_settings = 1;
3296 if (strncasecmp(optarg, "enable", 6) == 0)
3298 else if (strncasecmp(optarg, "disable", 7) == 0)
3301 warnx("-T argument \"%s\" is unknown", optarg);
3303 goto ratecontrol_bailout;
3305 change_settings = 1;
3311 bus_width = strtol(optarg, NULL, 0);
3312 if (bus_width < 0) {
3313 warnx("bus width %d is < 0", bus_width);
3315 goto ratecontrol_bailout;
3317 change_settings = 1;
3323 bzero(&(&ccb->ccb_h)[1],
3324 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3326 * Grab path inquiry information, so we can determine whether
3327 * or not the initiator is capable of the things that the user
3330 ccb->ccb_h.func_code = XPT_PATH_INQ;
3331 if (cam_send_ccb(device, ccb) < 0) {
3332 perror("error sending XPT_PATH_INQ CCB");
3333 if (arglist & CAM_ARG_VERBOSE) {
3334 cam_error_print(device, ccb, CAM_ESF_ALL,
3335 CAM_EPF_ALL, stderr);
3338 goto ratecontrol_bailout;
3340 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3341 warnx("XPT_PATH_INQ CCB failed");
3342 if (arglist & CAM_ARG_VERBOSE) {
3343 cam_error_print(device, ccb, CAM_ESF_ALL,
3344 CAM_EPF_ALL, stderr);
3347 goto ratecontrol_bailout;
3349 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3350 bzero(&(&ccb->ccb_h)[1],
3351 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3353 fprintf(stdout, "%s parameters:\n",
3354 user_settings ? "User" : "Current");
3356 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3358 goto ratecontrol_bailout;
3360 if (arglist & CAM_ARG_VERBOSE)
3363 if (change_settings) {
3364 int didsettings = 0;
3365 struct ccb_trans_settings_spi *spi = NULL;
3366 struct ccb_trans_settings_ata *ata = NULL;
3367 struct ccb_trans_settings_sata *sata = NULL;
3368 struct ccb_trans_settings_scsi *scsi = NULL;
3370 if (ccb->cts.transport == XPORT_SPI)
3371 spi = &ccb->cts.xport_specific.spi;
3372 if (ccb->cts.transport == XPORT_ATA)
3373 ata = &ccb->cts.xport_specific.ata;
3374 if (ccb->cts.transport == XPORT_SATA)
3375 sata = &ccb->cts.xport_specific.sata;
3376 if (ccb->cts.protocol == PROTO_SCSI)
3377 scsi = &ccb->cts.proto_specific.scsi;
3378 ccb->cts.xport_specific.valid = 0;
3379 ccb->cts.proto_specific.valid = 0;
3380 if (spi && disc_enable != -1) {
3381 spi->valid |= CTS_SPI_VALID_DISC;
3382 if (disc_enable == 0)
3383 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3385 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3387 if (scsi && tag_enable != -1) {
3388 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3389 warnx("HBA does not support tagged queueing, "
3390 "so you cannot modify tag settings");
3392 goto ratecontrol_bailout;
3394 scsi->valid |= CTS_SCSI_VALID_TQ;
3395 if (tag_enable == 0)
3396 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3398 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3401 if (spi && offset != -1) {
3402 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3403 warnx("HBA is not capable of changing offset");
3405 goto ratecontrol_bailout;
3407 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3408 spi->sync_offset = offset;
3411 if (spi && syncrate != -1) {
3412 int prelim_sync_period;
3415 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3416 warnx("HBA is not capable of changing "
3419 goto ratecontrol_bailout;
3421 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3423 * The sync rate the user gives us is in MHz.
3424 * We need to translate it into KHz for this
3429 * Next, we calculate a "preliminary" sync period
3430 * in tenths of a nanosecond.
3433 prelim_sync_period = 0;
3435 prelim_sync_period = 10000000 / syncrate;
3437 scsi_calc_syncparam(prelim_sync_period);
3438 freq = scsi_calc_syncsrate(spi->sync_period);
3441 if (sata && syncrate != -1) {
3442 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3443 warnx("HBA is not capable of changing "
3446 goto ratecontrol_bailout;
3448 sata->revision = ata_speed2revision(syncrate * 100);
3449 if (sata->revision < 0) {
3450 warnx("Invalid rate %f", syncrate);
3452 goto ratecontrol_bailout;
3454 sata->valid |= CTS_SATA_VALID_REVISION;
3457 if ((ata || sata) && mode != -1) {
3458 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3459 warnx("HBA is not capable of changing "
3462 goto ratecontrol_bailout;
3466 ata->valid |= CTS_ATA_VALID_MODE;
3469 sata->valid |= CTS_SATA_VALID_MODE;
3474 * The bus_width argument goes like this:
3478 * Therefore, if you shift the number of bits given on the
3479 * command line right by 4, you should get the correct
3482 if (spi && bus_width != -1) {
3484 * We might as well validate things here with a
3485 * decipherable error message, rather than what
3486 * will probably be an indecipherable error message
3487 * by the time it gets back to us.
3489 if ((bus_width == 16)
3490 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3491 warnx("HBA does not support 16 bit bus width");
3493 goto ratecontrol_bailout;
3494 } else if ((bus_width == 32)
3495 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3496 warnx("HBA does not support 32 bit bus width");
3498 goto ratecontrol_bailout;
3499 } else if ((bus_width != 8)
3500 && (bus_width != 16)
3501 && (bus_width != 32)) {
3502 warnx("Invalid bus width %d", bus_width);
3504 goto ratecontrol_bailout;
3506 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3507 spi->bus_width = bus_width >> 4;
3510 if (didsettings == 0) {
3511 goto ratecontrol_bailout;
3513 if (!user_settings && (ata || sata)) {
3514 warnx("You can modify only user settings for ATA/SATA");
3516 goto ratecontrol_bailout;
3518 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3519 if (cam_send_ccb(device, ccb) < 0) {
3520 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3521 if (arglist & CAM_ARG_VERBOSE) {
3522 cam_error_print(device, ccb, CAM_ESF_ALL,
3523 CAM_EPF_ALL, stderr);
3526 goto ratecontrol_bailout;
3528 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3529 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3530 if (arglist & CAM_ARG_VERBOSE) {
3531 cam_error_print(device, ccb, CAM_ESF_ALL,
3532 CAM_EPF_ALL, stderr);
3535 goto ratecontrol_bailout;
3539 retval = testunitready(device, retry_count, timeout,
3540 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3542 * If the TUR didn't succeed, just bail.
3546 fprintf(stderr, "Test Unit Ready failed\n");
3547 goto ratecontrol_bailout;
3550 * If the user wants things quiet, there's no sense in
3551 * getting the transfer settings, if we're not going
3555 goto ratecontrol_bailout;
3556 fprintf(stdout, "New parameters:\n");
3557 retval = get_print_cts(device, user_settings, 0, NULL);
3560 ratecontrol_bailout:
3566 scsiformat(struct cam_device *device, int argc, char **argv,
3567 char *combinedopt, int retry_count, int timeout)
3571 int ycount = 0, quiet = 0;
3572 int error = 0, response = 0, retval = 0;
3573 int use_timeout = 10800 * 1000;
3575 struct format_defect_list_header fh;
3576 u_int8_t *data_ptr = NULL;
3577 u_int32_t dxfer_len = 0;
3579 int num_warnings = 0;
3582 ccb = cam_getccb(device);
3585 warnx("scsiformat: error allocating ccb");
3589 bzero(&(&ccb->ccb_h)[1],
3590 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3592 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3613 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3614 "following device:\n");
3616 error = scsidoinquiry(device, argc, argv, combinedopt,
3617 retry_count, timeout);
3620 warnx("scsiformat: error sending inquiry");
3621 goto scsiformat_bailout;
3630 fprintf(stdout, "Are you SURE you want to do "
3633 if (fgets(str, sizeof(str), stdin) != NULL) {
3635 if (strncasecmp(str, "yes", 3) == 0)
3637 else if (strncasecmp(str, "no", 2) == 0)
3640 fprintf(stdout, "Please answer"
3641 " \"yes\" or \"no\"\n");
3644 } while (response == 0);
3646 if (response == -1) {
3648 goto scsiformat_bailout;
3653 use_timeout = timeout;
3656 fprintf(stdout, "Current format timeout is %d seconds\n",
3657 use_timeout / 1000);
3661 * If the user hasn't disabled questions and didn't specify a
3662 * timeout on the command line, ask them if they want the current
3666 && (timeout == 0)) {
3668 int new_timeout = 0;
3670 fprintf(stdout, "Enter new timeout in seconds or press\n"
3671 "return to keep the current timeout [%d] ",
3672 use_timeout / 1000);
3674 if (fgets(str, sizeof(str), stdin) != NULL) {
3676 new_timeout = atoi(str);
3679 if (new_timeout != 0) {
3680 use_timeout = new_timeout * 1000;
3681 fprintf(stdout, "Using new timeout value %d\n",
3682 use_timeout / 1000);
3687 * Keep this outside the if block below to silence any unused
3688 * variable warnings.
3690 bzero(&fh, sizeof(fh));
3693 * If we're in immediate mode, we've got to include the format
3696 if (immediate != 0) {
3697 fh.byte2 = FU_DLH_IMMED;
3698 data_ptr = (u_int8_t *)&fh;
3699 dxfer_len = sizeof(fh);
3700 byte2 = FU_FMT_DATA;
3701 } else if (quiet == 0) {
3702 fprintf(stdout, "Formatting...");
3706 scsi_format_unit(&ccb->csio,
3707 /* retries */ retry_count,
3709 /* tag_action */ MSG_SIMPLE_Q_TAG,
3712 /* data_ptr */ data_ptr,
3713 /* dxfer_len */ dxfer_len,
3714 /* sense_len */ SSD_FULL_SIZE,
3715 /* timeout */ use_timeout);
3717 /* Disable freezing the device queue */
3718 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3720 if (arglist & CAM_ARG_ERR_RECOVER)
3721 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3723 if (((retval = cam_send_ccb(device, ccb)) < 0)
3724 || ((immediate == 0)
3725 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3726 const char errstr[] = "error sending format command";
3733 if (arglist & CAM_ARG_VERBOSE) {
3734 cam_error_print(device, ccb, CAM_ESF_ALL,
3735 CAM_EPF_ALL, stderr);
3738 goto scsiformat_bailout;
3742 * If we ran in non-immediate mode, we already checked for errors
3743 * above and printed out any necessary information. If we're in
3744 * immediate mode, we need to loop through and get status
3745 * information periodically.
3747 if (immediate == 0) {
3749 fprintf(stdout, "Format Complete\n");
3751 goto scsiformat_bailout;
3758 bzero(&(&ccb->ccb_h)[1],
3759 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3762 * There's really no need to do error recovery or
3763 * retries here, since we're just going to sit in a
3764 * loop and wait for the device to finish formatting.
3766 scsi_test_unit_ready(&ccb->csio,
3769 /* tag_action */ MSG_SIMPLE_Q_TAG,
3770 /* sense_len */ SSD_FULL_SIZE,
3771 /* timeout */ 5000);
3773 /* Disable freezing the device queue */
3774 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3776 retval = cam_send_ccb(device, ccb);
3779 * If we get an error from the ioctl, bail out. SCSI
3780 * errors are expected.
3783 warn("error sending CAMIOCOMMAND ioctl");
3784 if (arglist & CAM_ARG_VERBOSE) {
3785 cam_error_print(device, ccb, CAM_ESF_ALL,
3786 CAM_EPF_ALL, stderr);
3789 goto scsiformat_bailout;
3792 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3794 if ((status != CAM_REQ_CMP)
3795 && (status == CAM_SCSI_STATUS_ERROR)
3796 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3797 struct scsi_sense_data *sense;
3798 int error_code, sense_key, asc, ascq;
3800 sense = &ccb->csio.sense_data;
3801 scsi_extract_sense(sense, &error_code, &sense_key,
3805 * According to the SCSI-2 and SCSI-3 specs, a
3806 * drive that is in the middle of a format should
3807 * return NOT READY with an ASC of "logical unit
3808 * not ready, format in progress". The sense key
3809 * specific bytes will then be a progress indicator.
3811 if ((sense_key == SSD_KEY_NOT_READY)
3812 && (asc == 0x04) && (ascq == 0x04)) {
3813 if ((sense->extra_len >= 10)
3814 && ((sense->sense_key_spec[0] &
3815 SSD_SCS_VALID) != 0)
3818 u_int64_t percentage;
3821 &sense->sense_key_spec[1]);
3822 percentage = 10000 * val;
3825 "\rFormatting: %ju.%02u %% "
3827 (uintmax_t)(percentage /
3829 (unsigned)((percentage /
3833 } else if ((quiet == 0)
3834 && (++num_warnings <= 1)) {
3835 warnx("Unexpected SCSI Sense Key "
3836 "Specific value returned "
3838 scsi_sense_print(device, &ccb->csio,
3840 warnx("Unable to print status "
3841 "information, but format will "
3843 warnx("will exit when format is "
3848 warnx("Unexpected SCSI error during format");
3849 cam_error_print(device, ccb, CAM_ESF_ALL,
3850 CAM_EPF_ALL, stderr);
3852 goto scsiformat_bailout;
3855 } else if (status != CAM_REQ_CMP) {
3856 warnx("Unexpected CAM status %#x", status);
3857 if (arglist & CAM_ARG_VERBOSE)
3858 cam_error_print(device, ccb, CAM_ESF_ALL,
3859 CAM_EPF_ALL, stderr);
3861 goto scsiformat_bailout;
3864 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3867 fprintf(stdout, "\nFormat Complete\n");
3877 scsireportluns(struct cam_device *device, int argc, char **argv,
3878 char *combinedopt, int retry_count, int timeout)
3881 int c, countonly, lunsonly;
3882 struct scsi_report_luns_data *lundata;
3884 uint8_t report_type;
3885 uint32_t list_len, i, j;
3890 report_type = RPL_REPORT_DEFAULT;
3891 ccb = cam_getccb(device);
3894 warnx("%s: error allocating ccb", __func__);
3898 bzero(&(&ccb->ccb_h)[1],
3899 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3904 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3913 if (strcasecmp(optarg, "default") == 0)
3914 report_type = RPL_REPORT_DEFAULT;
3915 else if (strcasecmp(optarg, "wellknown") == 0)
3916 report_type = RPL_REPORT_WELLKNOWN;
3917 else if (strcasecmp(optarg, "all") == 0)
3918 report_type = RPL_REPORT_ALL;
3920 warnx("%s: invalid report type \"%s\"",
3931 if ((countonly != 0)
3932 && (lunsonly != 0)) {
3933 warnx("%s: you can only specify one of -c or -l", __func__);
3938 * According to SPC-4, the allocation length must be at least 16
3939 * bytes -- enough for the header and one LUN.
3941 alloc_len = sizeof(*lundata) + 8;
3945 lundata = malloc(alloc_len);
3947 if (lundata == NULL) {
3948 warn("%s: error mallocing %d bytes", __func__, alloc_len);
3953 scsi_report_luns(&ccb->csio,
3954 /*retries*/ retry_count,
3956 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3957 /*select_report*/ report_type,
3958 /*rpl_buf*/ lundata,
3959 /*alloc_len*/ alloc_len,
3960 /*sense_len*/ SSD_FULL_SIZE,
3961 /*timeout*/ timeout ? timeout : 5000);
3963 /* Disable freezing the device queue */
3964 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3966 if (arglist & CAM_ARG_ERR_RECOVER)
3967 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3969 if (cam_send_ccb(device, ccb) < 0) {
3970 warn("error sending REPORT LUNS command");
3972 if (arglist & CAM_ARG_VERBOSE)
3973 cam_error_print(device, ccb, CAM_ESF_ALL,
3974 CAM_EPF_ALL, stderr);
3980 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3981 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3987 list_len = scsi_4btoul(lundata->length);
3990 * If we need to list the LUNs, and our allocation
3991 * length was too short, reallocate and retry.
3993 if ((countonly == 0)
3994 && (list_len > (alloc_len - sizeof(*lundata)))) {
3995 alloc_len = list_len + sizeof(*lundata);
4001 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
4002 ((list_len / 8) > 1) ? "s" : "");
4007 for (i = 0; i < (list_len / 8); i++) {
4011 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4013 fprintf(stdout, ",");
4014 switch (lundata->luns[i].lundata[j] &
4015 RPL_LUNDATA_ATYP_MASK) {
4016 case RPL_LUNDATA_ATYP_PERIPH:
4017 if ((lundata->luns[i].lundata[j] &
4018 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4019 fprintf(stdout, "%d:",
4020 lundata->luns[i].lundata[j] &
4021 RPL_LUNDATA_PERIPH_BUS_MASK);
4023 && ((lundata->luns[i].lundata[j+2] &
4024 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4027 fprintf(stdout, "%d",
4028 lundata->luns[i].lundata[j+1]);
4030 case RPL_LUNDATA_ATYP_FLAT: {
4032 tmplun[0] = lundata->luns[i].lundata[j] &
4033 RPL_LUNDATA_FLAT_LUN_MASK;
4034 tmplun[1] = lundata->luns[i].lundata[j+1];
4036 fprintf(stdout, "%d", scsi_2btoul(tmplun));
4040 case RPL_LUNDATA_ATYP_LUN:
4041 fprintf(stdout, "%d:%d:%d",
4042 (lundata->luns[i].lundata[j+1] &
4043 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4044 lundata->luns[i].lundata[j] &
4045 RPL_LUNDATA_LUN_TARG_MASK,
4046 lundata->luns[i].lundata[j+1] &
4047 RPL_LUNDATA_LUN_LUN_MASK);
4049 case RPL_LUNDATA_ATYP_EXTLUN: {
4050 int field_len, field_len_code, eam_code;
4052 eam_code = lundata->luns[i].lundata[j] &
4053 RPL_LUNDATA_EXT_EAM_MASK;
4054 field_len_code = (lundata->luns[i].lundata[j] &
4055 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4056 field_len = field_len_code * 2;
4058 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4059 && (field_len_code == 0x00)) {
4060 fprintf(stdout, "%d",
4061 lundata->luns[i].lundata[j+1]);
4062 } else if ((eam_code ==
4063 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4064 && (field_len_code == 0x03)) {
4068 * This format takes up all 8 bytes.
4069 * If we aren't starting at offset 0,
4073 fprintf(stdout, "Invalid "
4076 "specified format", j);
4080 bzero(tmp_lun, sizeof(tmp_lun));
4081 bcopy(&lundata->luns[i].lundata[j+1],
4082 &tmp_lun[1], sizeof(tmp_lun) - 1);
4083 fprintf(stdout, "%#jx",
4084 (intmax_t)scsi_8btou64(tmp_lun));
4087 fprintf(stderr, "Unknown Extended LUN"
4088 "Address method %#x, length "
4089 "code %#x", eam_code,
4096 fprintf(stderr, "Unknown LUN address method "
4097 "%#x\n", lundata->luns[i].lundata[0] &
4098 RPL_LUNDATA_ATYP_MASK);
4102 * For the flat addressing method, there are no
4103 * other levels after it.
4108 fprintf(stdout, "\n");
4121 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4122 char *combinedopt, int retry_count, int timeout)
4125 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4126 struct scsi_read_capacity_data rcap;
4127 struct scsi_read_capacity_data_long rcaplong;
4141 ccb = cam_getccb(device);
4144 warnx("%s: error allocating ccb", __func__);
4148 bzero(&(&ccb->ccb_h)[1],
4149 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4151 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4178 if ((blocksizeonly != 0)
4179 && (numblocks != 0)) {
4180 warnx("%s: you can only specify one of -b or -N", __func__);
4185 if ((blocksizeonly != 0)
4186 && (sizeonly != 0)) {
4187 warnx("%s: you can only specify one of -b or -s", __func__);
4194 warnx("%s: you can only specify one of -h/-H or -q", __func__);
4200 && (blocksizeonly != 0)) {
4201 warnx("%s: you can only specify one of -h/-H or -b", __func__);
4206 scsi_read_capacity(&ccb->csio,
4207 /*retries*/ retry_count,
4209 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4212 /*timeout*/ timeout ? timeout : 5000);
4214 /* Disable freezing the device queue */
4215 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4217 if (arglist & CAM_ARG_ERR_RECOVER)
4218 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4220 if (cam_send_ccb(device, ccb) < 0) {
4221 warn("error sending READ CAPACITY command");
4223 if (arglist & CAM_ARG_VERBOSE)
4224 cam_error_print(device, ccb, CAM_ESF_ALL,
4225 CAM_EPF_ALL, stderr);
4231 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4232 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4237 maxsector = scsi_4btoul(rcap.addr);
4238 block_len = scsi_4btoul(rcap.length);
4241 * A last block of 2^32-1 means that the true capacity is over 2TB,
4242 * and we need to issue the long READ CAPACITY to get the real
4243 * capacity. Otherwise, we're all set.
4245 if (maxsector != 0xffffffff)
4248 scsi_read_capacity_16(&ccb->csio,
4249 /*retries*/ retry_count,
4251 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4256 /*sense_len*/ SSD_FULL_SIZE,
4257 /*timeout*/ timeout ? timeout : 5000);
4259 /* Disable freezing the device queue */
4260 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4262 if (arglist & CAM_ARG_ERR_RECOVER)
4263 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4265 if (cam_send_ccb(device, ccb) < 0) {
4266 warn("error sending READ CAPACITY (16) command");
4268 if (arglist & CAM_ARG_VERBOSE)
4269 cam_error_print(device, ccb, CAM_ESF_ALL,
4270 CAM_EPF_ALL, stderr);
4276 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4277 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4282 maxsector = scsi_8btou64(rcaplong.addr);
4283 block_len = scsi_4btoul(rcaplong.length);
4286 if (blocksizeonly == 0) {
4288 * Humanize implies !quiet, and also implies numblocks.
4290 if (humanize != 0) {
4295 tmpbytes = (maxsector + 1) * block_len;
4296 ret = humanize_number(tmpstr, sizeof(tmpstr),
4297 tmpbytes, "", HN_AUTOSCALE,
4300 HN_DIVISOR_1000 : 0));
4302 warnx("%s: humanize_number failed!", __func__);
4306 fprintf(stdout, "Device Size: %s%s", tmpstr,
4307 (sizeonly == 0) ? ", " : "\n");
4308 } else if (numblocks != 0) {
4309 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4310 "Blocks: " : "", (uintmax_t)maxsector + 1,
4311 (sizeonly == 0) ? ", " : "\n");
4313 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4314 "Last Block: " : "", (uintmax_t)maxsector,
4315 (sizeonly == 0) ? ", " : "\n");
4319 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4320 "Block Length: " : "", block_len, (quiet == 0) ?
4329 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4330 int retry_count, int timeout)
4334 uint8_t *smp_request = NULL, *smp_response = NULL;
4335 int request_size = 0, response_size = 0;
4336 int fd_request = 0, fd_response = 0;
4337 char *datastr = NULL;
4338 struct get_hook hook;
4343 * Note that at the moment we don't support sending SMP CCBs to
4344 * devices that aren't probed by CAM.
4346 ccb = cam_getccb(device);
4348 warnx("%s: error allocating CCB", __func__);
4352 bzero(&(&ccb->ccb_h)[1],
4353 sizeof(union ccb) - sizeof(struct ccb_hdr));
4355 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4358 arglist |= CAM_ARG_CMD_IN;
4359 response_size = strtol(optarg, NULL, 0);
4360 if (response_size <= 0) {
4361 warnx("invalid number of response bytes %d",
4364 goto smpcmd_bailout;
4366 hook.argc = argc - optind;
4367 hook.argv = argv + optind;
4370 datastr = cget(&hook, NULL);
4372 * If the user supplied "-" instead of a format, he
4373 * wants the data to be written to stdout.
4375 if ((datastr != NULL)
4376 && (datastr[0] == '-'))
4379 smp_response = (u_int8_t *)malloc(response_size);
4380 if (smp_response == NULL) {
4381 warn("can't malloc memory for SMP response");
4383 goto smpcmd_bailout;
4387 arglist |= CAM_ARG_CMD_OUT;
4388 request_size = strtol(optarg, NULL, 0);
4389 if (request_size <= 0) {
4390 warnx("invalid number of request bytes %d",
4393 goto smpcmd_bailout;
4395 hook.argc = argc - optind;
4396 hook.argv = argv + optind;
4398 datastr = cget(&hook, NULL);
4399 smp_request = (u_int8_t *)malloc(request_size);
4400 if (smp_request == NULL) {
4401 warn("can't malloc memory for SMP request");
4403 goto smpcmd_bailout;
4405 bzero(smp_request, request_size);
4407 * If the user supplied "-" instead of a format, he
4408 * wants the data to be read from stdin.
4410 if ((datastr != NULL)
4411 && (datastr[0] == '-'))
4414 buff_encode_visit(smp_request, request_size,
4425 * If fd_data is set, and we're writing to the device, we need to
4426 * read the data the user wants written from stdin.
4428 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4430 int amt_to_read = request_size;
4431 u_int8_t *buf_ptr = smp_request;
4433 for (amt_read = 0; amt_to_read > 0;
4434 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4435 if (amt_read == -1) {
4436 warn("error reading data from stdin");
4438 goto smpcmd_bailout;
4440 amt_to_read -= amt_read;
4441 buf_ptr += amt_read;
4445 if (((arglist & CAM_ARG_CMD_IN) == 0)
4446 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
4447 warnx("%s: need both the request (-r) and response (-R) "
4448 "arguments", __func__);
4450 goto smpcmd_bailout;
4453 flags |= CAM_DEV_QFRZDIS;
4455 cam_fill_smpio(&ccb->smpio,
4456 /*retries*/ retry_count,
4459 /*smp_request*/ smp_request,
4460 /*smp_request_len*/ request_size,
4461 /*smp_response*/ smp_response,
4462 /*smp_response_len*/ response_size,
4463 /*timeout*/ timeout ? timeout : 5000);
4465 ccb->smpio.flags = SMP_FLAG_NONE;
4467 if (((retval = cam_send_ccb(device, ccb)) < 0)
4468 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4469 const char *warnstr = "error sending command";
4476 if (arglist & CAM_ARG_VERBOSE) {
4477 cam_error_print(device, ccb, CAM_ESF_ALL,
4478 CAM_EPF_ALL, stderr);
4482 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4483 && (response_size > 0)) {
4484 if (fd_response == 0) {
4485 buff_decode_visit(smp_response, response_size,
4486 datastr, arg_put, NULL);
4487 fprintf(stdout, "\n");
4489 ssize_t amt_written;
4490 int amt_to_write = response_size;
4491 u_int8_t *buf_ptr = smp_response;
4493 for (amt_written = 0; (amt_to_write > 0) &&
4494 (amt_written = write(STDOUT_FILENO, buf_ptr,
4495 amt_to_write)) > 0;){
4496 amt_to_write -= amt_written;
4497 buf_ptr += amt_written;
4499 if (amt_written == -1) {
4500 warn("error writing data to stdout");
4502 goto smpcmd_bailout;
4503 } else if ((amt_written == 0)
4504 && (amt_to_write > 0)) {
4505 warnx("only wrote %u bytes out of %u",
4506 response_size - amt_to_write,
4515 if (smp_request != NULL)
4518 if (smp_response != NULL)
4525 smpreportgeneral(struct cam_device *device, int argc, char **argv,
4526 char *combinedopt, int retry_count, int timeout)
4529 struct smp_report_general_request *request = NULL;
4530 struct smp_report_general_response *response = NULL;
4531 struct sbuf *sb = NULL;
4533 int c, long_response = 0;
4537 * Note that at the moment we don't support sending SMP CCBs to
4538 * devices that aren't probed by CAM.
4540 ccb = cam_getccb(device);
4542 warnx("%s: error allocating CCB", __func__);
4546 bzero(&(&ccb->ccb_h)[1],
4547 sizeof(union ccb) - sizeof(struct ccb_hdr));
4549 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4558 request = malloc(sizeof(*request));
4559 if (request == NULL) {
4560 warn("%s: unable to allocate %zd bytes", __func__,
4566 response = malloc(sizeof(*response));
4567 if (response == NULL) {
4568 warn("%s: unable to allocate %zd bytes", __func__,
4575 smp_report_general(&ccb->smpio,
4579 /*request_len*/ sizeof(*request),
4580 (uint8_t *)response,
4581 /*response_len*/ sizeof(*response),
4582 /*long_response*/ long_response,
4585 if (((retval = cam_send_ccb(device, ccb)) < 0)
4586 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4587 const char *warnstr = "error sending command";
4594 if (arglist & CAM_ARG_VERBOSE) {
4595 cam_error_print(device, ccb, CAM_ESF_ALL,
4596 CAM_EPF_ALL, stderr);
4603 * If the device supports the long response bit, try again and see
4604 * if we can get all of the data.
4606 if ((response->long_response & SMP_RG_LONG_RESPONSE)
4607 && (long_response == 0)) {
4608 ccb->ccb_h.status = CAM_REQ_INPROG;
4609 bzero(&(&ccb->ccb_h)[1],
4610 sizeof(union ccb) - sizeof(struct ccb_hdr));
4616 * XXX KDM detect and decode SMP errors here.
4618 sb = sbuf_new_auto();
4620 warnx("%s: error allocating sbuf", __func__);
4624 smp_report_general_sbuf(response, sizeof(*response), sb);
4628 printf("%s", sbuf_data(sb));
4634 if (request != NULL)
4637 if (response != NULL)
4646 struct camcontrol_opts phy_ops[] = {
4647 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
4648 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
4649 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
4650 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
4651 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
4652 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
4653 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
4654 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
4655 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
4660 smpphycontrol(struct cam_device *device, int argc, char **argv,
4661 char *combinedopt, int retry_count, int timeout)
4664 struct smp_phy_control_request *request = NULL;
4665 struct smp_phy_control_response *response = NULL;
4666 int long_response = 0;
4669 uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
4671 uint64_t attached_dev_name = 0;
4672 int dev_name_set = 0;
4673 uint32_t min_plr = 0, max_plr = 0;
4674 uint32_t pp_timeout_val = 0;
4675 int slumber_partial = 0;
4676 int set_pp_timeout_val = 0;
4680 * Note that at the moment we don't support sending SMP CCBs to
4681 * devices that aren't probed by CAM.
4683 ccb = cam_getccb(device);
4685 warnx("%s: error allocating CCB", __func__);
4689 bzero(&(&ccb->ccb_h)[1],
4690 sizeof(union ccb) - sizeof(struct ccb_hdr));
4692 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4700 if (strcasecmp(optarg, "enable") == 0)
4702 else if (strcasecmp(optarg, "disable") == 0)
4705 warnx("%s: Invalid argument %s", __func__,
4712 slumber_partial |= enable <<
4713 SMP_PC_SAS_SLUMBER_SHIFT;
4716 slumber_partial |= enable <<
4717 SMP_PC_SAS_PARTIAL_SHIFT;
4720 slumber_partial |= enable <<
4721 SMP_PC_SATA_SLUMBER_SHIFT;
4724 slumber_partial |= enable <<
4725 SMP_PC_SATA_PARTIAL_SHIFT;
4728 warnx("%s: programmer error", __func__);
4731 break; /*NOTREACHED*/
4736 attached_dev_name = (uintmax_t)strtoumax(optarg,
4745 * We don't do extensive checking here, so this
4746 * will continue to work when new speeds come out.
4748 min_plr = strtoul(optarg, NULL, 0);
4750 || (min_plr > 0xf)) {
4751 warnx("%s: invalid link rate %x",
4759 * We don't do extensive checking here, so this
4760 * will continue to work when new speeds come out.
4762 max_plr = strtoul(optarg, NULL, 0);
4764 || (max_plr > 0xf)) {
4765 warnx("%s: invalid link rate %x",
4772 camcontrol_optret optreturn;
4773 cam_argmask argnums;
4776 if (phy_op_set != 0) {
4777 warnx("%s: only one phy operation argument "
4778 "(-o) allowed", __func__);
4786 * Allow the user to specify the phy operation
4787 * numerically, as well as with a name. This will
4788 * future-proof it a bit, so options that are added
4789 * in future specs can be used.
4791 if (isdigit(optarg[0])) {
4792 phy_operation = strtoul(optarg, NULL, 0);
4793 if ((phy_operation == 0)
4794 || (phy_operation > 0xff)) {
4795 warnx("%s: invalid phy operation %#x",
4796 __func__, phy_operation);
4802 optreturn = getoption(phy_ops, optarg, &phy_operation,
4805 if (optreturn == CC_OR_AMBIGUOUS) {
4806 warnx("%s: ambiguous option %s", __func__,
4811 } else if (optreturn == CC_OR_NOT_FOUND) {
4812 warnx("%s: option %s not found", __func__,
4824 pp_timeout_val = strtoul(optarg, NULL, 0);
4825 if (pp_timeout_val > 15) {
4826 warnx("%s: invalid partial pathway timeout "
4827 "value %u, need a value less than 16",
4828 __func__, pp_timeout_val);
4832 set_pp_timeout_val = 1;
4840 warnx("%s: a PHY (-p phy) argument is required",__func__);
4845 if (((dev_name_set != 0)
4846 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
4847 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
4848 && (dev_name_set == 0))) {
4849 warnx("%s: -d name and -o setdevname arguments both "
4850 "required to set device name", __func__);
4855 request = malloc(sizeof(*request));
4856 if (request == NULL) {
4857 warn("%s: unable to allocate %zd bytes", __func__,
4863 response = malloc(sizeof(*response));
4864 if (response == NULL) {
4865 warn("%s: unable to allocate %zd bytes", __func__,
4871 smp_phy_control(&ccb->smpio,
4876 (uint8_t *)response,
4879 /*expected_exp_change_count*/ 0,
4882 (set_pp_timeout_val != 0) ? 1 : 0,
4890 if (((retval = cam_send_ccb(device, ccb)) < 0)
4891 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4892 const char *warnstr = "error sending command";
4899 if (arglist & CAM_ARG_VERBOSE) {
4901 * Use CAM_EPF_NORMAL so we only get one line of
4902 * SMP command decoding.
4904 cam_error_print(device, ccb, CAM_ESF_ALL,
4905 CAM_EPF_NORMAL, stderr);
4911 /* XXX KDM print out something here for success? */
4916 if (request != NULL)
4919 if (response != NULL)
4926 smpmaninfo(struct cam_device *device, int argc, char **argv,
4927 char *combinedopt, int retry_count, int timeout)
4930 struct smp_report_manuf_info_request request;
4931 struct smp_report_manuf_info_response response;
4932 struct sbuf *sb = NULL;
4933 int long_response = 0;
4938 * Note that at the moment we don't support sending SMP CCBs to
4939 * devices that aren't probed by CAM.
4941 ccb = cam_getccb(device);
4943 warnx("%s: error allocating CCB", __func__);
4947 bzero(&(&ccb->ccb_h)[1],
4948 sizeof(union ccb) - sizeof(struct ccb_hdr));
4950 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4959 bzero(&request, sizeof(request));
4960 bzero(&response, sizeof(response));
4962 smp_report_manuf_info(&ccb->smpio,
4967 (uint8_t *)&response,
4972 if (((retval = cam_send_ccb(device, ccb)) < 0)
4973 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4974 const char *warnstr = "error sending command";
4981 if (arglist & CAM_ARG_VERBOSE) {
4982 cam_error_print(device, ccb, CAM_ESF_ALL,
4983 CAM_EPF_ALL, stderr);
4989 sb = sbuf_new_auto();
4991 warnx("%s: error allocating sbuf", __func__);
4995 smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
4999 printf("%s", sbuf_data(sb));
5013 getdevid(struct cam_devitem *item)
5016 union ccb *ccb = NULL;
5018 struct cam_device *dev;
5020 dev = cam_open_btl(item->dev_match.path_id,
5021 item->dev_match.target_id,
5022 item->dev_match.target_lun, O_RDWR, NULL);
5025 warnx("%s", cam_errbuf);
5030 item->device_id_len = 0;
5032 ccb = cam_getccb(dev);
5034 warnx("%s: error allocating CCB", __func__);
5039 bzero(&(&ccb->ccb_h)[1],
5040 sizeof(union ccb) - sizeof(struct ccb_hdr));
5043 * On the first try, we just probe for the size of the data, and
5044 * then allocate that much memory and try again.
5047 ccb->ccb_h.func_code = XPT_GDEV_ADVINFO;
5048 ccb->ccb_h.flags = CAM_DIR_IN;
5049 ccb->cgdai.flags = CGDAI_FLAG_PROTO;
5050 ccb->cgdai.buftype = CGDAI_TYPE_SCSI_DEVID;
5051 ccb->cgdai.bufsiz = item->device_id_len;
5052 if (item->device_id_len != 0)
5053 ccb->cgdai.buf = (uint8_t *)item->device_id;
5055 if (cam_send_ccb(dev, ccb) < 0) {
5056 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
5061 if (ccb->ccb_h.status != CAM_REQ_CMP) {
5062 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
5067 if (item->device_id_len == 0) {
5069 * This is our first time through. Allocate the buffer,
5070 * and then go back to get the data.
5072 if (ccb->cgdai.provsiz == 0) {
5073 warnx("%s: invalid .provsiz field returned with "
5074 "XPT_GDEV_ADVINFO CCB", __func__);
5078 item->device_id_len = ccb->cgdai.provsiz;
5079 item->device_id = malloc(item->device_id_len);
5080 if (item->device_id == NULL) {
5081 warn("%s: unable to allocate %d bytes", __func__,
5082 item->device_id_len);
5086 ccb->ccb_h.status = CAM_REQ_INPROG;
5092 cam_close_device(dev);
5101 * XXX KDM merge this code with getdevtree()?
5104 buildbusdevlist(struct cam_devlist *devlist)
5107 int bufsize, fd = -1;
5108 struct dev_match_pattern *patterns;
5109 struct cam_devitem *item = NULL;
5110 int skip_device = 0;
5113 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
5114 warn("couldn't open %s", XPT_DEVICE);
5118 bzero(&ccb, sizeof(union ccb));
5120 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
5121 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
5122 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
5124 ccb.ccb_h.func_code = XPT_DEV_MATCH;
5125 bufsize = sizeof(struct dev_match_result) * 100;
5126 ccb.cdm.match_buf_len = bufsize;
5127 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
5128 if (ccb.cdm.matches == NULL) {
5129 warnx("can't malloc memory for matches");
5133 ccb.cdm.num_matches = 0;
5134 ccb.cdm.num_patterns = 2;
5135 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
5136 ccb.cdm.num_patterns;
5138 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
5139 if (patterns == NULL) {
5140 warnx("can't malloc memory for patterns");
5145 ccb.cdm.patterns = patterns;
5146 bzero(patterns, ccb.cdm.pattern_buf_len);
5148 patterns[0].type = DEV_MATCH_DEVICE;
5149 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
5150 patterns[0].pattern.device_pattern.path_id = devlist->path_id;
5151 patterns[1].type = DEV_MATCH_PERIPH;
5152 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
5153 patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
5156 * We do the ioctl multiple times if necessary, in case there are
5157 * more than 100 nodes in the EDT.
5162 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
5163 warn("error sending CAMIOCOMMAND ioctl");
5168 if ((ccb.ccb_h.status != CAM_REQ_CMP)
5169 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
5170 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
5171 warnx("got CAM error %#x, CDM error %d\n",
5172 ccb.ccb_h.status, ccb.cdm.status);
5177 for (i = 0; i < ccb.cdm.num_matches; i++) {
5178 switch (ccb.cdm.matches[i].type) {
5179 case DEV_MATCH_DEVICE: {
5180 struct device_match_result *dev_result;
5183 &ccb.cdm.matches[i].result.device_result;
5185 if (dev_result->flags &
5186 DEV_RESULT_UNCONFIGURED) {
5192 item = malloc(sizeof(*item));
5194 warn("%s: unable to allocate %zd bytes",
5195 __func__, sizeof(*item));
5199 bzero(item, sizeof(*item));
5200 bcopy(dev_result, &item->dev_match,
5201 sizeof(*dev_result));
5202 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
5205 if (getdevid(item) != 0) {
5211 case DEV_MATCH_PERIPH: {
5212 struct periph_match_result *periph_result;
5215 &ccb.cdm.matches[i].result.periph_result;
5217 if (skip_device != 0)
5219 item->num_periphs++;
5220 item->periph_matches = realloc(
5221 item->periph_matches,
5223 sizeof(struct periph_match_result));
5224 if (item->periph_matches == NULL) {
5225 warn("%s: error allocating periph "
5230 bcopy(periph_result, &item->periph_matches[
5231 item->num_periphs - 1],
5232 sizeof(*periph_result));
5236 fprintf(stderr, "%s: unexpected match "
5237 "type %d\n", __func__,
5238 ccb.cdm.matches[i].type);
5241 break; /*NOTREACHED*/
5244 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
5245 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
5253 free(ccb.cdm.matches);
5256 freebusdevlist(devlist);
5262 freebusdevlist(struct cam_devlist *devlist)
5264 struct cam_devitem *item, *item2;
5266 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
5267 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
5269 free(item->device_id);
5270 free(item->periph_matches);
5275 static struct cam_devitem *
5276 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
5278 struct cam_devitem *item;
5280 STAILQ_FOREACH(item, &devlist->dev_queue, links) {
5284 * XXX KDM look for LUN IDs as well?
5286 item_addr = scsi_get_sas_addr(item->device_id,
5287 item->device_id_len);
5288 if (item_addr == NULL)
5291 if (scsi_8btou64(item_addr) == sasaddr)
5299 smpphylist(struct cam_device *device, int argc, char **argv,
5300 char *combinedopt, int retry_count, int timeout)
5302 struct smp_report_general_request *rgrequest = NULL;
5303 struct smp_report_general_response *rgresponse = NULL;
5304 struct smp_discover_request *disrequest = NULL;
5305 struct smp_discover_response *disresponse = NULL;
5306 struct cam_devlist devlist;
5308 int long_response = 0;
5315 * Note that at the moment we don't support sending SMP CCBs to
5316 * devices that aren't probed by CAM.
5318 ccb = cam_getccb(device);
5320 warnx("%s: error allocating CCB", __func__);
5324 bzero(&(&ccb->ccb_h)[1],
5325 sizeof(union ccb) - sizeof(struct ccb_hdr));
5327 rgrequest = malloc(sizeof(*rgrequest));
5328 if (rgrequest == NULL) {
5329 warn("%s: unable to allocate %zd bytes", __func__,
5330 sizeof(*rgrequest));
5335 rgresponse = malloc(sizeof(*rgresponse));
5336 if (rgresponse == NULL) {
5337 warn("%s: unable to allocate %zd bytes", __func__,
5338 sizeof(*rgresponse));
5343 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5356 smp_report_general(&ccb->smpio,
5360 /*request_len*/ sizeof(*rgrequest),
5361 (uint8_t *)rgresponse,
5362 /*response_len*/ sizeof(*rgresponse),
5363 /*long_response*/ long_response,
5366 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5368 if (((retval = cam_send_ccb(device, ccb)) < 0)
5369 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5370 const char *warnstr = "error sending command";
5377 if (arglist & CAM_ARG_VERBOSE) {
5378 cam_error_print(device, ccb, CAM_ESF_ALL,
5379 CAM_EPF_ALL, stderr);
5385 num_phys = rgresponse->num_phys;
5387 if (num_phys == 0) {
5389 fprintf(stdout, "%s: No Phys reported\n", __func__);
5394 STAILQ_INIT(&devlist.dev_queue);
5395 devlist.path_id = device->path_id;
5397 retval = buildbusdevlist(&devlist);
5402 fprintf(stdout, "%d PHYs:\n", num_phys);
5403 fprintf(stdout, "PHY Attached SAS Address\n");
5406 disrequest = malloc(sizeof(*disrequest));
5407 if (disrequest == NULL) {
5408 warn("%s: unable to allocate %zd bytes", __func__,
5409 sizeof(*disrequest));
5414 disresponse = malloc(sizeof(*disresponse));
5415 if (disresponse == NULL) {
5416 warn("%s: unable to allocate %zd bytes", __func__,
5417 sizeof(*disresponse));
5422 for (i = 0; i < num_phys; i++) {
5423 struct cam_devitem *item;
5424 struct device_match_result *dev_match;
5425 char vendor[16], product[48], revision[16];
5429 bzero(&(&ccb->ccb_h)[1],
5430 sizeof(union ccb) - sizeof(struct ccb_hdr));
5432 ccb->ccb_h.status = CAM_REQ_INPROG;
5433 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5435 smp_discover(&ccb->smpio,
5439 sizeof(*disrequest),
5440 (uint8_t *)disresponse,
5441 sizeof(*disresponse),
5443 /*ignore_zone_group*/ 0,
5447 if (((retval = cam_send_ccb(device, ccb)) < 0)
5448 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
5449 && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
5450 const char *warnstr = "error sending command";
5457 if (arglist & CAM_ARG_VERBOSE) {
5458 cam_error_print(device, ccb, CAM_ESF_ALL,
5459 CAM_EPF_ALL, stderr);
5465 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
5467 fprintf(stdout, "%3d <vacant>\n", i);
5471 item = findsasdevice(&devlist,
5472 scsi_8btou64(disresponse->attached_sas_address));
5475 || (item != NULL)) {
5476 fprintf(stdout, "%3d 0x%016jx", i,
5477 (uintmax_t)scsi_8btou64(
5478 disresponse->attached_sas_address));
5480 fprintf(stdout, "\n");
5483 } else if (quiet != 0)
5486 dev_match = &item->dev_match;
5488 if (dev_match->protocol == PROTO_SCSI) {
5489 cam_strvis(vendor, dev_match->inq_data.vendor,
5490 sizeof(dev_match->inq_data.vendor),
5492 cam_strvis(product, dev_match->inq_data.product,
5493 sizeof(dev_match->inq_data.product),
5495 cam_strvis(revision, dev_match->inq_data.revision,
5496 sizeof(dev_match->inq_data.revision),
5498 sprintf(tmpstr, "<%s %s %s>", vendor, product,
5500 } else if ((dev_match->protocol == PROTO_ATA)
5501 || (dev_match->protocol == PROTO_SATAPM)) {
5502 cam_strvis(product, dev_match->ident_data.model,
5503 sizeof(dev_match->ident_data.model),
5505 cam_strvis(revision, dev_match->ident_data.revision,
5506 sizeof(dev_match->ident_data.revision),
5508 sprintf(tmpstr, "<%s %s>", product, revision);
5510 sprintf(tmpstr, "<>");
5512 fprintf(stdout, " %-33s ", tmpstr);
5515 * If we have 0 periphs, that's a bug...
5517 if (item->num_periphs == 0) {
5518 fprintf(stdout, "\n");
5522 fprintf(stdout, "(");
5523 for (j = 0; j < item->num_periphs; j++) {
5525 fprintf(stdout, ",");
5527 fprintf(stdout, "%s%d",
5528 item->periph_matches[j].periph_name,
5529 item->periph_matches[j].unit_number);
5532 fprintf(stdout, ")\n");
5546 freebusdevlist(&devlist);
5552 atapm(struct cam_device *device, int argc, char **argv,
5553 char *combinedopt, int retry_count, int timeout)
5561 ccb = cam_getccb(device);
5564 warnx("%s: error allocating ccb", __func__);
5568 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5577 if (strcmp(argv[1], "idle") == 0) {
5579 cmd = ATA_IDLE_IMMEDIATE;
5582 } else if (strcmp(argv[1], "standby") == 0) {
5584 cmd = ATA_STANDBY_IMMEDIATE;
5586 cmd = ATA_STANDBY_CMD;
5594 else if (t <= (240 * 5))
5596 else if (t <= (252 * 5))
5597 /* special encoding for 21 minutes */
5599 else if (t <= (11 * 30 * 60))
5600 sc = (t - 1) / (30 * 60) + 241;
5604 cam_fill_ataio(&ccb->ataio,
5607 /*flags*/CAM_DIR_NONE,
5611 timeout ? timeout : 30 * 1000);
5612 ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
5614 /* Disable freezing the device queue */
5615 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5617 if (arglist & CAM_ARG_ERR_RECOVER)
5618 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5620 if (cam_send_ccb(device, ccb) < 0) {
5621 warn("error sending command");
5623 if (arglist & CAM_ARG_VERBOSE)
5624 cam_error_print(device, ccb, CAM_ESF_ALL,
5625 CAM_EPF_ALL, stderr);
5631 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5632 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5641 #endif /* MINIMALISTIC */
5646 fprintf(verbose ? stdout : stderr,
5647 "usage: camcontrol <command> [device id][generic args][command args]\n"
5648 " camcontrol devlist [-v]\n"
5649 #ifndef MINIMALISTIC
5650 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
5651 " camcontrol tur [dev_id][generic args]\n"
5652 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
5653 " camcontrol identify [dev_id][generic args] [-v]\n"
5654 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
5655 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
5657 " camcontrol start [dev_id][generic args]\n"
5658 " camcontrol stop [dev_id][generic args]\n"
5659 " camcontrol load [dev_id][generic args]\n"
5660 " camcontrol eject [dev_id][generic args]\n"
5661 #endif /* MINIMALISTIC */
5662 " camcontrol rescan <all | bus[:target:lun]>\n"
5663 " camcontrol reset <all | bus[:target:lun]>\n"
5664 #ifndef MINIMALISTIC
5665 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
5666 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
5667 " [-P pagectl][-e | -b][-d]\n"
5668 " camcontrol cmd [dev_id][generic args]\n"
5669 " <-a cmd [args] | -c cmd [args]>\n"
5670 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
5671 " camcontrol smpcmd [dev_id][generic args]\n"
5672 " <-r len fmt [args]> <-R len fmt [args]>\n"
5673 " camcontrol smprg [dev_id][generic args][-l]\n"
5674 " camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n"
5675 " [-o operation][-d name][-m rate][-M rate]\n"
5676 " [-T pp_timeout][-a enable|disable]\n"
5677 " [-A enable|disable][-s enable|disable]\n"
5678 " [-S enable|disable]\n"
5679 " camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
5680 " camcontrol smpmaninfo [dev_id][generic args][-l]\n"
5681 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
5682 " <all|bus[:target[:lun]]|off>\n"
5683 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
5684 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
5685 " [-D <enable|disable>][-M mode][-O offset]\n"
5686 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
5687 " [-U][-W bus_width]\n"
5688 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
5689 " camcontrol idle [dev_id][generic args][-t time]\n"
5690 " camcontrol standby [dev_id][generic args][-t time]\n"
5691 " camcontrol sleep [dev_id][generic args]\n"
5692 #endif /* MINIMALISTIC */
5693 " camcontrol help\n");
5696 #ifndef MINIMALISTIC
5698 "Specify one of the following options:\n"
5699 "devlist list all CAM devices\n"
5700 "periphlist list all CAM peripheral drivers attached to a device\n"
5701 "tur send a test unit ready to the named device\n"
5702 "inquiry send a SCSI inquiry command to the named device\n"
5703 "identify send a ATA identify command to the named device\n"
5704 "reportluns send a SCSI report luns command to the device\n"
5705 "readcap send a SCSI read capacity command to the device\n"
5706 "start send a Start Unit command to the device\n"
5707 "stop send a Stop Unit command to the device\n"
5708 "load send a Start Unit command to the device with the load bit set\n"
5709 "eject send a Stop Unit command to the device with the eject bit set\n"
5710 "rescan rescan all busses, the given bus, or bus:target:lun\n"
5711 "reset reset all busses, the given bus, or bus:target:lun\n"
5712 "defects read the defect list of the specified device\n"
5713 "modepage display or edit (-e) the given mode page\n"
5714 "cmd send the given SCSI command, may need -i or -o as well\n"
5715 "smpcmd send the given SMP command, requires -o and -i\n"
5716 "smprg send the SMP Report General command\n"
5717 "smppc send the SMP PHY Control command, requires -p\n"
5718 "smpphylist display phys attached to a SAS expander\n"
5719 "smpmaninfo send the SMP Report Manufacturer Info command\n"
5720 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
5721 "tags report or set the number of transaction slots for a device\n"
5722 "negotiate report or set device negotiation parameters\n"
5723 "format send the SCSI FORMAT UNIT command to the named device\n"
5724 "idle send the ATA IDLE command to the named device\n"
5725 "standby send the ATA STANDBY command to the named device\n"
5726 "sleep send the ATA SLEEP command to the named device\n"
5727 "help this message\n"
5728 "Device Identifiers:\n"
5729 "bus:target specify the bus and target, lun defaults to 0\n"
5730 "bus:target:lun specify the bus, target and lun\n"
5731 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
5732 "Generic arguments:\n"
5733 "-v be verbose, print out sense information\n"
5734 "-t timeout command timeout in seconds, overrides default timeout\n"
5735 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
5736 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
5737 "-E have the kernel attempt to perform SCSI error recovery\n"
5738 "-C count specify the SCSI command retry count (needs -E to work)\n"
5739 "modepage arguments:\n"
5740 "-l list all available mode pages\n"
5741 "-m page specify the mode page to view or edit\n"
5742 "-e edit the specified mode page\n"
5743 "-b force view to binary mode\n"
5744 "-d disable block descriptors for mode sense\n"
5745 "-P pgctl page control field 0-3\n"
5746 "defects arguments:\n"
5747 "-f format specify defect list format (block, bfi or phys)\n"
5748 "-G get the grown defect list\n"
5749 "-P get the permanant defect list\n"
5750 "inquiry arguments:\n"
5751 "-D get the standard inquiry data\n"
5752 "-S get the serial number\n"
5753 "-R get the transfer rate, etc.\n"
5754 "reportluns arguments:\n"
5755 "-c only report a count of available LUNs\n"
5756 "-l only print out luns, and not a count\n"
5757 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
5758 "readcap arguments\n"
5759 "-b only report the blocksize\n"
5760 "-h human readable device size, base 2\n"
5761 "-H human readable device size, base 10\n"
5762 "-N print the number of blocks instead of last block\n"
5763 "-q quiet, print numbers only\n"
5764 "-s only report the last block/device size\n"
5766 "-c cdb [args] specify the SCSI CDB\n"
5767 "-i len fmt specify input data and input data format\n"
5768 "-o len fmt [args] specify output data and output data fmt\n"
5769 "smpcmd arguments:\n"
5770 "-r len fmt [args] specify the SMP command to be sent\n"
5771 "-R len fmt [args] specify SMP response format\n"
5772 "smprg arguments:\n"
5773 "-l specify the long response format\n"
5774 "smppc arguments:\n"
5775 "-p phy specify the PHY to operate on\n"
5776 "-l specify the long request/response format\n"
5777 "-o operation specify the phy control operation\n"
5778 "-d name set the attached device name\n"
5779 "-m rate set the minimum physical link rate\n"
5780 "-M rate set the maximum physical link rate\n"
5781 "-T pp_timeout set the partial pathway timeout value\n"
5782 "-a enable|disable enable or disable SATA slumber\n"
5783 "-A enable|disable enable or disable SATA partial phy power\n"
5784 "-s enable|disable enable or disable SAS slumber\n"
5785 "-S enable|disable enable or disable SAS partial phy power\n"
5786 "smpphylist arguments:\n"
5787 "-l specify the long response format\n"
5788 "-q only print phys with attached devices\n"
5789 "smpmaninfo arguments:\n"
5790 "-l specify the long response format\n"
5791 "debug arguments:\n"
5792 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
5793 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
5794 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
5795 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
5797 "-N tags specify the number of tags to use for this device\n"
5798 "-q be quiet, don't report the number of tags\n"
5799 "-v report a number of tag-related parameters\n"
5800 "negotiate arguments:\n"
5801 "-a send a test unit ready after negotiation\n"
5802 "-c report/set current negotiation settings\n"
5803 "-D <arg> \"enable\" or \"disable\" disconnection\n"
5804 "-M mode set ATA mode\n"
5805 "-O offset set command delay offset\n"
5806 "-q be quiet, don't report anything\n"
5807 "-R syncrate synchronization rate in MHz\n"
5808 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
5809 "-U report/set user negotiation settings\n"
5810 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
5811 "-v also print a Path Inquiry CCB for the controller\n"
5812 "format arguments:\n"
5813 "-q be quiet, don't print status messages\n"
5814 "-r run in report only mode\n"
5815 "-w don't send immediate format command\n"
5816 "-y don't ask any questions\n"
5817 "idle/standby arguments:\n"
5818 "-t <arg> number of seconds before respective state.\n");
5819 #endif /* MINIMALISTIC */
5823 main(int argc, char **argv)
5826 char *device = NULL;
5828 struct cam_device *cam_dev = NULL;
5829 int timeout = 0, retry_count = 1;
5830 camcontrol_optret optreturn;
5832 const char *mainopt = "C:En:t:u:v";
5833 const char *subopt = NULL;
5834 char combinedopt[256];
5835 int error = 0, optstart = 2;
5837 #ifndef MINIMALISTIC
5838 int bus, target, lun;
5839 #endif /* MINIMALISTIC */
5841 cmdlist = CAM_CMD_NONE;
5842 arglist = CAM_ARG_NONE;
5850 * Get the base option.
5852 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
5854 if (optreturn == CC_OR_AMBIGUOUS) {
5855 warnx("ambiguous option %s", argv[1]);
5858 } else if (optreturn == CC_OR_NOT_FOUND) {
5859 warnx("option %s not found", argv[1]);
5865 * Ahh, getopt(3) is a pain.
5867 * This is a gross hack. There really aren't many other good
5868 * options (excuse the pun) for parsing options in a situation like
5869 * this. getopt is kinda braindead, so you end up having to run
5870 * through the options twice, and give each invocation of getopt
5871 * the option string for the other invocation.
5873 * You would think that you could just have two groups of options.
5874 * The first group would get parsed by the first invocation of
5875 * getopt, and the second group would get parsed by the second
5876 * invocation of getopt. It doesn't quite work out that way. When
5877 * the first invocation of getopt finishes, it leaves optind pointing
5878 * to the argument _after_ the first argument in the second group.
5879 * So when the second invocation of getopt comes around, it doesn't
5880 * recognize the first argument it gets and then bails out.
5882 * A nice alternative would be to have a flag for getopt that says
5883 * "just keep parsing arguments even when you encounter an unknown
5884 * argument", but there isn't one. So there's no real clean way to
5885 * easily parse two sets of arguments without having one invocation
5886 * of getopt know about the other.
5888 * Without this hack, the first invocation of getopt would work as
5889 * long as the generic arguments are first, but the second invocation
5890 * (in the subfunction) would fail in one of two ways. In the case
5891 * where you don't set optreset, it would fail because optind may be
5892 * pointing to the argument after the one it should be pointing at.
5893 * In the case where you do set optreset, and reset optind, it would
5894 * fail because getopt would run into the first set of options, which
5895 * it doesn't understand.
5897 * All of this would "sort of" work if you could somehow figure out
5898 * whether optind had been incremented one option too far. The
5899 * mechanics of that, however, are more daunting than just giving
5900 * both invocations all of the expect options for either invocation.
5902 * Needless to say, I wouldn't mind if someone invented a better
5903 * (non-GPL!) command line parsing interface than getopt. I
5904 * wouldn't mind if someone added more knobs to getopt to make it
5905 * work better. Who knows, I may talk myself into doing it someday,
5906 * if the standards weenies let me. As it is, it just leads to
5907 * hackery like this and causes people to avoid it in some cases.
5909 * KDM, September 8th, 1998
5912 sprintf(combinedopt, "%s%s", mainopt, subopt);
5914 sprintf(combinedopt, "%s", mainopt);
5917 * For these options we do not parse optional device arguments and
5918 * we do not open a passthrough device.
5920 if ((cmdlist == CAM_CMD_RESCAN)
5921 || (cmdlist == CAM_CMD_RESET)
5922 || (cmdlist == CAM_CMD_DEVTREE)
5923 || (cmdlist == CAM_CMD_USAGE)
5924 || (cmdlist == CAM_CMD_DEBUG))
5927 #ifndef MINIMALISTIC
5929 && (argc > 2 && argv[2][0] != '-')) {
5933 if (isdigit(argv[2][0])) {
5934 /* device specified as bus:target[:lun] */
5935 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
5937 errx(1, "numeric device specification must "
5938 "be either bus:target, or "
5940 /* default to 0 if lun was not specified */
5941 if ((arglist & CAM_ARG_LUN) == 0) {
5943 arglist |= CAM_ARG_LUN;
5947 if (cam_get_device(argv[2], name, sizeof name, &unit)
5949 errx(1, "%s", cam_errbuf);
5950 device = strdup(name);
5951 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
5955 #endif /* MINIMALISTIC */
5957 * Start getopt processing at argv[2/3], since we've already
5958 * accepted argv[1..2] as the command name, and as a possible
5964 * Now we run through the argument list looking for generic
5965 * options, and ignoring options that possibly belong to
5968 while ((c = getopt(argc, argv, combinedopt))!= -1){
5971 retry_count = strtol(optarg, NULL, 0);
5972 if (retry_count < 0)
5973 errx(1, "retry count %d is < 0",
5975 arglist |= CAM_ARG_RETRIES;
5978 arglist |= CAM_ARG_ERR_RECOVER;
5981 arglist |= CAM_ARG_DEVICE;
5983 while (isspace(*tstr) && (*tstr != '\0'))
5985 device = (char *)strdup(tstr);
5988 timeout = strtol(optarg, NULL, 0);
5990 errx(1, "invalid timeout %d", timeout);
5991 /* Convert the timeout from seconds to ms */
5993 arglist |= CAM_ARG_TIMEOUT;
5996 arglist |= CAM_ARG_UNIT;
5997 unit = strtol(optarg, NULL, 0);
6000 arglist |= CAM_ARG_VERBOSE;
6007 #ifndef MINIMALISTIC
6009 * For most commands we'll want to open the passthrough device
6010 * associated with the specified device. In the case of the rescan
6011 * commands, we don't use a passthrough device at all, just the
6012 * transport layer device.
6015 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
6016 && (((arglist & CAM_ARG_DEVICE) == 0)
6017 || ((arglist & CAM_ARG_UNIT) == 0))) {
6018 errx(1, "subcommand \"%s\" requires a valid device "
6019 "identifier", argv[1]);
6022 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
6023 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
6024 cam_open_spec_device(device,unit,O_RDWR,NULL)))
6026 errx(1,"%s", cam_errbuf);
6028 #endif /* MINIMALISTIC */
6031 * Reset optind to 2, and reset getopt, so these routines can parse
6032 * the arguments again.
6038 #ifndef MINIMALISTIC
6039 case CAM_CMD_DEVLIST:
6040 error = getdevlist(cam_dev);
6042 #endif /* MINIMALISTIC */
6043 case CAM_CMD_DEVTREE:
6044 error = getdevtree();
6046 #ifndef MINIMALISTIC
6048 error = testunitready(cam_dev, retry_count, timeout, 0);
6050 case CAM_CMD_INQUIRY:
6051 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
6052 retry_count, timeout);
6054 case CAM_CMD_IDENTIFY:
6055 error = ataidentify(cam_dev, retry_count, timeout);
6057 case CAM_CMD_STARTSTOP:
6058 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
6059 arglist & CAM_ARG_EJECT, retry_count,
6062 #endif /* MINIMALISTIC */
6063 case CAM_CMD_RESCAN:
6064 error = dorescan_or_reset(argc, argv, 1);
6067 error = dorescan_or_reset(argc, argv, 0);
6069 #ifndef MINIMALISTIC
6070 case CAM_CMD_READ_DEFECTS:
6071 error = readdefects(cam_dev, argc, argv, combinedopt,
6072 retry_count, timeout);
6074 case CAM_CMD_MODE_PAGE:
6075 modepage(cam_dev, argc, argv, combinedopt,
6076 retry_count, timeout);
6078 case CAM_CMD_SCSI_CMD:
6079 error = scsicmd(cam_dev, argc, argv, combinedopt,
6080 retry_count, timeout);
6082 case CAM_CMD_SMP_CMD:
6083 error = smpcmd(cam_dev, argc, argv, combinedopt,
6084 retry_count, timeout);
6086 case CAM_CMD_SMP_RG:
6087 error = smpreportgeneral(cam_dev, argc, argv,
6088 combinedopt, retry_count,
6091 case CAM_CMD_SMP_PC:
6092 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
6093 retry_count, timeout);
6095 case CAM_CMD_SMP_PHYLIST:
6096 error = smpphylist(cam_dev, argc, argv, combinedopt,
6097 retry_count, timeout);
6099 case CAM_CMD_SMP_MANINFO:
6100 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
6101 retry_count, timeout);
6104 error = camdebug(argc, argv, combinedopt);
6107 error = tagcontrol(cam_dev, argc, argv, combinedopt);
6110 error = ratecontrol(cam_dev, retry_count, timeout,
6111 argc, argv, combinedopt);
6113 case CAM_CMD_FORMAT:
6114 error = scsiformat(cam_dev, argc, argv,
6115 combinedopt, retry_count, timeout);
6117 case CAM_CMD_REPORTLUNS:
6118 error = scsireportluns(cam_dev, argc, argv,
6119 combinedopt, retry_count,
6122 case CAM_CMD_READCAP:
6123 error = scsireadcapacity(cam_dev, argc, argv,
6124 combinedopt, retry_count,
6128 case CAM_CMD_STANDBY:
6130 error = atapm(cam_dev, argc, argv,
6131 combinedopt, retry_count,
6134 #endif /* MINIMALISTIC */
6144 if (cam_dev != NULL)
6145 cam_close_device(cam_dev);