Make CAM_NEW_TRAN_CODE default.
[dragonfly.git] / sbin / camcontrol / camcontrol.c
bloba86d0d439fca53073f7d8864b3f03c926a4851a4
1 /*
2 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2005, 2006 Kenneth D. Merry
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
26 * SUCH DAMAGE.
28 * $FreeBSD: src/sbin/camcontrol/camcontrol.c,v 1.21.2.13 2003/01/08 17:55:02 njl Exp $
29 * $DragonFly: src/sbin/camcontrol/camcontrol.c,v 1.10 2008/02/10 00:01:01 pavalos Exp $
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <ctype.h>
40 #include <err.h>
42 #include <cam/cam.h>
43 #include <cam/cam_debug.h>
44 #include <cam/cam_ccb.h>
45 #include <cam/scsi/scsi_all.h>
46 #include <cam/scsi/scsi_da.h>
47 #include <cam/scsi/scsi_pass.h>
48 #include <cam/scsi/scsi_message.h>
49 #include <camlib.h>
50 #include "camcontrol.h"
52 typedef enum {
53 CAM_CMD_NONE = 0x00000000,
54 CAM_CMD_DEVLIST = 0x00000001,
55 CAM_CMD_TUR = 0x00000002,
56 CAM_CMD_INQUIRY = 0x00000003,
57 CAM_CMD_STARTSTOP = 0x00000004,
58 CAM_CMD_RESCAN = 0x00000005,
59 CAM_CMD_READ_DEFECTS = 0x00000006,
60 CAM_CMD_MODE_PAGE = 0x00000007,
61 CAM_CMD_SCSI_CMD = 0x00000008,
62 CAM_CMD_DEVTREE = 0x00000009,
63 CAM_CMD_USAGE = 0x0000000a,
64 CAM_CMD_DEBUG = 0x0000000b,
65 CAM_CMD_RESET = 0x0000000c,
66 CAM_CMD_FORMAT = 0x0000000d,
67 CAM_CMD_TAG = 0x0000000e,
68 CAM_CMD_RATE = 0x0000000f,
69 CAM_CMD_DETACH = 0x00000010,
70 CAM_CMD_REPORTLUNS = 0x00000011
71 } cam_cmdmask;
73 typedef enum {
74 CAM_ARG_NONE = 0x00000000,
75 CAM_ARG_VERBOSE = 0x00000001,
76 CAM_ARG_DEVICE = 0x00000002,
77 CAM_ARG_BUS = 0x00000004,
78 CAM_ARG_TARGET = 0x00000008,
79 CAM_ARG_LUN = 0x00000010,
80 CAM_ARG_EJECT = 0x00000020,
81 CAM_ARG_UNIT = 0x00000040,
82 CAM_ARG_FORMAT_BLOCK = 0x00000080,
83 CAM_ARG_FORMAT_BFI = 0x00000100,
84 CAM_ARG_FORMAT_PHYS = 0x00000200,
85 CAM_ARG_PLIST = 0x00000400,
86 CAM_ARG_GLIST = 0x00000800,
87 CAM_ARG_GET_SERIAL = 0x00001000,
88 CAM_ARG_GET_STDINQ = 0x00002000,
89 CAM_ARG_GET_XFERRATE = 0x00004000,
90 CAM_ARG_INQ_MASK = 0x00007000,
91 CAM_ARG_MODE_EDIT = 0x00008000,
92 CAM_ARG_PAGE_CNTL = 0x00010000,
93 CAM_ARG_TIMEOUT = 0x00020000,
94 CAM_ARG_CMD_IN = 0x00040000,
95 CAM_ARG_CMD_OUT = 0x00080000,
96 CAM_ARG_DBD = 0x00100000,
97 CAM_ARG_ERR_RECOVER = 0x00200000,
98 CAM_ARG_RETRIES = 0x00400000,
99 CAM_ARG_START_UNIT = 0x00800000,
100 CAM_ARG_DEBUG_INFO = 0x01000000,
101 CAM_ARG_DEBUG_TRACE = 0x02000000,
102 CAM_ARG_DEBUG_SUBTRACE = 0x04000000,
103 CAM_ARG_DEBUG_CDB = 0x08000000,
104 CAM_ARG_DEBUG_XPT = 0x10000000,
105 CAM_ARG_DEBUG_PERIPH = 0x20000000,
106 } cam_argmask;
108 struct camcontrol_opts {
109 const char *optname;
110 cam_cmdmask cmdnum;
111 cam_argmask argnum;
112 const char *subopt;
115 #ifndef MINIMALISTIC
116 static const char scsicmd_opts[] = "c:i:o:";
117 static const char readdefect_opts[] = "f:GP";
118 static const char negotiate_opts[] = "acD:O:qR:T:UW:";
119 #endif
121 struct camcontrol_opts option_table[] = {
122 #ifndef MINIMALISTIC
123 {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
124 {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
125 {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
126 {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
127 {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
128 {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
129 {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
130 #endif /* MINIMALISTIC */
131 {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
132 {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
133 #ifndef MINIMALISTIC
134 {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
135 {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
136 {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
137 {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
138 #endif /* MINIMALISTIC */
139 {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
140 #ifndef MINIMALISTIC
141 {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
142 {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
143 {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
144 {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
145 {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
146 {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
147 {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
148 #endif /* MINIMALISTIC */
149 {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
150 {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
151 {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
152 {NULL, 0, 0, NULL}
155 typedef enum {
156 CC_OR_NOT_FOUND,
157 CC_OR_AMBIGUOUS,
158 CC_OR_FOUND
159 } camcontrol_optret;
161 cam_cmdmask cmdlist;
162 cam_argmask arglist;
163 int bus, target, lun;
166 camcontrol_optret getoption(char *, cam_cmdmask *, cam_argmask *,
167 const char **);
168 #ifndef MINIMALISTIC
169 static int getdevlist(struct cam_device *);
170 static int getdevtree(void);
171 static int testunitready(struct cam_device *, int, int, int);
172 static int scsistart(struct cam_device *, int, int, int, int);
173 static int scsidoinquiry(struct cam_device *, int, char **, char *, int,
174 int);
175 static int scsiinquiry(struct cam_device *, int, int);
176 static int scsiserial(struct cam_device *, int, int);
177 static int scsixferrate(struct cam_device *);
178 #endif /* MINIMALISTIC */
179 static int parse_btl(char *, int *, int *, int *, cam_argmask *);
180 static int dorescan_or_reset(int, char **, int);
181 static int rescan_or_reset_bus(int, int);
182 static int scanlun_or_reset_dev(int, int, int, int);
183 #ifndef MINIMALISTIC
184 static int readdefects(struct cam_device *, int, char **, char *, int,
185 int);
186 static void modepage(struct cam_device *, int, char **, char *, int, int);
187 static int scsicmd(struct cam_device *, int, char **, char *, int, int);
188 static int tagcontrol(struct cam_device *, int, char **, char *);
189 static void cts_print(struct cam_device *device,
190 struct ccb_trans_settings *);
191 static void cpi_print(struct ccb_pathinq *);
192 static int get_cpi(struct cam_device *, struct ccb_pathinq *);
193 static int get_print_cts(struct cam_device *, int, int,
194 struct ccb_trans_settings *);
195 static int ratecontrol(struct cam_device *, int, int, int, char **,
196 char *);
197 static int scsiformat(struct cam_device *, int, char **, char *, int, int);
198 static int scsireportluns(struct cam_device *device, int argc, char **argv,
199 char *combinedopt, int retry_count, int timeout);
200 #endif /* MINIMALISTIC */
203 camcontrol_optret
204 getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
205 const char **subopt)
207 struct camcontrol_opts *opts;
208 int num_matches = 0;
210 for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
211 opts++) {
212 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
213 *cmdnum = opts->cmdnum;
214 *argnum = opts->argnum;
215 *subopt = opts->subopt;
216 if (++num_matches > 1)
217 return(CC_OR_AMBIGUOUS);
221 if (num_matches > 0)
222 return(CC_OR_FOUND);
223 else
224 return(CC_OR_NOT_FOUND);
227 #ifndef MINIMALISTIC
228 static int
229 getdevlist(struct cam_device *device)
231 union ccb *ccb;
232 char status[32];
233 int error = 0;
235 ccb = cam_getccb(device);
237 ccb->ccb_h.func_code = XPT_GDEVLIST;
238 ccb->ccb_h.flags = CAM_DIR_NONE;
239 ccb->ccb_h.retry_count = 1;
240 ccb->cgdl.index = 0;
241 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
242 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
243 if (cam_send_ccb(device, ccb) < 0) {
244 perror("error getting device list");
245 cam_freeccb(ccb);
246 return(1);
249 status[0] = '\0';
251 switch (ccb->cgdl.status) {
252 case CAM_GDEVLIST_MORE_DEVS:
253 strcpy(status, "MORE");
254 break;
255 case CAM_GDEVLIST_LAST_DEVICE:
256 strcpy(status, "LAST");
257 break;
258 case CAM_GDEVLIST_LIST_CHANGED:
259 strcpy(status, "CHANGED");
260 break;
261 case CAM_GDEVLIST_ERROR:
262 strcpy(status, "ERROR");
263 error = 1;
264 break;
267 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
268 ccb->cgdl.periph_name,
269 ccb->cgdl.unit_number,
270 ccb->cgdl.generation,
271 ccb->cgdl.index,
272 status);
275 * If the list has changed, we need to start over from the
276 * beginning.
278 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
279 ccb->cgdl.index = 0;
282 cam_freeccb(ccb);
284 return(error);
286 #endif /* MINIMALISTIC */
288 static int
289 getdevtree(void)
291 union ccb ccb;
292 int bufsize, fd;
293 unsigned int i;
294 int need_close = 0;
295 int error = 0;
296 int skip_device = 0;
298 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
299 warn("couldn't open %s", XPT_DEVICE);
300 return(1);
303 bzero(&ccb, sizeof(union ccb));
305 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
306 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
307 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
309 ccb.ccb_h.func_code = XPT_DEV_MATCH;
310 bufsize = sizeof(struct dev_match_result) * 100;
311 ccb.cdm.match_buf_len = bufsize;
312 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
313 if (ccb.cdm.matches == NULL) {
314 warnx("can't malloc memory for matches");
315 close(fd);
316 return(1);
318 ccb.cdm.num_matches = 0;
321 * We fetch all nodes, since we display most of them in the default
322 * case, and all in the verbose case.
324 ccb.cdm.num_patterns = 0;
325 ccb.cdm.pattern_buf_len = 0;
328 * We do the ioctl multiple times if necessary, in case there are
329 * more than 100 nodes in the EDT.
331 do {
332 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
333 warn("error sending CAMIOCOMMAND ioctl");
334 error = 1;
335 break;
338 if ((ccb.ccb_h.status != CAM_REQ_CMP)
339 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
340 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
341 warnx("got CAM error %#x, CDM error %d\n",
342 ccb.ccb_h.status, ccb.cdm.status);
343 error = 1;
344 break;
347 for (i = 0; i < ccb.cdm.num_matches; i++) {
348 switch (ccb.cdm.matches[i].type) {
349 case DEV_MATCH_BUS: {
350 struct bus_match_result *bus_result;
353 * Only print the bus information if the
354 * user turns on the verbose flag.
356 if ((arglist & CAM_ARG_VERBOSE) == 0)
357 break;
359 bus_result =
360 &ccb.cdm.matches[i].result.bus_result;
362 if (need_close) {
363 fprintf(stdout, ")\n");
364 need_close = 0;
367 fprintf(stdout, "scbus%d on %s%d bus %d:\n",
368 bus_result->path_id,
369 bus_result->dev_name,
370 bus_result->unit_number,
371 bus_result->bus_id);
372 break;
374 case DEV_MATCH_DEVICE: {
375 struct device_match_result *dev_result;
376 char vendor[16], product[48], revision[16];
377 char tmpstr[256];
379 dev_result =
380 &ccb.cdm.matches[i].result.device_result;
382 if ((dev_result->flags
383 & DEV_RESULT_UNCONFIGURED)
384 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
385 skip_device = 1;
386 break;
387 } else
388 skip_device = 0;
390 cam_strvis(vendor, dev_result->inq_data.vendor,
391 sizeof(dev_result->inq_data.vendor),
392 sizeof(vendor));
393 cam_strvis(product,
394 dev_result->inq_data.product,
395 sizeof(dev_result->inq_data.product),
396 sizeof(product));
397 cam_strvis(revision,
398 dev_result->inq_data.revision,
399 sizeof(dev_result->inq_data.revision),
400 sizeof(revision));
401 sprintf(tmpstr, "<%s %s %s>", vendor, product,
402 revision);
403 if (need_close) {
404 fprintf(stdout, ")\n");
405 need_close = 0;
408 fprintf(stdout, "%-33s at scbus%d "
409 "target %d lun %d (",
410 tmpstr,
411 dev_result->path_id,
412 dev_result->target_id,
413 dev_result->target_lun);
415 need_close = 1;
417 break;
419 case DEV_MATCH_PERIPH: {
420 struct periph_match_result *periph_result;
422 periph_result =
423 &ccb.cdm.matches[i].result.periph_result;
425 if (skip_device != 0)
426 break;
428 if (need_close > 1)
429 fprintf(stdout, ",");
431 fprintf(stdout, "%s%d",
432 periph_result->periph_name,
433 periph_result->unit_number);
435 need_close++;
436 break;
438 default:
439 fprintf(stdout, "unknown match type\n");
440 break;
444 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
445 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
447 if (need_close)
448 fprintf(stdout, ")\n");
450 close(fd);
452 return(error);
455 #ifndef MINIMALISTIC
456 static int
457 testunitready(struct cam_device *device, int retry_count, int timeout,
458 int quiet)
460 int error = 0;
461 union ccb *ccb;
463 ccb = cam_getccb(device);
465 scsi_test_unit_ready(&ccb->csio,
466 /* retries */ retry_count,
467 /* cbfcnp */ NULL,
468 /* tag_action */ MSG_SIMPLE_Q_TAG,
469 /* sense_len */ SSD_FULL_SIZE,
470 /* timeout */ timeout ? timeout : 5000);
472 /* Disable freezing the device queue */
473 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
475 if (arglist & CAM_ARG_ERR_RECOVER)
476 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
478 if (cam_send_ccb(device, ccb) < 0) {
479 if (quiet == 0)
480 perror("error sending test unit ready");
482 if (arglist & CAM_ARG_VERBOSE) {
483 cam_error_print(device, ccb, CAM_ESF_ALL,
484 CAM_EPF_ALL, stderr);
487 cam_freeccb(ccb);
488 return(1);
491 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
492 if (quiet == 0)
493 fprintf(stdout, "Unit is ready\n");
494 } else {
495 if (quiet == 0)
496 fprintf(stdout, "Unit is not ready\n");
497 error = 1;
499 if (arglist & CAM_ARG_VERBOSE) {
500 cam_error_print(device, ccb, CAM_ESF_ALL,
501 CAM_EPF_ALL, stderr);
505 cam_freeccb(ccb);
507 return(error);
510 static int
511 scsistart(struct cam_device *device, int startstop, int loadeject,
512 int retry_count, int timeout)
514 union ccb *ccb;
515 int error = 0;
517 ccb = cam_getccb(device);
520 * If we're stopping, send an ordered tag so the drive in question
521 * will finish any previously queued writes before stopping. If
522 * the device isn't capable of tagged queueing, or if tagged
523 * queueing is turned off, the tag action is a no-op.
525 scsi_start_stop(&ccb->csio,
526 /* retries */ retry_count,
527 /* cbfcnp */ NULL,
528 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
529 MSG_ORDERED_Q_TAG,
530 /* start/stop */ startstop,
531 /* load_eject */ loadeject,
532 /* immediate */ 0,
533 /* sense_len */ SSD_FULL_SIZE,
534 /* timeout */ timeout ? timeout : 120000);
536 /* Disable freezing the device queue */
537 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
539 if (arglist & CAM_ARG_ERR_RECOVER)
540 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
542 if (cam_send_ccb(device, ccb) < 0) {
543 perror("error sending start unit");
545 if (arglist & CAM_ARG_VERBOSE) {
546 cam_error_print(device, ccb, CAM_ESF_ALL,
547 CAM_EPF_ALL, stderr);
550 cam_freeccb(ccb);
551 return(1);
554 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
555 if (startstop) {
556 fprintf(stdout, "Unit started successfully");
557 if (loadeject)
558 fprintf(stdout,", Media loaded\n");
559 else
560 fprintf(stdout,"\n");
561 } else {
562 fprintf(stdout, "Unit stopped successfully");
563 if (loadeject)
564 fprintf(stdout, ", Media ejected\n");
565 else
566 fprintf(stdout, "\n");
568 else {
569 error = 1;
570 if (startstop)
571 fprintf(stdout,
572 "Error received from start unit command\n");
573 else
574 fprintf(stdout,
575 "Error received from stop unit command\n");
577 if (arglist & CAM_ARG_VERBOSE) {
578 cam_error_print(device, ccb, CAM_ESF_ALL,
579 CAM_EPF_ALL, stderr);
583 cam_freeccb(ccb);
585 return(error);
588 static int
589 scsidoinquiry(struct cam_device *device, int argc, char **argv,
590 char *combinedopt, int retry_count, int timeout)
592 int c;
593 int error = 0;
595 while ((c = getopt(argc, argv, combinedopt)) != -1) {
596 switch(c) {
597 case 'D':
598 arglist |= CAM_ARG_GET_STDINQ;
599 break;
600 case 'R':
601 arglist |= CAM_ARG_GET_XFERRATE;
602 break;
603 case 'S':
604 arglist |= CAM_ARG_GET_SERIAL;
605 break;
606 default:
607 break;
612 * If the user didn't specify any inquiry options, he wants all of
613 * them.
615 if ((arglist & CAM_ARG_INQ_MASK) == 0)
616 arglist |= CAM_ARG_INQ_MASK;
618 if (arglist & CAM_ARG_GET_STDINQ)
619 error = scsiinquiry(device, retry_count, timeout);
621 if (error != 0)
622 return(error);
624 if (arglist & CAM_ARG_GET_SERIAL)
625 scsiserial(device, retry_count, timeout);
627 if (error != 0)
628 return(error);
630 if (arglist & CAM_ARG_GET_XFERRATE)
631 error = scsixferrate(device);
633 return(error);
636 static int
637 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
639 union ccb *ccb;
640 struct scsi_inquiry_data *inq_buf;
641 int error = 0;
643 ccb = cam_getccb(device);
645 if (ccb == NULL) {
646 warnx("couldn't allocate CCB");
647 return(1);
650 /* cam_getccb cleans up the header, caller has to zero the payload */
651 bzero(&(&ccb->ccb_h)[1],
652 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
654 inq_buf = (struct scsi_inquiry_data *)malloc(
655 sizeof(struct scsi_inquiry_data));
657 if (inq_buf == NULL) {
658 cam_freeccb(ccb);
659 warnx("can't malloc memory for inquiry\n");
660 return(1);
662 bzero(inq_buf, sizeof(*inq_buf));
665 * Note that although the size of the inquiry buffer is the full
666 * 256 bytes specified in the SCSI spec, we only tell the device
667 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
668 * two reasons for this:
670 * - The SCSI spec says that when a length field is only 1 byte,
671 * a value of 0 will be interpreted as 256. Therefore
672 * scsi_inquiry() will convert an inq_len (which is passed in as
673 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
674 * to 0. Evidently, very few devices meet the spec in that
675 * regard. Some devices, like many Seagate disks, take the 0 as
676 * 0, and don't return any data. One Pioneer DVD-R drive
677 * returns more data than the command asked for.
679 * So, since there are numerous devices that just don't work
680 * right with the full inquiry size, we don't send the full size.
682 * - The second reason not to use the full inquiry data length is
683 * that we don't need it here. The only reason we issue a
684 * standard inquiry is to get the vendor name, device name,
685 * and revision so scsi_print_inquiry() can print them.
687 * If, at some point in the future, more inquiry data is needed for
688 * some reason, this code should use a procedure similar to the
689 * probe code. i.e., issue a short inquiry, and determine from
690 * the additional length passed back from the device how much
691 * inquiry data the device supports. Once the amount the device
692 * supports is determined, issue an inquiry for that amount and no
693 * more.
695 * KDM, 2/18/2000
697 scsi_inquiry(&ccb->csio,
698 /* retries */ retry_count,
699 /* cbfcnp */ NULL,
700 /* tag_action */ MSG_SIMPLE_Q_TAG,
701 /* inq_buf */ (u_int8_t *)inq_buf,
702 /* inq_len */ SHORT_INQUIRY_LENGTH,
703 /* evpd */ 0,
704 /* page_code */ 0,
705 /* sense_len */ SSD_FULL_SIZE,
706 /* timeout */ timeout ? timeout : 5000);
708 /* Disable freezing the device queue */
709 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
711 if (arglist & CAM_ARG_ERR_RECOVER)
712 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
714 if (cam_send_ccb(device, ccb) < 0) {
715 perror("error sending SCSI inquiry");
717 if (arglist & CAM_ARG_VERBOSE) {
718 cam_error_print(device, ccb, CAM_ESF_ALL,
719 CAM_EPF_ALL, stderr);
722 cam_freeccb(ccb);
723 return(1);
726 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
727 error = 1;
729 if (arglist & CAM_ARG_VERBOSE) {
730 cam_error_print(device, ccb, CAM_ESF_ALL,
731 CAM_EPF_ALL, stderr);
735 cam_freeccb(ccb);
737 if (error != 0) {
738 free(inq_buf);
739 return(error);
742 fprintf(stdout, "%s%d: ", device->device_name,
743 device->dev_unit_num);
744 scsi_print_inquiry(inq_buf);
746 free(inq_buf);
748 return(0);
751 static int
752 scsiserial(struct cam_device *device, int retry_count, int timeout)
754 union ccb *ccb;
755 struct scsi_vpd_unit_serial_number *serial_buf;
756 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
757 int error = 0;
759 ccb = cam_getccb(device);
761 if (ccb == NULL) {
762 warnx("couldn't allocate CCB");
763 return(1);
766 /* cam_getccb cleans up the header, caller has to zero the payload */
767 bzero(&(&ccb->ccb_h)[1],
768 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
770 serial_buf = (struct scsi_vpd_unit_serial_number *)
771 malloc(sizeof(*serial_buf));
773 if (serial_buf == NULL) {
774 cam_freeccb(ccb);
775 warnx("can't malloc memory for serial number");
776 return(1);
779 scsi_inquiry(&ccb->csio,
780 /*retries*/ retry_count,
781 /*cbfcnp*/ NULL,
782 /* tag_action */ MSG_SIMPLE_Q_TAG,
783 /* inq_buf */ (u_int8_t *)serial_buf,
784 /* inq_len */ sizeof(*serial_buf),
785 /* evpd */ 1,
786 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
787 /* sense_len */ SSD_FULL_SIZE,
788 /* timeout */ timeout ? timeout : 5000);
790 /* Disable freezing the device queue */
791 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
793 if (arglist & CAM_ARG_ERR_RECOVER)
794 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
796 if (cam_send_ccb(device, ccb) < 0) {
797 warn("error getting serial number");
799 if (arglist & CAM_ARG_VERBOSE) {
800 cam_error_print(device, ccb, CAM_ESF_ALL,
801 CAM_EPF_ALL, stderr);
804 cam_freeccb(ccb);
805 free(serial_buf);
806 return(1);
809 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
810 error = 1;
812 if (arglist & CAM_ARG_VERBOSE) {
813 cam_error_print(device, ccb, CAM_ESF_ALL,
814 CAM_EPF_ALL, stderr);
818 cam_freeccb(ccb);
820 if (error != 0) {
821 free(serial_buf);
822 return(error);
825 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
826 serial_num[serial_buf->length] = '\0';
828 if ((arglist & CAM_ARG_GET_STDINQ)
829 || (arglist & CAM_ARG_GET_XFERRATE))
830 fprintf(stdout, "%s%d: Serial Number ",
831 device->device_name, device->dev_unit_num);
833 fprintf(stdout, "%.60s\n", serial_num);
835 free(serial_buf);
837 return(0);
840 static int
841 scsixferrate(struct cam_device *device)
843 u_int32_t freq = 0;
844 u_int32_t speed = 0;
845 union ccb *ccb;
846 u_int mb;
847 int retval = 0;
849 ccb = cam_getccb(device);
851 if (ccb == NULL) {
852 warnx("couldn't allocate CCB");
853 return(1);
856 bzero(&(&ccb->ccb_h)[1],
857 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
859 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
860 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
862 if (((retval = cam_send_ccb(device, ccb)) < 0)
863 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
864 const char error_string[] = "error getting transfer settings";
866 if (retval < 0)
867 warn(error_string);
868 else
869 warnx(error_string);
871 if (arglist & CAM_ARG_VERBOSE)
872 cam_error_print(device, ccb, CAM_ESF_ALL,
873 CAM_EPF_ALL, stderr);
875 retval = 1;
877 goto xferrate_bailout;
881 if (ccb->cts.transport == XPORT_SPI) {
882 struct ccb_trans_settings_spi *spi =
883 &ccb->cts.xport_specific.spi;
885 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
886 freq = scsi_calc_syncsrate(spi->sync_period);
887 speed = freq;
890 fprintf(stdout, "%s%d: ", device->device_name,
891 device->dev_unit_num);
893 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
894 speed *= (0x01 << spi->bus_width);
897 mb = speed / 1000;
899 if (mb > 0)
900 fprintf(stdout, "%d.%03dMB/s transfers ",
901 mb, speed % 1000);
902 else
903 fprintf(stdout, "%dKB/s transfers ",
904 speed);
906 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
907 && (spi->sync_offset != 0))
908 fprintf(stdout, "(%d.%03dMHz, offset %d", freq / 1000,
909 freq % 1000, spi->sync_offset);
911 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
912 && (spi->bus_width > 0)) {
913 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
914 && (spi->sync_offset != 0)) {
915 fprintf(stdout, ", ");
916 } else {
917 fprintf(stdout, " (");
919 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
920 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
921 && (spi->sync_offset != 0)) {
922 fprintf(stdout, ")");
924 } else {
925 struct ccb_pathinq cpi;
927 retval = get_cpi(device, &cpi);
929 if (retval != 0)
930 goto xferrate_bailout;
932 speed = cpi.base_transfer_speed;
933 freq = 0;
935 mb = speed / 1000;
937 if (mb > 0)
938 fprintf(stdout, "%d.%03dMB/s transfers ",
939 mb, speed % 1000);
940 else
941 fprintf(stdout, "%dKB/s transfers ",
942 speed);
945 if (ccb->cts.protocol == PROTO_SCSI) {
946 struct ccb_trans_settings_scsi *scsi =
947 &ccb->cts.proto_specific.scsi;
948 if (scsi->valid & CTS_SCSI_VALID_TQ) {
949 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB)
950 fprintf(stdout, ", Command Queueing Enabled");
951 else
952 fprintf(stdout, ", Command Queueing Supported");
956 fprintf(stdout, "\n");
958 xferrate_bailout:
960 cam_freeccb(ccb);
962 return(retval);
964 #endif /* MINIMALISTIC */
967 * Parse out a bus, or a bus, target and lun in the following
968 * format:
969 * bus
970 * bus:target
971 * bus:target:lun
973 * Returns the number of parsed components, or 0.
975 static int
976 parse_btl(char *tstr, int *mybus, int *mytarget, int *mylun,
977 cam_argmask *myarglist)
979 char *tmpstr;
980 int convs = 0;
982 while (isspace(*tstr) && (*tstr != '\0'))
983 tstr++;
985 tmpstr = (char *)strtok(tstr, ":");
986 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
987 *mybus = strtol(tmpstr, NULL, 0);
988 *myarglist |= CAM_ARG_BUS;
989 convs++;
990 tmpstr = (char *)strtok(NULL, ":");
991 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
992 *mytarget = strtol(tmpstr, NULL, 0);
993 *myarglist |= CAM_ARG_TARGET;
994 convs++;
995 tmpstr = (char *)strtok(NULL, ":");
996 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
997 *mylun = strtol(tmpstr, NULL, 0);
998 *myarglist |= CAM_ARG_LUN;
999 convs++;
1004 return convs;
1007 static int
1008 dorescan_or_reset(int argc, char **argv, int rescan)
1010 static const char must[] =
1011 "you must specify \"all\", a bus, or a bus:target:lun to %s";
1012 int rv, error = 0;
1013 int mybus = -1, mytarget = -1, mylun = -1;
1014 char *tstr;
1016 if (argc < 3) {
1017 warnx(must, rescan? "rescan" : "reset");
1018 return(1);
1021 tstr = argv[optind];
1022 while (isspace(*tstr) && (*tstr != '\0'))
1023 tstr++;
1024 if (strncasecmp(tstr, "all", strlen("all")) == 0)
1025 arglist |= CAM_ARG_BUS;
1026 else {
1027 rv = parse_btl(argv[optind], &mybus, &mytarget, &mylun,
1028 &arglist);
1029 if (rv != 1 && rv != 3) {
1030 warnx(must, rescan? "rescan" : "reset");
1031 return(1);
1035 if ((arglist & CAM_ARG_BUS)
1036 && (arglist & CAM_ARG_TARGET)
1037 && (arglist & CAM_ARG_LUN))
1038 error = scanlun_or_reset_dev(mybus, mytarget, mylun, rescan);
1039 else
1040 error = rescan_or_reset_bus(mybus, rescan);
1042 return(error);
1045 static int
1046 rescan_or_reset_bus(int mybus, int rescan)
1048 union ccb ccb, matchccb;
1049 int fd, retval;
1050 int bufsize;
1052 retval = 0;
1054 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1055 warnx("error opening transport layer device %s", XPT_DEVICE);
1056 warn("%s", XPT_DEVICE);
1057 return(1);
1060 if (mybus != -1) {
1061 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1062 ccb.ccb_h.path_id = mybus;
1063 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1064 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1065 ccb.crcn.flags = CAM_FLAG_NONE;
1067 /* run this at a low priority */
1068 ccb.ccb_h.pinfo.priority = 5;
1070 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1071 warn("CAMIOCOMMAND ioctl failed");
1072 close(fd);
1073 return(1);
1076 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1077 fprintf(stdout, "%s of bus %d was successful\n",
1078 rescan ? "Re-scan" : "Reset", mybus);
1079 } else {
1080 fprintf(stdout, "%s of bus %d returned error %#x\n",
1081 rescan ? "Re-scan" : "Reset", mybus,
1082 ccb.ccb_h.status & CAM_STATUS_MASK);
1083 retval = 1;
1086 close(fd);
1087 return(retval);
1093 * The right way to handle this is to modify the xpt so that it can
1094 * handle a wildcarded bus in a rescan or reset CCB. At the moment
1095 * that isn't implemented, so instead we enumerate the busses and
1096 * send the rescan or reset to those busses in the case where the
1097 * given bus is -1 (wildcard). We don't send a rescan or reset
1098 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1099 * no-op, sending a rescan to the xpt bus would result in a status of
1100 * CAM_REQ_INVALID.
1102 bzero(&(&matchccb.ccb_h)[1],
1103 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1104 matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1105 bufsize = sizeof(struct dev_match_result) * 20;
1106 matchccb.cdm.match_buf_len = bufsize;
1107 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1108 if (matchccb.cdm.matches == NULL) {
1109 warnx("can't malloc memory for matches");
1110 retval = 1;
1111 goto bailout;
1113 matchccb.cdm.num_matches = 0;
1115 matchccb.cdm.num_patterns = 1;
1116 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1118 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1119 matchccb.cdm.pattern_buf_len);
1120 if (matchccb.cdm.patterns == NULL) {
1121 warnx("can't malloc memory for patterns");
1122 retval = 1;
1123 goto bailout;
1125 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1126 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1128 do {
1129 unsigned int i;
1131 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1132 warn("CAMIOCOMMAND ioctl failed");
1133 retval = 1;
1134 goto bailout;
1137 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1138 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1139 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1140 warnx("got CAM error %#x, CDM error %d\n",
1141 matchccb.ccb_h.status, matchccb.cdm.status);
1142 retval = 1;
1143 goto bailout;
1146 for (i = 0; i < matchccb.cdm.num_matches; i++) {
1147 struct bus_match_result *bus_result;
1149 /* This shouldn't happen. */
1150 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1151 continue;
1153 bus_result = &matchccb.cdm.matches[i].result.bus_result;
1156 * We don't want to rescan or reset the xpt bus.
1157 * See above.
1159 if ((int)bus_result->path_id == -1)
1160 continue;
1162 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1163 XPT_RESET_BUS;
1164 ccb.ccb_h.path_id = bus_result->path_id;
1165 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1166 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1167 ccb.crcn.flags = CAM_FLAG_NONE;
1169 /* run this at a low priority */
1170 ccb.ccb_h.pinfo.priority = 5;
1172 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1173 warn("CAMIOCOMMAND ioctl failed");
1174 retval = 1;
1175 goto bailout;
1178 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1179 fprintf(stdout, "%s of bus %d was successful\n",
1180 rescan? "Re-scan" : "Reset",
1181 bus_result->path_id);
1182 } else {
1184 * Don't bail out just yet, maybe the other
1185 * rescan or reset commands will complete
1186 * successfully.
1188 fprintf(stderr, "%s of bus %d returned error "
1189 "%#x\n", rescan? "Re-scan" : "Reset",
1190 bus_result->path_id,
1191 ccb.ccb_h.status & CAM_STATUS_MASK);
1192 retval = 1;
1195 } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1196 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1198 bailout:
1200 if (fd != -1)
1201 close(fd);
1203 if (matchccb.cdm.patterns != NULL)
1204 free(matchccb.cdm.patterns);
1205 if (matchccb.cdm.matches != NULL)
1206 free(matchccb.cdm.matches);
1208 return(retval);
1211 static int
1212 scanlun_or_reset_dev(int mybus, int mytarget, int mylun, int scan)
1214 union ccb ccb;
1215 struct cam_device *device;
1216 int fd;
1218 device = NULL;
1220 if (mybus < 0) {
1221 warnx("invalid bus number %d", mybus);
1222 return(1);
1225 if (mytarget < 0) {
1226 warnx("invalid target number %d", mytarget);
1227 return(1);
1230 if (mylun < 0) {
1231 warnx("invalid lun number %d", mylun);
1232 return(1);
1235 fd = -1;
1237 bzero(&ccb, sizeof(union ccb));
1239 if (scan) {
1240 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1241 warnx("error opening transport layer device %s\n",
1242 XPT_DEVICE);
1243 warn("%s", XPT_DEVICE);
1244 return(1);
1246 } else {
1247 device = cam_open_btl(mybus, mytarget, mylun, O_RDWR, NULL);
1248 if (device == NULL) {
1249 warnx("%s", cam_errbuf);
1250 return(1);
1254 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1255 ccb.ccb_h.path_id = mybus;
1256 ccb.ccb_h.target_id = mytarget;
1257 ccb.ccb_h.target_lun = mylun;
1258 ccb.ccb_h.timeout = 5000;
1259 ccb.crcn.flags = CAM_FLAG_NONE;
1261 /* run this at a low priority */
1262 ccb.ccb_h.pinfo.priority = 5;
1264 if (scan) {
1265 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1266 warn("CAMIOCOMMAND ioctl failed");
1267 close(fd);
1268 return(1);
1270 } else {
1271 if (cam_send_ccb(device, &ccb) < 0) {
1272 warn("error sending XPT_RESET_DEV CCB");
1273 cam_close_device(device);
1274 return(1);
1278 if (scan)
1279 close(fd);
1280 else
1281 cam_close_device(device);
1284 * An error code of CAM_BDR_SENT is normal for a BDR request.
1286 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1287 || ((!scan)
1288 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1289 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1290 scan? "Re-scan" : "Reset", mybus, mytarget, mylun);
1291 return(0);
1292 } else {
1293 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1294 scan? "Re-scan" : "Reset", mybus, mytarget, mylun,
1295 ccb.ccb_h.status & CAM_STATUS_MASK);
1296 return(1);
1300 #ifndef MINIMALISTIC
1301 static int
1302 readdefects(struct cam_device *device, int argc, char **argv,
1303 char *combinedopt, int retry_count, int timeout)
1305 union ccb *ccb = NULL;
1306 struct scsi_read_defect_data_10 *rdd_cdb;
1307 u_int8_t *defect_list = NULL;
1308 u_int32_t dlist_length = 65000;
1309 u_int32_t returned_length = 0;
1310 u_int32_t num_returned = 0;
1311 u_int8_t returned_format;
1312 unsigned int i;
1313 int c, error = 0;
1314 int lists_specified = 0;
1316 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1317 switch(c){
1318 case 'f':
1320 char *tstr;
1321 tstr = optarg;
1322 while (isspace(*tstr) && (*tstr != '\0'))
1323 tstr++;
1324 if (strcmp(tstr, "block") == 0)
1325 arglist |= CAM_ARG_FORMAT_BLOCK;
1326 else if (strcmp(tstr, "bfi") == 0)
1327 arglist |= CAM_ARG_FORMAT_BFI;
1328 else if (strcmp(tstr, "phys") == 0)
1329 arglist |= CAM_ARG_FORMAT_PHYS;
1330 else {
1331 error = 1;
1332 warnx("invalid defect format %s", tstr);
1333 goto defect_bailout;
1335 break;
1337 case 'G':
1338 arglist |= CAM_ARG_GLIST;
1339 break;
1340 case 'P':
1341 arglist |= CAM_ARG_PLIST;
1342 break;
1343 default:
1344 break;
1348 ccb = cam_getccb(device);
1351 * Hopefully 65000 bytes is enough to hold the defect list. If it
1352 * isn't, the disk is probably dead already. We'd have to go with
1353 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1354 * to hold them all.
1356 defect_list = malloc(dlist_length);
1357 if (defect_list == NULL) {
1358 warnx("can't malloc memory for defect list");
1359 error = 1;
1360 goto defect_bailout;
1363 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1366 * cam_getccb() zeros the CCB header only. So we need to zero the
1367 * payload portion of the ccb.
1369 bzero(&(&ccb->ccb_h)[1],
1370 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1372 cam_fill_csio(&ccb->csio,
1373 /*retries*/ retry_count,
1374 /*cbfcnp*/ NULL,
1375 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1376 CAM_PASS_ERR_RECOVER : 0),
1377 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1378 /*data_ptr*/ defect_list,
1379 /*dxfer_len*/ dlist_length,
1380 /*sense_len*/ SSD_FULL_SIZE,
1381 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1382 /*timeout*/ timeout ? timeout : 5000);
1384 rdd_cdb->opcode = READ_DEFECT_DATA_10;
1385 if (arglist & CAM_ARG_FORMAT_BLOCK)
1386 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1387 else if (arglist & CAM_ARG_FORMAT_BFI)
1388 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1389 else if (arglist & CAM_ARG_FORMAT_PHYS)
1390 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1391 else {
1392 error = 1;
1393 warnx("no defect list format specified");
1394 goto defect_bailout;
1396 if (arglist & CAM_ARG_PLIST) {
1397 rdd_cdb->format |= SRDD10_PLIST;
1398 lists_specified++;
1401 if (arglist & CAM_ARG_GLIST) {
1402 rdd_cdb->format |= SRDD10_GLIST;
1403 lists_specified++;
1406 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1408 /* Disable freezing the device queue */
1409 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1411 if (cam_send_ccb(device, ccb) < 0) {
1412 perror("error reading defect list");
1414 if (arglist & CAM_ARG_VERBOSE) {
1415 cam_error_print(device, ccb, CAM_ESF_ALL,
1416 CAM_EPF_ALL, stderr);
1419 error = 1;
1420 goto defect_bailout;
1423 returned_length = scsi_2btoul(((struct
1424 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1426 returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1427 defect_list)->format;
1429 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1430 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1431 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1432 struct scsi_sense_data *sense;
1433 int error_code, sense_key, asc, ascq;
1435 sense = &ccb->csio.sense_data;
1436 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1439 * According to the SCSI spec, if the disk doesn't support
1440 * the requested format, it will generally return a sense
1441 * key of RECOVERED ERROR, and an additional sense code
1442 * of "DEFECT LIST NOT FOUND". So, we check for that, and
1443 * also check to make sure that the returned length is
1444 * greater than 0, and then print out whatever format the
1445 * disk gave us.
1447 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1448 && (asc == 0x1c) && (ascq == 0x00)
1449 && (returned_length > 0)) {
1450 warnx("requested defect format not available");
1451 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1452 case SRDD10_BLOCK_FORMAT:
1453 warnx("Device returned block format");
1454 break;
1455 case SRDD10_BYTES_FROM_INDEX_FORMAT:
1456 warnx("Device returned bytes from index"
1457 " format");
1458 break;
1459 case SRDD10_PHYSICAL_SECTOR_FORMAT:
1460 warnx("Device returned physical sector format");
1461 break;
1462 default:
1463 error = 1;
1464 warnx("Device returned unknown defect"
1465 " data format %#x", returned_format);
1466 goto defect_bailout;
1467 break; /* NOTREACHED */
1469 } else {
1470 error = 1;
1471 warnx("Error returned from read defect data command");
1472 if (arglist & CAM_ARG_VERBOSE)
1473 cam_error_print(device, ccb, CAM_ESF_ALL,
1474 CAM_EPF_ALL, stderr);
1475 goto defect_bailout;
1477 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1478 error = 1;
1479 warnx("Error returned from read defect data command");
1480 if (arglist & CAM_ARG_VERBOSE)
1481 cam_error_print(device, ccb, CAM_ESF_ALL,
1482 CAM_EPF_ALL, stderr);
1483 goto defect_bailout;
1487 * XXX KDM I should probably clean up the printout format for the
1488 * disk defects.
1490 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1491 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1493 struct scsi_defect_desc_phys_sector *dlist;
1495 dlist = (struct scsi_defect_desc_phys_sector *)
1496 (defect_list +
1497 sizeof(struct scsi_read_defect_data_hdr_10));
1499 num_returned = returned_length /
1500 sizeof(struct scsi_defect_desc_phys_sector);
1502 fprintf(stderr, "Got %d defect", num_returned);
1504 if ((lists_specified == 0) || (num_returned == 0)) {
1505 fprintf(stderr, "s.\n");
1506 break;
1507 } else if (num_returned == 1)
1508 fprintf(stderr, ":\n");
1509 else
1510 fprintf(stderr, "s:\n");
1512 for (i = 0; i < num_returned; i++) {
1513 fprintf(stdout, "%d:%d:%d\n",
1514 scsi_3btoul(dlist[i].cylinder),
1515 dlist[i].head,
1516 scsi_4btoul(dlist[i].sector));
1518 break;
1520 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1522 struct scsi_defect_desc_bytes_from_index *dlist;
1524 dlist = (struct scsi_defect_desc_bytes_from_index *)
1525 (defect_list +
1526 sizeof(struct scsi_read_defect_data_hdr_10));
1528 num_returned = returned_length /
1529 sizeof(struct scsi_defect_desc_bytes_from_index);
1531 fprintf(stderr, "Got %d defect", num_returned);
1533 if ((lists_specified == 0) || (num_returned == 0)) {
1534 fprintf(stderr, "s.\n");
1535 break;
1536 } else if (num_returned == 1)
1537 fprintf(stderr, ":\n");
1538 else
1539 fprintf(stderr, "s:\n");
1541 for (i = 0; i < num_returned; i++) {
1542 fprintf(stdout, "%d:%d:%d\n",
1543 scsi_3btoul(dlist[i].cylinder),
1544 dlist[i].head,
1545 scsi_4btoul(dlist[i].bytes_from_index));
1547 break;
1549 case SRDDH10_BLOCK_FORMAT:
1551 struct scsi_defect_desc_block *dlist;
1553 dlist = (struct scsi_defect_desc_block *)(defect_list +
1554 sizeof(struct scsi_read_defect_data_hdr_10));
1556 num_returned = returned_length /
1557 sizeof(struct scsi_defect_desc_block);
1559 fprintf(stderr, "Got %d defect", num_returned);
1561 if ((lists_specified == 0) || (num_returned == 0)) {
1562 fprintf(stderr, "s.\n");
1563 break;
1564 } else if (num_returned == 1)
1565 fprintf(stderr, ":\n");
1566 else
1567 fprintf(stderr, "s:\n");
1569 for (i = 0; i < num_returned; i++)
1570 fprintf(stdout, "%u\n",
1571 scsi_4btoul(dlist[i].address));
1572 break;
1574 default:
1575 fprintf(stderr, "Unknown defect format %d\n",
1576 returned_format & SRDDH10_DLIST_FORMAT_MASK);
1577 error = 1;
1578 break;
1580 defect_bailout:
1582 if (defect_list != NULL)
1583 free(defect_list);
1585 if (ccb != NULL)
1586 cam_freeccb(ccb);
1588 return(error);
1590 #endif /* MINIMALISTIC */
1592 #if 0
1593 void
1594 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
1596 union ccb *ccb;
1598 ccb = cam_getccb(device);
1600 cam_freeccb(ccb);
1602 #endif
1604 #ifndef MINIMALISTIC
1605 void
1606 mode_sense(struct cam_device *device, int mode_page, int page_control,
1607 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
1609 union ccb *ccb;
1610 int retval;
1612 ccb = cam_getccb(device);
1614 if (ccb == NULL)
1615 errx(1, "mode_sense: couldn't allocate CCB");
1617 bzero(&(&ccb->ccb_h)[1],
1618 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1620 scsi_mode_sense(&ccb->csio,
1621 /* retries */ retry_count,
1622 /* cbfcnp */ NULL,
1623 /* tag_action */ MSG_SIMPLE_Q_TAG,
1624 /* dbd */ dbd,
1625 /* page_code */ page_control << 6,
1626 /* page */ mode_page,
1627 /* param_buf */ data,
1628 /* param_len */ datalen,
1629 /* sense_len */ SSD_FULL_SIZE,
1630 /* timeout */ timeout ? timeout : 5000);
1632 if (arglist & CAM_ARG_ERR_RECOVER)
1633 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1635 /* Disable freezing the device queue */
1636 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1638 if (((retval = cam_send_ccb(device, ccb)) < 0)
1639 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1640 if (arglist & CAM_ARG_VERBOSE) {
1641 cam_error_print(device, ccb, CAM_ESF_ALL,
1642 CAM_EPF_ALL, stderr);
1644 cam_freeccb(ccb);
1645 cam_close_device(device);
1646 if (retval < 0)
1647 err(1, "error sending mode sense command");
1648 else
1649 errx(1, "error sending mode sense command");
1652 cam_freeccb(ccb);
1655 void
1656 mode_select(struct cam_device *device, int save_pages, int retry_count,
1657 int timeout, u_int8_t *data, int datalen)
1659 union ccb *ccb;
1660 int retval;
1662 ccb = cam_getccb(device);
1664 if (ccb == NULL)
1665 errx(1, "mode_select: couldn't allocate CCB");
1667 bzero(&(&ccb->ccb_h)[1],
1668 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1670 scsi_mode_select(&ccb->csio,
1671 /* retries */ retry_count,
1672 /* cbfcnp */ NULL,
1673 /* tag_action */ MSG_SIMPLE_Q_TAG,
1674 /* scsi_page_fmt */ 1,
1675 /* save_pages */ save_pages,
1676 /* param_buf */ data,
1677 /* param_len */ datalen,
1678 /* sense_len */ SSD_FULL_SIZE,
1679 /* timeout */ timeout ? timeout : 5000);
1681 if (arglist & CAM_ARG_ERR_RECOVER)
1682 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1684 /* Disable freezing the device queue */
1685 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1687 if (((retval = cam_send_ccb(device, ccb)) < 0)
1688 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1689 if (arglist & CAM_ARG_VERBOSE) {
1690 cam_error_print(device, ccb, CAM_ESF_ALL,
1691 CAM_EPF_ALL, stderr);
1693 cam_freeccb(ccb);
1694 cam_close_device(device);
1696 if (retval < 0)
1697 err(1, "error sending mode select command");
1698 else
1699 errx(1, "error sending mode select command");
1703 cam_freeccb(ccb);
1706 void
1707 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
1708 int retry_count, int timeout)
1710 int c, mode_page = -1, page_control = 0;
1711 int binary = 0, list = 0;
1713 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1714 switch(c) {
1715 case 'b':
1716 binary = 1;
1717 break;
1718 case 'd':
1719 arglist |= CAM_ARG_DBD;
1720 break;
1721 case 'e':
1722 arglist |= CAM_ARG_MODE_EDIT;
1723 break;
1724 case 'l':
1725 list = 1;
1726 break;
1727 case 'm':
1728 mode_page = strtol(optarg, NULL, 0);
1729 if (mode_page < 0)
1730 errx(1, "invalid mode page %d", mode_page);
1731 break;
1732 case 'P':
1733 page_control = strtol(optarg, NULL, 0);
1734 if ((page_control < 0) || (page_control > 3))
1735 errx(1, "invalid page control field %d",
1736 page_control);
1737 arglist |= CAM_ARG_PAGE_CNTL;
1738 break;
1739 default:
1740 break;
1744 if (mode_page == -1 && list == 0)
1745 errx(1, "you must specify a mode page!");
1747 if (list) {
1748 mode_list(device, page_control, arglist & CAM_ARG_DBD,
1749 retry_count, timeout);
1750 } else {
1751 mode_edit(device, mode_page, page_control,
1752 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
1753 retry_count, timeout);
1757 static int
1758 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
1759 int retry_count, int timeout)
1761 union ccb *ccb;
1762 u_int32_t flags = CAM_DIR_NONE;
1763 u_int8_t *data_ptr = NULL;
1764 u_int8_t cdb[20];
1765 struct get_hook hook;
1766 int c, data_bytes = 0;
1767 int cdb_len = 0;
1768 char *datastr = NULL, *tstr;
1769 int error = 0;
1770 int fd_data = 0;
1771 int retval;
1773 ccb = cam_getccb(device);
1775 if (ccb == NULL) {
1776 warnx("scsicmd: error allocating ccb");
1777 return(1);
1780 bzero(&(&ccb->ccb_h)[1],
1781 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1783 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1784 switch(c) {
1785 case 'c':
1786 tstr = optarg;
1787 while (isspace(*tstr) && (*tstr != '\0'))
1788 tstr++;
1789 hook.argc = argc - optind;
1790 hook.argv = argv + optind;
1791 hook.got = 0;
1792 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
1793 iget, &hook);
1795 * Increment optind by the number of arguments the
1796 * encoding routine processed. After each call to
1797 * getopt(3), optind points to the argument that
1798 * getopt should process _next_. In this case,
1799 * that means it points to the first command string
1800 * argument, if there is one. Once we increment
1801 * this, it should point to either the next command
1802 * line argument, or it should be past the end of
1803 * the list.
1805 optind += hook.got;
1806 break;
1807 case 'i':
1808 if (arglist & CAM_ARG_CMD_OUT) {
1809 warnx("command must either be "
1810 "read or write, not both");
1811 error = 1;
1812 goto scsicmd_bailout;
1814 arglist |= CAM_ARG_CMD_IN;
1815 flags = CAM_DIR_IN;
1816 data_bytes = strtol(optarg, NULL, 0);
1817 if (data_bytes <= 0) {
1818 warnx("invalid number of input bytes %d",
1819 data_bytes);
1820 error = 1;
1821 goto scsicmd_bailout;
1823 hook.argc = argc - optind;
1824 hook.argv = argv + optind;
1825 hook.got = 0;
1826 optind++;
1827 datastr = cget(&hook, NULL);
1829 * If the user supplied "-" instead of a format, he
1830 * wants the data to be written to stdout.
1832 if ((datastr != NULL)
1833 && (datastr[0] == '-'))
1834 fd_data = 1;
1836 data_ptr = (u_int8_t *)malloc(data_bytes);
1837 if (data_ptr == NULL) {
1838 warnx("can't malloc memory for data_ptr");
1839 error = 1;
1840 goto scsicmd_bailout;
1842 break;
1843 case 'o':
1844 if (arglist & CAM_ARG_CMD_IN) {
1845 warnx("command must either be "
1846 "read or write, not both");
1847 error = 1;
1848 goto scsicmd_bailout;
1850 arglist |= CAM_ARG_CMD_OUT;
1851 flags = CAM_DIR_OUT;
1852 data_bytes = strtol(optarg, NULL, 0);
1853 if (data_bytes <= 0) {
1854 warnx("invalid number of output bytes %d",
1855 data_bytes);
1856 error = 1;
1857 goto scsicmd_bailout;
1859 hook.argc = argc - optind;
1860 hook.argv = argv + optind;
1861 hook.got = 0;
1862 datastr = cget(&hook, NULL);
1863 data_ptr = (u_int8_t *)malloc(data_bytes);
1864 if (data_ptr == NULL) {
1865 warnx("can't malloc memory for data_ptr");
1866 error = 1;
1867 goto scsicmd_bailout;
1870 * If the user supplied "-" instead of a format, he
1871 * wants the data to be read from stdin.
1873 if ((datastr != NULL)
1874 && (datastr[0] == '-'))
1875 fd_data = 1;
1876 else
1877 buff_encode_visit(data_ptr, data_bytes, datastr,
1878 iget, &hook);
1879 optind += hook.got;
1880 break;
1881 default:
1882 break;
1887 * If fd_data is set, and we're writing to the device, we need to
1888 * read the data the user wants written from stdin.
1890 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
1891 ssize_t amt_read;
1892 int amt_to_read = data_bytes;
1893 u_int8_t *buf_ptr = data_ptr;
1895 for (amt_read = 0; amt_to_read > 0;
1896 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
1897 if (amt_read == -1) {
1898 warn("error reading data from stdin");
1899 error = 1;
1900 goto scsicmd_bailout;
1902 amt_to_read -= amt_read;
1903 buf_ptr += amt_read;
1907 if (arglist & CAM_ARG_ERR_RECOVER)
1908 flags |= CAM_PASS_ERR_RECOVER;
1910 /* Disable freezing the device queue */
1911 flags |= CAM_DEV_QFRZDIS;
1914 * This is taken from the SCSI-3 draft spec.
1915 * (T10/1157D revision 0.3)
1916 * The top 3 bits of an opcode are the group code. The next 5 bits
1917 * are the command code.
1918 * Group 0: six byte commands
1919 * Group 1: ten byte commands
1920 * Group 2: ten byte commands
1921 * Group 3: reserved
1922 * Group 4: sixteen byte commands
1923 * Group 5: twelve byte commands
1924 * Group 6: vendor specific
1925 * Group 7: vendor specific
1927 switch((cdb[0] >> 5) & 0x7) {
1928 case 0:
1929 cdb_len = 6;
1930 break;
1931 case 1:
1932 case 2:
1933 cdb_len = 10;
1934 break;
1935 case 3:
1936 case 6:
1937 case 7:
1938 /* computed by buff_encode_visit */
1939 break;
1940 case 4:
1941 cdb_len = 16;
1942 break;
1943 case 5:
1944 cdb_len = 12;
1945 break;
1949 * We should probably use csio_build_visit or something like that
1950 * here, but it's easier to encode arguments as you go. The
1951 * alternative would be skipping the CDB argument and then encoding
1952 * it here, since we've got the data buffer argument by now.
1954 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
1956 cam_fill_csio(&ccb->csio,
1957 /*retries*/ retry_count,
1958 /*cbfcnp*/ NULL,
1959 /*flags*/ flags,
1960 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1961 /*data_ptr*/ data_ptr,
1962 /*dxfer_len*/ data_bytes,
1963 /*sense_len*/ SSD_FULL_SIZE,
1964 /*cdb_len*/ cdb_len,
1965 /*timeout*/ timeout ? timeout : 5000);
1967 if (((retval = cam_send_ccb(device, ccb)) < 0)
1968 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1969 if (retval < 0)
1970 warn("error sending command");
1971 else
1972 warnx("error sending command");
1974 if (arglist & CAM_ARG_VERBOSE) {
1975 cam_error_print(device, ccb, CAM_ESF_ALL,
1976 CAM_EPF_ALL, stderr);
1979 error = 1;
1980 goto scsicmd_bailout;
1984 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1985 && (arglist & CAM_ARG_CMD_IN)
1986 && (data_bytes > 0)) {
1987 if (fd_data == 0) {
1988 buff_decode_visit(data_ptr, data_bytes, datastr,
1989 arg_put, NULL);
1990 fprintf(stdout, "\n");
1991 } else {
1992 ssize_t amt_written;
1993 int amt_to_write = data_bytes;
1994 u_int8_t *buf_ptr = data_ptr;
1996 for (amt_written = 0; (amt_to_write > 0) &&
1997 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
1998 amt_to_write -= amt_written;
1999 buf_ptr += amt_written;
2001 if (amt_written == -1) {
2002 warn("error writing data to stdout");
2003 error = 1;
2004 goto scsicmd_bailout;
2005 } else if ((amt_written == 0)
2006 && (amt_to_write > 0)) {
2007 warnx("only wrote %u bytes out of %u",
2008 data_bytes - amt_to_write, data_bytes);
2013 scsicmd_bailout:
2015 if ((data_bytes > 0) && (data_ptr != NULL))
2016 free(data_ptr);
2018 cam_freeccb(ccb);
2020 return(error);
2023 static int
2024 camdebug(int argc, char **argv, char *combinedopt)
2026 int c, fd;
2027 int mybus = -1, mytarget = -1, mylun = -1;
2028 char *tstr, *tmpstr = NULL;
2029 union ccb ccb;
2030 int error = 0;
2032 bzero(&ccb, sizeof(union ccb));
2034 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2035 switch(c) {
2036 case 'I':
2037 arglist |= CAM_ARG_DEBUG_INFO;
2038 ccb.cdbg.flags |= CAM_DEBUG_INFO;
2039 break;
2040 case 'P':
2041 arglist |= CAM_ARG_DEBUG_PERIPH;
2042 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2043 break;
2044 case 'S':
2045 arglist |= CAM_ARG_DEBUG_SUBTRACE;
2046 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2047 break;
2048 case 'T':
2049 arglist |= CAM_ARG_DEBUG_TRACE;
2050 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2051 break;
2052 case 'X':
2053 arglist |= CAM_ARG_DEBUG_XPT;
2054 ccb.cdbg.flags |= CAM_DEBUG_XPT;
2055 break;
2056 case 'c':
2057 arglist |= CAM_ARG_DEBUG_CDB;
2058 ccb.cdbg.flags |= CAM_DEBUG_CDB;
2059 break;
2060 default:
2061 break;
2065 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2066 warnx("error opening transport layer device %s", XPT_DEVICE);
2067 warn("%s", XPT_DEVICE);
2068 return(1);
2070 argc -= optind;
2071 argv += optind;
2073 if (argc <= 0) {
2074 warnx("you must specify \"off\", \"all\" or a bus,");
2075 warnx("bus:target, or bus:target:lun");
2076 close(fd);
2077 return(1);
2080 tstr = *argv;
2082 while (isspace(*tstr) && (*tstr != '\0'))
2083 tstr++;
2085 if (strncmp(tstr, "off", 3) == 0) {
2086 ccb.cdbg.flags = CAM_DEBUG_NONE;
2087 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2088 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2089 CAM_ARG_DEBUG_XPT);
2090 } else if (strncmp(tstr, "all", 3) != 0) {
2091 tmpstr = (char *)strtok(tstr, ":");
2092 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2093 mybus = strtol(tmpstr, NULL, 0);
2094 arglist |= CAM_ARG_BUS;
2095 tmpstr = (char *)strtok(NULL, ":");
2096 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2097 mytarget = strtol(tmpstr, NULL, 0);
2098 arglist |= CAM_ARG_TARGET;
2099 tmpstr = (char *)strtok(NULL, ":");
2100 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2101 mylun = strtol(tmpstr, NULL, 0);
2102 arglist |= CAM_ARG_LUN;
2105 } else {
2106 error = 1;
2107 warnx("you must specify \"all\", \"off\", or a bus,");
2108 warnx("bus:target, or bus:target:lun to debug");
2112 if (error == 0) {
2114 ccb.ccb_h.func_code = XPT_DEBUG;
2115 ccb.ccb_h.path_id = mybus;
2116 ccb.ccb_h.target_id = mytarget;
2117 ccb.ccb_h.target_lun = mylun;
2119 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2120 warn("CAMIOCOMMAND ioctl failed");
2121 error = 1;
2124 if (error == 0) {
2125 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2126 CAM_FUNC_NOTAVAIL) {
2127 warnx("CAM debugging not available");
2128 warnx("you need to put options CAMDEBUG in"
2129 " your kernel config file!");
2130 error = 1;
2131 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2132 CAM_REQ_CMP) {
2133 warnx("XPT_DEBUG CCB failed with status %#x",
2134 ccb.ccb_h.status);
2135 error = 1;
2136 } else {
2137 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2138 fprintf(stderr,
2139 "Debugging turned off\n");
2140 } else {
2141 fprintf(stderr,
2142 "Debugging enabled for "
2143 "%d:%d:%d\n",
2144 mybus, mytarget, mylun);
2148 close(fd);
2151 return(error);
2154 static int
2155 tagcontrol(struct cam_device *device, int argc, char **argv,
2156 char *combinedopt)
2158 int c;
2159 union ccb *ccb;
2160 int numtags = -1;
2161 int retval = 0;
2162 int quiet = 0;
2163 char pathstr[1024];
2165 ccb = cam_getccb(device);
2167 if (ccb == NULL) {
2168 warnx("tagcontrol: error allocating ccb");
2169 return(1);
2172 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2173 switch(c) {
2174 case 'N':
2175 numtags = strtol(optarg, NULL, 0);
2176 if (numtags < 0) {
2177 warnx("tag count %d is < 0", numtags);
2178 retval = 1;
2179 goto tagcontrol_bailout;
2181 break;
2182 case 'q':
2183 quiet++;
2184 break;
2185 default:
2186 break;
2190 cam_path_string(device, pathstr, sizeof(pathstr));
2192 if (numtags >= 0) {
2193 bzero(&(&ccb->ccb_h)[1],
2194 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2195 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2196 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2197 ccb->crs.openings = numtags;
2200 if (cam_send_ccb(device, ccb) < 0) {
2201 perror("error sending XPT_REL_SIMQ CCB");
2202 retval = 1;
2203 goto tagcontrol_bailout;
2206 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2207 warnx("XPT_REL_SIMQ CCB failed");
2208 cam_error_print(device, ccb, CAM_ESF_ALL,
2209 CAM_EPF_ALL, stderr);
2210 retval = 1;
2211 goto tagcontrol_bailout;
2215 if (quiet == 0)
2216 fprintf(stdout, "%stagged openings now %d\n",
2217 pathstr, ccb->crs.openings);
2220 bzero(&(&ccb->ccb_h)[1],
2221 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2223 ccb->ccb_h.func_code = XPT_GDEV_STATS;
2225 if (cam_send_ccb(device, ccb) < 0) {
2226 perror("error sending XPT_GDEV_STATS CCB");
2227 retval = 1;
2228 goto tagcontrol_bailout;
2231 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2232 warnx("XPT_GDEV_STATS CCB failed");
2233 cam_error_print(device, ccb, CAM_ESF_ALL,
2234 CAM_EPF_ALL, stderr);
2235 retval = 1;
2236 goto tagcontrol_bailout;
2239 if (arglist & CAM_ARG_VERBOSE) {
2240 fprintf(stdout, "%s", pathstr);
2241 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
2242 fprintf(stdout, "%s", pathstr);
2243 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
2244 fprintf(stdout, "%s", pathstr);
2245 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2246 fprintf(stdout, "%s", pathstr);
2247 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued);
2248 fprintf(stdout, "%s", pathstr);
2249 fprintf(stdout, "held %d\n", ccb->cgds.held);
2250 fprintf(stdout, "%s", pathstr);
2251 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
2252 fprintf(stdout, "%s", pathstr);
2253 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
2254 } else {
2255 if (quiet == 0) {
2256 fprintf(stdout, "%s", pathstr);
2257 fprintf(stdout, "device openings: ");
2259 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2260 ccb->cgds.dev_active);
2263 tagcontrol_bailout:
2265 cam_freeccb(ccb);
2266 return(retval);
2269 static void
2270 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2272 char pathstr[1024];
2274 cam_path_string(device, pathstr, sizeof(pathstr));
2276 if (cts->transport == XPORT_SPI) {
2277 struct ccb_trans_settings_spi *spi =
2278 &cts->xport_specific.spi;
2280 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2282 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2283 spi->sync_period);
2285 if (spi->sync_offset != 0) {
2286 u_int freq;
2288 freq = scsi_calc_syncsrate(spi->sync_period);
2289 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2290 pathstr, freq / 1000, freq % 1000);
2294 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2295 fprintf(stdout, "%soffset: %d\n", pathstr,
2296 spi->sync_offset);
2299 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2300 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2301 (0x01 << spi->bus_width) * 8);
2304 if (spi->valid & CTS_SPI_VALID_DISC) {
2305 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2306 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2307 "enabled" : "disabled");
2311 if (cts->protocol == PROTO_SCSI) {
2312 struct ccb_trans_settings_scsi *scsi=
2313 &cts->proto_specific.scsi;
2315 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2316 fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2317 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2318 "enabled" : "disabled");
2325 * Get a path inquiry CCB for the specified device.
2327 static int
2328 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2330 union ccb *ccb;
2331 int retval = 0;
2333 ccb = cam_getccb(device);
2335 if (ccb == NULL) {
2336 warnx("get_cpi: couldn't allocate CCB");
2337 return(1);
2340 bzero(&(&ccb->ccb_h)[1],
2341 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2343 ccb->ccb_h.func_code = XPT_PATH_INQ;
2345 if (cam_send_ccb(device, ccb) < 0) {
2346 warn("get_cpi: error sending Path Inquiry CCB");
2348 if (arglist & CAM_ARG_VERBOSE)
2349 cam_error_print(device, ccb, CAM_ESF_ALL,
2350 CAM_EPF_ALL, stderr);
2352 retval = 1;
2354 goto get_cpi_bailout;
2357 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2359 if (arglist & CAM_ARG_VERBOSE)
2360 cam_error_print(device, ccb, CAM_ESF_ALL,
2361 CAM_EPF_ALL, stderr);
2363 retval = 1;
2365 goto get_cpi_bailout;
2368 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2370 get_cpi_bailout:
2372 cam_freeccb(ccb);
2374 return(retval);
2377 static void
2378 cpi_print(struct ccb_pathinq *cpi)
2380 char adapter_str[1024];
2381 int i;
2383 snprintf(adapter_str, sizeof(adapter_str),
2384 "%s%d:", cpi->dev_name, cpi->unit_number);
2386 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2387 cpi->version_num);
2389 for (i = 1; i < 0xff; i = i << 1) {
2390 const char *str;
2392 if ((i & cpi->hba_inquiry) == 0)
2393 continue;
2395 fprintf(stdout, "%s supports ", adapter_str);
2397 switch(i) {
2398 case PI_MDP_ABLE:
2399 str = "MDP message";
2400 break;
2401 case PI_WIDE_32:
2402 str = "32 bit wide SCSI";
2403 break;
2404 case PI_WIDE_16:
2405 str = "16 bit wide SCSI";
2406 break;
2407 case PI_SDTR_ABLE:
2408 str = "SDTR message";
2409 break;
2410 case PI_LINKED_CDB:
2411 str = "linked CDBs";
2412 break;
2413 case PI_TAG_ABLE:
2414 str = "tag queue messages";
2415 break;
2416 case PI_SOFT_RST:
2417 str = "soft reset alternative";
2418 break;
2419 default:
2420 str = "unknown PI bit set";
2421 break;
2423 fprintf(stdout, "%s\n", str);
2426 for (i = 1; i < 0xff; i = i << 1) {
2427 const char *str;
2429 if ((i & cpi->hba_misc) == 0)
2430 continue;
2432 fprintf(stdout, "%s ", adapter_str);
2434 switch(i) {
2435 case PIM_SCANHILO:
2436 str = "bus scans from high ID to low ID";
2437 break;
2438 case PIM_NOREMOVE:
2439 str = "removable devices not included in scan";
2440 break;
2441 case PIM_NOINITIATOR:
2442 str = "initiator role not supported";
2443 break;
2444 case PIM_NOBUSRESET:
2445 str = "user has disabled initial BUS RESET or"
2446 " controller is in target/mixed mode";
2447 break;
2448 default:
2449 str = "unknown PIM bit set";
2450 break;
2452 fprintf(stdout, "%s\n", str);
2455 for (i = 1; i < 0xff; i = i << 1) {
2456 const char *str;
2458 if ((i & cpi->target_sprt) == 0)
2459 continue;
2461 fprintf(stdout, "%s supports ", adapter_str);
2462 switch(i) {
2463 case PIT_PROCESSOR:
2464 str = "target mode processor mode";
2465 break;
2466 case PIT_PHASE:
2467 str = "target mode phase cog. mode";
2468 break;
2469 case PIT_DISCONNECT:
2470 str = "disconnects in target mode";
2471 break;
2472 case PIT_TERM_IO:
2473 str = "terminate I/O message in target mode";
2474 break;
2475 case PIT_GRP_6:
2476 str = "group 6 commands in target mode";
2477 break;
2478 case PIT_GRP_7:
2479 str = "group 7 commands in target mode";
2480 break;
2481 default:
2482 str = "unknown PIT bit set";
2483 break;
2486 fprintf(stdout, "%s\n", str);
2488 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
2489 cpi->hba_eng_cnt);
2490 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
2491 cpi->max_target);
2492 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
2493 cpi->max_lun);
2494 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
2495 adapter_str, cpi->hpath_id);
2496 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
2497 cpi->initiator_id);
2498 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
2499 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
2500 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
2501 fprintf(stdout, "%s base transfer speed: ", adapter_str);
2502 if (cpi->base_transfer_speed > 1000)
2503 fprintf(stdout, "%d.%03dMB/sec\n",
2504 cpi->base_transfer_speed / 1000,
2505 cpi->base_transfer_speed % 1000);
2506 else
2507 fprintf(stdout, "%dKB/sec\n",
2508 (cpi->base_transfer_speed % 1000) * 1000);
2511 static int
2512 get_print_cts(struct cam_device *device, int user_settings, int quiet,
2513 struct ccb_trans_settings *cts)
2515 int retval;
2516 union ccb *ccb;
2518 retval = 0;
2519 ccb = cam_getccb(device);
2521 if (ccb == NULL) {
2522 warnx("get_print_cts: error allocating ccb");
2523 return(1);
2526 bzero(&(&ccb->ccb_h)[1],
2527 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2529 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
2531 if (user_settings == 0)
2532 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
2533 else
2534 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
2536 if (cam_send_ccb(device, ccb) < 0) {
2537 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
2538 if (arglist & CAM_ARG_VERBOSE)
2539 cam_error_print(device, ccb, CAM_ESF_ALL,
2540 CAM_EPF_ALL, stderr);
2541 retval = 1;
2542 goto get_print_cts_bailout;
2545 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2546 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
2547 if (arglist & CAM_ARG_VERBOSE)
2548 cam_error_print(device, ccb, CAM_ESF_ALL,
2549 CAM_EPF_ALL, stderr);
2550 retval = 1;
2551 goto get_print_cts_bailout;
2554 if (quiet == 0)
2555 cts_print(device, &ccb->cts);
2557 if (cts != NULL)
2558 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
2560 get_print_cts_bailout:
2562 cam_freeccb(ccb);
2564 return(retval);
2567 static int
2568 ratecontrol(struct cam_device *device, int retry_count, int timeout,
2569 int argc, char **argv, char *combinedopt)
2571 int c;
2572 union ccb *ccb;
2573 int user_settings = 0;
2574 int retval = 0;
2575 int disc_enable = -1, tag_enable = -1;
2576 int offset = -1;
2577 double syncrate = -1;
2578 int bus_width = -1;
2579 int quiet = 0;
2580 int change_settings = 0, send_tur = 0;
2581 struct ccb_pathinq cpi;
2583 ccb = cam_getccb(device);
2585 if (ccb == NULL) {
2586 warnx("ratecontrol: error allocating ccb");
2587 return(1);
2590 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2591 switch(c){
2592 case 'a':
2593 send_tur = 1;
2594 break;
2595 case 'c':
2596 user_settings = 0;
2597 break;
2598 case 'D':
2599 if (strncasecmp(optarg, "enable", 6) == 0)
2600 disc_enable = 1;
2601 else if (strncasecmp(optarg, "disable", 7) == 0)
2602 disc_enable = 0;
2603 else {
2604 warnx("-D argument \"%s\" is unknown", optarg);
2605 retval = 1;
2606 goto ratecontrol_bailout;
2608 change_settings = 1;
2609 break;
2610 case 'O':
2611 offset = strtol(optarg, NULL, 0);
2612 if (offset < 0) {
2613 warnx("offset value %d is < 0", offset);
2614 retval = 1;
2615 goto ratecontrol_bailout;
2617 change_settings = 1;
2618 break;
2619 case 'q':
2620 quiet++;
2621 break;
2622 case 'R':
2623 syncrate = atof(optarg);
2625 if (syncrate < 0) {
2626 warnx("sync rate %f is < 0", syncrate);
2627 retval = 1;
2628 goto ratecontrol_bailout;
2630 change_settings = 1;
2631 break;
2632 case 'T':
2633 if (strncasecmp(optarg, "enable", 6) == 0)
2634 tag_enable = 1;
2635 else if (strncasecmp(optarg, "disable", 7) == 0)
2636 tag_enable = 0;
2637 else {
2638 warnx("-T argument \"%s\" is unknown", optarg);
2639 retval = 1;
2640 goto ratecontrol_bailout;
2642 change_settings = 1;
2643 break;
2644 case 'U':
2645 user_settings = 1;
2646 break;
2647 case 'W':
2648 bus_width = strtol(optarg, NULL, 0);
2649 if (bus_width < 0) {
2650 warnx("bus width %d is < 0", bus_width);
2651 retval = 1;
2652 goto ratecontrol_bailout;
2654 change_settings = 1;
2655 break;
2656 default:
2657 break;
2661 bzero(&(&ccb->ccb_h)[1],
2662 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2665 * Grab path inquiry information, so we can determine whether
2666 * or not the initiator is capable of the things that the user
2667 * requests.
2669 ccb->ccb_h.func_code = XPT_PATH_INQ;
2671 if (cam_send_ccb(device, ccb) < 0) {
2672 perror("error sending XPT_PATH_INQ CCB");
2673 if (arglist & CAM_ARG_VERBOSE) {
2674 cam_error_print(device, ccb, CAM_ESF_ALL,
2675 CAM_EPF_ALL, stderr);
2677 retval = 1;
2678 goto ratecontrol_bailout;
2681 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2682 warnx("XPT_PATH_INQ CCB failed");
2683 if (arglist & CAM_ARG_VERBOSE) {
2684 cam_error_print(device, ccb, CAM_ESF_ALL,
2685 CAM_EPF_ALL, stderr);
2687 retval = 1;
2688 goto ratecontrol_bailout;
2691 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
2693 bzero(&(&ccb->ccb_h)[1],
2694 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2696 if (quiet == 0)
2697 fprintf(stdout, "Current Parameters:\n");
2699 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
2701 if (retval != 0)
2702 goto ratecontrol_bailout;
2704 if (arglist & CAM_ARG_VERBOSE)
2705 cpi_print(&cpi);
2707 if (change_settings) {
2708 int didsettings = 0;
2709 struct ccb_trans_settings_spi *spi = NULL;
2710 struct ccb_trans_settings_scsi *scsi = NULL;
2712 if (ccb->cts.transport == XPORT_SPI) {
2713 spi = &ccb->cts.xport_specific.spi;
2714 spi->valid = 0;
2716 if (ccb->cts.protocol == PROTO_SCSI) {
2717 scsi = &ccb->cts.proto_specific.scsi;
2718 scsi->valid = 0;
2720 if (spi && disc_enable != -1) {
2721 spi->valid |= CTS_SPI_VALID_DISC;
2722 if (disc_enable == 0)
2723 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
2724 else
2725 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
2728 if (scsi && tag_enable != -1) {
2729 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
2730 warnx("HBA does not support tagged queueing, "
2731 "so you cannot modify tag settings");
2732 retval = 1;
2733 goto ratecontrol_bailout;
2736 scsi->valid |= CTS_SCSI_VALID_TQ;
2738 if (tag_enable == 0)
2739 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
2740 else
2741 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
2742 didsettings++;
2745 if (spi && offset != -1) {
2746 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2747 warnx("HBA at %s%d is not cable of changing "
2748 "offset", cpi.dev_name,
2749 cpi.unit_number);
2750 retval = 1;
2751 goto ratecontrol_bailout;
2753 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
2754 spi->sync_offset = offset;
2755 didsettings++;
2758 if (spi && syncrate != -1) {
2759 int prelim_sync_period;
2760 u_int freq;
2762 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2763 warnx("HBA at %s%d is not cable of changing "
2764 "transfer rates", cpi.dev_name,
2765 cpi.unit_number);
2766 retval = 1;
2767 goto ratecontrol_bailout;
2770 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
2773 * The sync rate the user gives us is in MHz.
2774 * We need to translate it into KHz for this
2775 * calculation.
2777 syncrate *= 1000;
2780 * Next, we calculate a "preliminary" sync period
2781 * in tenths of a nanosecond.
2783 if (syncrate == 0)
2784 prelim_sync_period = 0;
2785 else
2786 prelim_sync_period = 10000000 / syncrate;
2788 spi->sync_period =
2789 scsi_calc_syncparam(prelim_sync_period);
2791 freq = scsi_calc_syncsrate(spi->sync_period);
2792 didsettings++;
2796 * The bus_width argument goes like this:
2797 * 0 == 8 bit
2798 * 1 == 16 bit
2799 * 2 == 32 bit
2800 * Therefore, if you shift the number of bits given on the
2801 * command line right by 4, you should get the correct
2802 * number.
2804 if (spi && bus_width != -1) {
2807 * We might as well validate things here with a
2808 * decipherable error message, rather than what
2809 * will probably be an indecipherable error message
2810 * by the time it gets back to us.
2812 if ((bus_width == 16)
2813 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
2814 warnx("HBA does not support 16 bit bus width");
2815 retval = 1;
2816 goto ratecontrol_bailout;
2817 } else if ((bus_width == 32)
2818 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
2819 warnx("HBA does not support 32 bit bus width");
2820 retval = 1;
2821 goto ratecontrol_bailout;
2822 } else if ((bus_width != 8)
2823 && (bus_width != 16)
2824 && (bus_width != 32)) {
2825 warnx("Invalid bus width %d", bus_width);
2826 retval = 1;
2827 goto ratecontrol_bailout;
2830 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
2831 spi->bus_width = bus_width >> 4;
2832 didsettings++;
2835 if (didsettings == 0) {
2836 goto ratecontrol_bailout;
2838 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
2840 if (cam_send_ccb(device, ccb) < 0) {
2841 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
2842 if (arglist & CAM_ARG_VERBOSE) {
2843 cam_error_print(device, ccb, CAM_ESF_ALL,
2844 CAM_EPF_ALL, stderr);
2846 retval = 1;
2847 goto ratecontrol_bailout;
2850 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2851 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
2852 if (arglist & CAM_ARG_VERBOSE) {
2853 cam_error_print(device, ccb, CAM_ESF_ALL,
2854 CAM_EPF_ALL, stderr);
2856 retval = 1;
2857 goto ratecontrol_bailout;
2861 if (send_tur) {
2862 retval = testunitready(device, retry_count, timeout,
2863 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
2866 * If the TUR didn't succeed, just bail.
2868 if (retval != 0) {
2869 if (quiet == 0)
2870 fprintf(stderr, "Test Unit Ready failed\n");
2871 goto ratecontrol_bailout;
2875 * If the user wants things quiet, there's no sense in
2876 * getting the transfer settings, if we're not going
2877 * to print them.
2879 if (quiet != 0)
2880 goto ratecontrol_bailout;
2882 fprintf(stdout, "New Parameters:\n");
2883 retval = get_print_cts(device, user_settings, 0, NULL);
2886 ratecontrol_bailout:
2888 cam_freeccb(ccb);
2889 return(retval);
2892 static int
2893 scsiformat(struct cam_device *device, int argc, char **argv,
2894 char *combinedopt, int retry_count, int timeout)
2896 union ccb *ccb;
2897 int c;
2898 int ycount = 0, quiet = 0;
2899 int error = 0, response = 0, retval = 0;
2900 int use_timeout = 10800 * 1000;
2901 int immediate = 1;
2902 struct format_defect_list_header fh;
2903 u_int8_t *data_ptr = NULL;
2904 u_int32_t dxfer_len = 0;
2905 u_int8_t byte2 = 0;
2906 int num_warnings = 0;
2907 int reportonly = 0;
2909 ccb = cam_getccb(device);
2911 if (ccb == NULL) {
2912 warnx("scsiformat: error allocating ccb");
2913 return(1);
2916 bzero(&(&ccb->ccb_h)[1],
2917 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2919 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2920 switch(c) {
2921 case 'q':
2922 quiet++;
2923 break;
2924 case 'r':
2925 reportonly = 1;
2926 break;
2927 case 'w':
2928 immediate = 0;
2929 break;
2930 case 'y':
2931 ycount++;
2932 break;
2936 if (reportonly)
2937 goto doreport;
2939 if (quiet == 0) {
2940 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
2941 "following device:\n");
2943 error = scsidoinquiry(device, argc, argv, combinedopt,
2944 retry_count, timeout);
2946 if (error != 0) {
2947 warnx("scsiformat: error sending inquiry");
2948 goto scsiformat_bailout;
2952 if (ycount == 0) {
2954 do {
2955 char str[1024];
2957 fprintf(stdout, "Are you SURE you want to do "
2958 "this? (yes/no) ");
2960 if (fgets(str, sizeof(str), stdin) != NULL) {
2962 if (strncasecmp(str, "yes", 3) == 0)
2963 response = 1;
2964 else if (strncasecmp(str, "no", 2) == 0)
2965 response = -1;
2966 else {
2967 fprintf(stdout, "Please answer"
2968 " \"yes\" or \"no\"\n");
2971 } while (response == 0);
2973 if (response == -1) {
2974 error = 1;
2975 goto scsiformat_bailout;
2979 if (timeout != 0)
2980 use_timeout = timeout;
2982 if (quiet == 0) {
2983 fprintf(stdout, "Current format timeout is %d seconds\n",
2984 use_timeout / 1000);
2988 * If the user hasn't disabled questions and didn't specify a
2989 * timeout on the command line, ask them if they want the current
2990 * timeout.
2992 if ((ycount == 0)
2993 && (timeout == 0)) {
2994 char str[1024];
2995 int new_timeout = 0;
2997 fprintf(stdout, "Enter new timeout in seconds or press\n"
2998 "return to keep the current timeout [%d] ",
2999 use_timeout / 1000);
3001 if (fgets(str, sizeof(str), stdin) != NULL) {
3002 if (str[0] != '\0')
3003 new_timeout = atoi(str);
3006 if (new_timeout != 0) {
3007 use_timeout = new_timeout * 1000;
3008 fprintf(stdout, "Using new timeout value %d\n",
3009 use_timeout / 1000);
3014 * Keep this outside the if block below to silence any unused
3015 * variable warnings.
3017 bzero(&fh, sizeof(fh));
3020 * If we're in immediate mode, we've got to include the format
3021 * header
3023 if (immediate != 0) {
3024 fh.byte2 = FU_DLH_IMMED;
3025 data_ptr = (u_int8_t *)&fh;
3026 dxfer_len = sizeof(fh);
3027 byte2 = FU_FMT_DATA;
3028 } else if (quiet == 0) {
3029 fprintf(stdout, "Formatting...");
3030 fflush(stdout);
3033 scsi_format_unit(&ccb->csio,
3034 /* retries */ retry_count,
3035 /* cbfcnp */ NULL,
3036 /* tag_action */ MSG_SIMPLE_Q_TAG,
3037 /* byte2 */ byte2,
3038 /* ileave */ 0,
3039 /* data_ptr */ data_ptr,
3040 /* dxfer_len */ dxfer_len,
3041 /* sense_len */ SSD_FULL_SIZE,
3042 /* timeout */ use_timeout);
3044 /* Disable freezing the device queue */
3045 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3047 if (arglist & CAM_ARG_ERR_RECOVER)
3048 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3050 if (((retval = cam_send_ccb(device, ccb)) < 0)
3051 || ((immediate == 0)
3052 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3053 const char errstr[] = "error sending format command";
3055 if (retval < 0)
3056 warn(errstr);
3057 else
3058 warnx(errstr);
3060 if (arglist & CAM_ARG_VERBOSE) {
3061 cam_error_print(device, ccb, CAM_ESF_ALL,
3062 CAM_EPF_ALL, stderr);
3064 error = 1;
3065 goto scsiformat_bailout;
3069 * If we ran in non-immediate mode, we already checked for errors
3070 * above and printed out any necessary information. If we're in
3071 * immediate mode, we need to loop through and get status
3072 * information periodically.
3074 if (immediate == 0) {
3075 if (quiet == 0) {
3076 fprintf(stdout, "Format Complete\n");
3078 goto scsiformat_bailout;
3081 doreport:
3082 do {
3083 cam_status status;
3085 bzero(&(&ccb->ccb_h)[1],
3086 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3089 * There's really no need to do error recovery or
3090 * retries here, since we're just going to sit in a
3091 * loop and wait for the device to finish formatting.
3093 scsi_test_unit_ready(&ccb->csio,
3094 /* retries */ 0,
3095 /* cbfcnp */ NULL,
3096 /* tag_action */ MSG_SIMPLE_Q_TAG,
3097 /* sense_len */ SSD_FULL_SIZE,
3098 /* timeout */ 5000);
3100 /* Disable freezing the device queue */
3101 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3103 retval = cam_send_ccb(device, ccb);
3106 * If we get an error from the ioctl, bail out. SCSI
3107 * errors are expected.
3109 if (retval < 0) {
3110 warn("error sending CAMIOCOMMAND ioctl");
3111 if (arglist & CAM_ARG_VERBOSE) {
3112 cam_error_print(device, ccb, CAM_ESF_ALL,
3113 CAM_EPF_ALL, stderr);
3115 error = 1;
3116 goto scsiformat_bailout;
3119 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3121 if ((status != CAM_REQ_CMP)
3122 && (status == CAM_SCSI_STATUS_ERROR)
3123 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3124 struct scsi_sense_data *sense;
3125 int error_code, sense_key, asc, ascq;
3127 sense = &ccb->csio.sense_data;
3128 scsi_extract_sense(sense, &error_code, &sense_key,
3129 &asc, &ascq);
3132 * According to the SCSI-2 and SCSI-3 specs, a
3133 * drive that is in the middle of a format should
3134 * return NOT READY with an ASC of "logical unit
3135 * not ready, format in progress". The sense key
3136 * specific bytes will then be a progress indicator.
3138 if ((sense_key == SSD_KEY_NOT_READY)
3139 && (asc == 0x04) && (ascq == 0x04)) {
3140 if ((sense->extra_len >= 10)
3141 && ((sense->sense_key_spec[0] &
3142 SSD_SCS_VALID) != 0)
3143 && (quiet == 0)) {
3144 int val;
3145 u_int64_t percentage;
3147 val = scsi_2btoul(
3148 &sense->sense_key_spec[1]);
3149 percentage = 10000 * val;
3151 fprintf(stdout,
3152 "\rFormatting: %qd.%02qd %% "
3153 "(%d/%d) done",
3154 percentage / (0x10000 * 100),
3155 (percentage / 0x10000) % 100,
3156 val, 0x10000);
3157 fflush(stdout);
3158 } else if ((quiet == 0)
3159 && (++num_warnings <= 1)) {
3160 warnx("Unexpected SCSI Sense Key "
3161 "Specific value returned "
3162 "during format:");
3163 scsi_sense_print(device, &ccb->csio,
3164 stderr);
3165 warnx("Unable to print status "
3166 "information, but format will "
3167 "proceed.");
3168 warnx("will exit when format is "
3169 "complete");
3171 sleep(1);
3172 } else {
3173 warnx("Unexpected SCSI error during format");
3174 cam_error_print(device, ccb, CAM_ESF_ALL,
3175 CAM_EPF_ALL, stderr);
3176 error = 1;
3177 goto scsiformat_bailout;
3180 } else if (status != CAM_REQ_CMP) {
3181 warnx("Unexpected CAM status %#x", status);
3182 if (arglist & CAM_ARG_VERBOSE)
3183 cam_error_print(device, ccb, CAM_ESF_ALL,
3184 CAM_EPF_ALL, stderr);
3185 error = 1;
3186 goto scsiformat_bailout;
3189 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3191 if (quiet == 0)
3192 fprintf(stdout, "\nFormat Complete\n");
3194 scsiformat_bailout:
3196 cam_freeccb(ccb);
3198 return(error);
3201 static int
3202 scsireportluns(struct cam_device *device, int argc, char **argv,
3203 char *combinedopt, int retry_count, int timeout)
3205 union ccb *ccb;
3206 int c, countonly, lunsonly;
3207 struct scsi_report_luns_data *lundata;
3208 int alloc_len;
3209 uint8_t report_type;
3210 uint32_t list_len, i, j;
3211 int retval;
3213 retval = 0;
3214 lundata = NULL;
3215 report_type = RPL_REPORT_DEFAULT;
3216 ccb = cam_getccb(device);
3218 if (ccb == NULL) {
3219 warnx("%s: error allocating ccb", __func__);
3220 return (1);
3223 bzero(&(&ccb->ccb_h)[1],
3224 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3226 countonly = 0;
3227 lunsonly = 0;
3229 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3230 switch (c) {
3231 case 'c':
3232 countonly++;
3233 break;
3234 case 'l':
3235 lunsonly++;
3236 break;
3237 case 'r':
3238 if (strcasecmp(optarg, "default") == 0)
3239 report_type = RPL_REPORT_DEFAULT;
3240 else if (strcasecmp(optarg, "wellknown") == 0)
3241 report_type = RPL_REPORT_WELLKNOWN;
3242 else if (strcasecmp(optarg, "all") == 0)
3243 report_type = RPL_REPORT_ALL;
3244 else {
3245 warnx("%s: invalid report type \"%s\"",
3246 __func__, optarg);
3247 retval = 1;
3248 goto bailout;
3250 break;
3251 default:
3252 break;
3256 if ((countonly != 0)
3257 && (lunsonly != 0)) {
3258 warnx("%s: you can only specify one of -c or -l", __func__);
3259 retval = 1;
3260 goto bailout;
3263 * According to SPC-4, the allocation length must be at least 16
3264 * bytes -- enough for the header and one LUN.
3266 alloc_len = sizeof(*lundata) + 8;
3268 retry:
3270 lundata = malloc(alloc_len);
3272 if (lundata == NULL) {
3273 warn("%s: error mallocing %d bytes", __func__, alloc_len);
3274 retval = 1;
3275 goto bailout;
3278 scsi_report_luns(&ccb->csio,
3279 /*retries*/ retry_count,
3280 /*cbfcnp*/ NULL,
3281 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3282 /*select_report*/ report_type,
3283 /*rpl_buf*/ lundata,
3284 /*alloc_len*/ alloc_len,
3285 /*sense_len*/ SSD_FULL_SIZE,
3286 /*timeout*/ timeout ? timeout : 5000);
3288 /* Disable freezing the device queue */
3289 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3291 if (arglist & CAM_ARG_ERR_RECOVER)
3292 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3294 if (cam_send_ccb(device, ccb) < 0) {
3295 warn("error sending REPORT LUNS command");
3297 if (arglist & CAM_ARG_VERBOSE)
3298 cam_error_print(device, ccb, CAM_ESF_ALL,
3299 CAM_EPF_ALL, stderr);
3301 retval = 1;
3302 goto bailout;
3305 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3306 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3307 retval = 1;
3308 goto bailout;
3312 list_len = scsi_4btoul(lundata->length);
3315 * If we need to list the LUNs, and our allocation
3316 * length was too short, reallocate and retry.
3318 if ((countonly == 0)
3319 && (list_len > (alloc_len - sizeof(*lundata)))) {
3320 alloc_len = list_len + sizeof(*lundata);
3321 free(lundata);
3322 goto retry;
3325 if (lunsonly == 0)
3326 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
3327 ((list_len / 8) > 1) ? "s" : "");
3329 if (countonly != 0)
3330 goto bailout;
3332 for (i = 0; i < (list_len / 8); i++) {
3333 int no_more;
3335 no_more = 0;
3336 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
3337 if (j != 0)
3338 fprintf(stdout, ",");
3339 switch (lundata->luns[i].lundata[j] &
3340 RPL_LUNDATA_ATYP_MASK) {
3341 case RPL_LUNDATA_ATYP_PERIPH:
3342 if ((lundata->luns[i].lundata[j] &
3343 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
3344 fprintf(stdout, "%d:",
3345 lundata->luns[i].lundata[j] &
3346 RPL_LUNDATA_PERIPH_BUS_MASK);
3347 else if ((j == 0)
3348 && ((lundata->luns[i].lundata[j+2] &
3349 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
3350 no_more = 1;
3352 fprintf(stdout, "%d",
3353 lundata->luns[i].lundata[j+1]);
3354 break;
3355 case RPL_LUNDATA_ATYP_FLAT: {
3356 uint8_t tmplun[2];
3357 tmplun[0] = lundata->luns[i].lundata[j] &
3358 RPL_LUNDATA_FLAT_LUN_MASK;
3359 tmplun[1] = lundata->luns[i].lundata[j+1];
3361 fprintf(stdout, "%d", scsi_2btoul(tmplun));
3362 no_more = 1;
3363 break;
3365 case RPL_LUNDATA_ATYP_LUN:
3366 fprintf(stdout, "%d:%d:%d",
3367 (lundata->luns[i].lundata[j+1] &
3368 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
3369 lundata->luns[i].lundata[j] &
3370 RPL_LUNDATA_LUN_TARG_MASK,
3371 lundata->luns[i].lundata[j+1] &
3372 RPL_LUNDATA_LUN_LUN_MASK);
3373 break;
3374 case RPL_LUNDATA_ATYP_EXTLUN: {
3375 int field_len, field_len_code, eam_code;
3377 eam_code = lundata->luns[i].lundata[j] &
3378 RPL_LUNDATA_EXT_EAM_MASK;
3379 field_len_code = (lundata->luns[i].lundata[j] &
3380 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
3381 field_len = field_len_code * 2;
3383 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
3384 && (field_len_code == 0x00)) {
3385 fprintf(stdout, "%d",
3386 lundata->luns[i].lundata[j+1]);
3387 } else if ((eam_code ==
3388 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
3389 && (field_len_code == 0x03)) {
3390 uint8_t tmp_lun[8];
3393 * This format takes up all 8 bytes.
3394 * If we aren't starting at offset 0,
3395 * that's a bug.
3397 if (j != 0) {
3398 fprintf(stdout, "Invalid "
3399 "offset %d for "
3400 "Extended LUN not "
3401 "specified format", j);
3402 no_more = 1;
3403 break;
3405 bzero(tmp_lun, sizeof(tmp_lun));
3406 bcopy(&lundata->luns[i].lundata[j+1],
3407 &tmp_lun[1], sizeof(tmp_lun) - 1);
3408 fprintf(stdout, "%#jx",
3409 (intmax_t)scsi_8btou64(tmp_lun));
3410 no_more = 1;
3411 } else {
3412 fprintf(stderr, "Unknown Extended LUN"
3413 "Address method %#x, length "
3414 "code %#x", eam_code,
3415 field_len_code);
3416 no_more = 1;
3418 break;
3420 default:
3421 fprintf(stderr, "Unknown LUN address method "
3422 "%#x\n", lundata->luns[i].lundata[0] &
3423 RPL_LUNDATA_ATYP_MASK);
3424 break;
3427 * For the flat addressing method, there are no
3428 * other levels after it.
3430 if (no_more != 0)
3431 break;
3433 fprintf(stdout, "\n");
3436 bailout:
3438 cam_freeccb(ccb);
3440 free(lundata);
3442 return (retval);
3445 #endif /* MINIMALISTIC */
3447 void
3448 usage(int verbose)
3450 fprintf(verbose ? stdout : stderr,
3451 "usage: camcontrol <command> [device id][generic args][command args]\n"
3452 " camcontrol devlist [-v]\n"
3453 #ifndef MINIMALISTIC
3454 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
3455 " camcontrol tur [dev_id][generic args]\n"
3456 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
3457 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
3458 " camcontrol start [dev_id][generic args]\n"
3459 " camcontrol stop [dev_id][generic args]\n"
3460 " camcontrol load [dev_id][generic args]\n"
3461 " camcontrol eject [dev_id][generic args]\n"
3462 #endif /* MINIMALISTIC */
3463 " camcontrol rescan <all | bus[:target:lun]>\n"
3464 " camcontrol reset <all | bus[:target:lun]>\n"
3465 #ifndef MINIMALISTIC
3466 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
3467 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
3468 " [-P pagectl][-e | -b][-d]\n"
3469 " camcontrol cmd [dev_id][generic args] <-c cmd [args]>\n"
3470 " [-i len fmt|-o len fmt [args]]\n"
3471 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
3472 " <all|bus[:target[:lun]]|off>\n"
3473 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
3474 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
3475 " [-D <enable|disable>][-O offset][-q]\n"
3476 " [-R syncrate][-v][-T <enable|disable>]\n"
3477 " [-U][-W bus_width]\n"
3478 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
3479 #endif /* MINIMALISTIC */
3480 " camcontrol help\n");
3481 if (!verbose)
3482 return;
3483 #ifndef MINIMALISTIC
3484 fprintf(stdout,
3485 "Specify one of the following options:\n"
3486 "devlist list all CAM devices\n"
3487 "periphlist list all CAM peripheral drivers attached to a device\n"
3488 "tur send a test unit ready to the named device\n"
3489 "inquiry send a SCSI inquiry command to the named device\n"
3490 "reportluns send a SCSI report luns command to the device\n"
3491 "start send a Start Unit command to the device\n"
3492 "stop send a Stop Unit command to the device\n"
3493 "load send a Start Unit command to the device with the load bit set\n"
3494 "eject send a Stop Unit command to the device with the eject bit set\n"
3495 "rescan rescan all busses, the given bus, or bus:target:lun\n"
3496 "reset reset all busses, the given bus, or bus:target:lun\n"
3497 "defects read the defect list of the specified device\n"
3498 "modepage display or edit (-e) the given mode page\n"
3499 "cmd send the given scsi command, may need -i or -o as well\n"
3500 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
3501 "tags report or set the number of transaction slots for a device\n"
3502 "negotiate report or set device negotiation parameters\n"
3503 "format send the SCSI FORMAT UNIT command to the named device\n"
3504 "help this message\n"
3505 "Device Identifiers:\n"
3506 "bus:target specify the bus and target, lun defaults to 0\n"
3507 "bus:target:lun specify the bus, target and lun\n"
3508 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
3509 "Generic arguments:\n"
3510 "-v be verbose, print out sense information\n"
3511 "-t timeout command timeout in seconds, overrides default timeout\n"
3512 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
3513 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
3514 "-E have the kernel attempt to perform SCSI error recovery\n"
3515 "-C count specify the SCSI command retry count (needs -E to work)\n"
3516 "modepage arguments:\n"
3517 "-l list all available mode pages\n"
3518 "-m page specify the mode page to view or edit\n"
3519 "-e edit the specified mode page\n"
3520 "-b force view to binary mode\n"
3521 "-d disable block descriptors for mode sense\n"
3522 "-P pgctl page control field 0-3\n"
3523 "defects arguments:\n"
3524 "-f format specify defect list format (block, bfi or phys)\n"
3525 "-G get the grown defect list\n"
3526 "-P get the permanant defect list\n"
3527 "inquiry arguments:\n"
3528 "-D get the standard inquiry data\n"
3529 "-S get the serial number\n"
3530 "-R get the transfer rate, etc.\n"
3531 "reportluns arguments:\n"
3532 "-c only report a count of available LUNs\n"
3533 "-l only print out luns, and not a count\n"
3534 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
3535 "cmd arguments:\n"
3536 "-c cdb [args] specify the SCSI CDB\n"
3537 "-i len fmt specify input data and input data format\n"
3538 "-o len fmt [args] specify output data and output data fmt\n"
3539 "debug arguments:\n"
3540 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
3541 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
3542 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
3543 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
3544 "tags arguments:\n"
3545 "-N tags specify the number of tags to use for this device\n"
3546 "-q be quiet, don't report the number of tags\n"
3547 "-v report a number of tag-related parameters\n"
3548 "negotiate arguments:\n"
3549 "-a send a test unit ready after negotiation\n"
3550 "-c report/set current negotiation settings\n"
3551 "-D <arg> \"enable\" or \"disable\" disconnection\n"
3552 "-O offset set command delay offset\n"
3553 "-q be quiet, don't report anything\n"
3554 "-R syncrate synchronization rate in MHz\n"
3555 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
3556 "-U report/set user negotiation settings\n"
3557 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
3558 "-v also print a Path Inquiry CCB for the controller\n"
3559 "format arguments:\n"
3560 "-q be quiet, don't print status messages\n"
3561 "-r run in report only mode\n"
3562 "-w don't send immediate format command\n"
3563 "-y don't ask any questions\n");
3564 #endif /* MINIMALISTIC */
3567 int
3568 main(int argc, char **argv)
3570 int c;
3571 char *device = NULL;
3572 int unit = 0;
3573 struct cam_device *cam_dev = NULL;
3574 int timeout = 0, retry_count = 1;
3575 camcontrol_optret optreturn;
3576 char *tstr;
3577 const char *mainopt = "C:En:t:u:v";
3578 const char *subopt = NULL;
3579 char combinedopt[256];
3580 int error = 0, optstart = 2;
3581 int devopen = 1;
3583 cmdlist = CAM_CMD_NONE;
3584 arglist = CAM_ARG_NONE;
3586 if (argc < 2) {
3587 usage(0);
3588 exit(1);
3592 * Get the base option.
3594 optreturn = getoption(argv[1], &cmdlist, &arglist, &subopt);
3596 if (optreturn == CC_OR_AMBIGUOUS) {
3597 warnx("ambiguous option %s", argv[1]);
3598 usage(0);
3599 exit(1);
3600 } else if (optreturn == CC_OR_NOT_FOUND) {
3601 warnx("option %s not found", argv[1]);
3602 usage(0);
3603 exit(1);
3607 * Ahh, getopt(3) is a pain.
3609 * This is a gross hack. There really aren't many other good
3610 * options (excuse the pun) for parsing options in a situation like
3611 * this. getopt is kinda braindead, so you end up having to run
3612 * through the options twice, and give each invocation of getopt
3613 * the option string for the other invocation.
3615 * You would think that you could just have two groups of options.
3616 * The first group would get parsed by the first invocation of
3617 * getopt, and the second group would get parsed by the second
3618 * invocation of getopt. It doesn't quite work out that way. When
3619 * the first invocation of getopt finishes, it leaves optind pointing
3620 * to the argument _after_ the first argument in the second group.
3621 * So when the second invocation of getopt comes around, it doesn't
3622 * recognize the first argument it gets and then bails out.
3624 * A nice alternative would be to have a flag for getopt that says
3625 * "just keep parsing arguments even when you encounter an unknown
3626 * argument", but there isn't one. So there's no real clean way to
3627 * easily parse two sets of arguments without having one invocation
3628 * of getopt know about the other.
3630 * Without this hack, the first invocation of getopt would work as
3631 * long as the generic arguments are first, but the second invocation
3632 * (in the subfunction) would fail in one of two ways. In the case
3633 * where you don't set optreset, it would fail because optind may be
3634 * pointing to the argument after the one it should be pointing at.
3635 * In the case where you do set optreset, and reset optind, it would
3636 * fail because getopt would run into the first set of options, which
3637 * it doesn't understand.
3639 * All of this would "sort of" work if you could somehow figure out
3640 * whether optind had been incremented one option too far. The
3641 * mechanics of that, however, are more daunting than just giving
3642 * both invocations all of the expect options for either invocation.
3644 * Needless to say, I wouldn't mind if someone invented a better
3645 * (non-GPL!) command line parsing interface than getopt. I
3646 * wouldn't mind if someone added more knobs to getopt to make it
3647 * work better. Who knows, I may talk myself into doing it someday,
3648 * if the standards weenies let me. As it is, it just leads to
3649 * hackery like this and causes people to avoid it in some cases.
3651 * KDM, September 8th, 1998
3653 if (subopt != NULL)
3654 sprintf(combinedopt, "%s%s", mainopt, subopt);
3655 else
3656 sprintf(combinedopt, "%s", mainopt);
3659 * For these options we do not parse optional device arguments and
3660 * we do not open a passthrough device.
3662 if ((cmdlist == CAM_CMD_RESCAN)
3663 || (cmdlist == CAM_CMD_RESET)
3664 || (cmdlist == CAM_CMD_DEVTREE)
3665 || (cmdlist == CAM_CMD_USAGE)
3666 || (cmdlist == CAM_CMD_DEBUG))
3667 devopen = 0;
3669 #ifndef MINIMALISTIC
3670 if ((devopen == 1)
3671 && (argc > 2 && argv[2][0] != '-')) {
3672 char name[30];
3673 int rv;
3676 * First catch people who try to do things like:
3677 * camcontrol tur /dev/da0
3678 * camcontrol doesn't take device nodes as arguments.
3680 if (argv[2][0] == '/') {
3681 warnx("%s is not a valid device identifier", argv[2]);
3682 errx(1, "please read the camcontrol(8) man page");
3683 } else if (isdigit(argv[2][0])) {
3684 /* device specified as bus:target[:lun] */
3685 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
3686 if (rv < 2)
3687 errx(1, "numeric device specification must "
3688 "be either bus:target, or "
3689 "bus:target:lun");
3690 /* default to 0 if lun was not specified */
3691 if ((arglist & CAM_ARG_LUN) == 0) {
3692 lun = 0;
3693 arglist |= CAM_ARG_LUN;
3695 optstart++;
3696 } else {
3697 if (cam_get_device(argv[2], name, sizeof name, &unit)
3698 == -1)
3699 errx(1, "%s", cam_errbuf);
3700 device = strdup(name);
3701 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
3702 optstart++;
3705 #endif /* MINIMALISTIC */
3707 * Start getopt processing at argv[2/3], since we've already
3708 * accepted argv[1..2] as the command name, and as a possible
3709 * device name.
3711 optind = optstart;
3714 * Now we run through the argument list looking for generic
3715 * options, and ignoring options that possibly belong to
3716 * subfunctions.
3718 while ((c = getopt(argc, argv, combinedopt))!= -1){
3719 switch(c) {
3720 case 'C':
3721 retry_count = strtol(optarg, NULL, 0);
3722 if (retry_count < 0)
3723 errx(1, "retry count %d is < 0",
3724 retry_count);
3725 arglist |= CAM_ARG_RETRIES;
3726 break;
3727 case 'E':
3728 arglist |= CAM_ARG_ERR_RECOVER;
3729 break;
3730 case 'n':
3731 arglist |= CAM_ARG_DEVICE;
3732 tstr = optarg;
3733 while (isspace(*tstr) && (*tstr != '\0'))
3734 tstr++;
3735 device = (char *)strdup(tstr);
3736 break;
3737 case 't':
3738 timeout = strtol(optarg, NULL, 0);
3739 if (timeout < 0)
3740 errx(1, "invalid timeout %d", timeout);
3741 /* Convert the timeout from seconds to ms */
3742 timeout *= 1000;
3743 arglist |= CAM_ARG_TIMEOUT;
3744 break;
3745 case 'u':
3746 arglist |= CAM_ARG_UNIT;
3747 unit = strtol(optarg, NULL, 0);
3748 break;
3749 case 'v':
3750 arglist |= CAM_ARG_VERBOSE;
3751 break;
3752 default:
3753 break;
3757 #ifndef MINIMALISTIC
3759 * For most commands we'll want to open the passthrough device
3760 * associated with the specified device. In the case of the rescan
3761 * commands, we don't use a passthrough device at all, just the
3762 * transport layer device.
3764 if (devopen == 1) {
3765 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
3766 && (((arglist & CAM_ARG_DEVICE) == 0)
3767 || ((arglist & CAM_ARG_UNIT) == 0))) {
3768 errx(1, "subcommand \"%s\" requires a valid device "
3769 "identifier", argv[1]);
3772 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
3773 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
3774 cam_open_spec_device(device,unit,O_RDWR,NULL)))
3775 == NULL)
3776 errx(1,"%s", cam_errbuf);
3778 #endif /* MINIMALISTIC */
3781 * Reset optind to 2, and reset getopt, so these routines can parse
3782 * the arguments again.
3784 optind = optstart;
3785 optreset = 1;
3787 switch(cmdlist) {
3788 #ifndef MINIMALISTIC
3789 case CAM_CMD_DEVLIST:
3790 error = getdevlist(cam_dev);
3791 break;
3792 #endif /* MINIMALISTIC */
3793 case CAM_CMD_DEVTREE:
3794 error = getdevtree();
3795 break;
3796 #ifndef MINIMALISTIC
3797 case CAM_CMD_TUR:
3798 error = testunitready(cam_dev, retry_count, timeout, 0);
3799 break;
3800 case CAM_CMD_INQUIRY:
3801 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
3802 retry_count, timeout);
3803 break;
3804 case CAM_CMD_STARTSTOP:
3805 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
3806 arglist & CAM_ARG_EJECT, retry_count,
3807 timeout);
3808 break;
3809 #endif /* MINIMALISTIC */
3810 case CAM_CMD_RESCAN:
3811 error = dorescan_or_reset(argc, argv, 1);
3812 break;
3813 case CAM_CMD_RESET:
3814 error = dorescan_or_reset(argc, argv, 0);
3815 break;
3816 #ifndef MINIMALISTIC
3817 case CAM_CMD_READ_DEFECTS:
3818 error = readdefects(cam_dev, argc, argv, combinedopt,
3819 retry_count, timeout);
3820 break;
3821 case CAM_CMD_MODE_PAGE:
3822 modepage(cam_dev, argc, argv, combinedopt,
3823 retry_count, timeout);
3824 break;
3825 case CAM_CMD_SCSI_CMD:
3826 error = scsicmd(cam_dev, argc, argv, combinedopt,
3827 retry_count, timeout);
3828 break;
3829 case CAM_CMD_DEBUG:
3830 error = camdebug(argc, argv, combinedopt);
3831 break;
3832 case CAM_CMD_TAG:
3833 error = tagcontrol(cam_dev, argc, argv, combinedopt);
3834 break;
3835 case CAM_CMD_RATE:
3836 error = ratecontrol(cam_dev, retry_count, timeout,
3837 argc, argv, combinedopt);
3838 break;
3839 case CAM_CMD_FORMAT:
3840 error = scsiformat(cam_dev, argc, argv,
3841 combinedopt, retry_count, timeout);
3842 break;
3843 case CAM_CMD_REPORTLUNS:
3844 error = scsireportluns(cam_dev, argc, argv,
3845 combinedopt, retry_count,
3846 timeout);
3847 break;
3848 #endif /* MINIMALISTIC */
3849 case CAM_CMD_USAGE:
3850 usage(1);
3851 break;
3852 default:
3853 usage(0);
3854 error = 1;
3855 break;
3858 if (cam_dev != NULL)
3859 cam_close_device(cam_dev);
3861 exit(error);