]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sbin/camcontrol/camcontrol.c
MFC r236437:
[FreeBSD/stable/8.git] / sbin / camcontrol / camcontrol.c
1 /*
2  * Copyright (c) 1997-2007 Kenneth D. Merry
3  * All rights reserved.
4  *
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.
15  *
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.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/ioctl.h>
33 #include <sys/stdint.h>
34 #include <sys/types.h>
35 #include <sys/endian.h>
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <ctype.h>
43 #include <err.h>
44 #include <libutil.h>
45
46 #include <cam/cam.h>
47 #include <cam/cam_debug.h>
48 #include <cam/cam_ccb.h>
49 #include <cam/scsi/scsi_all.h>
50 #include <cam/scsi/scsi_da.h>
51 #include <cam/scsi/scsi_pass.h>
52 #include <cam/scsi/scsi_message.h>
53 #include <cam/ata/ata_all.h>
54 #include <camlib.h>
55 #include "camcontrol.h"
56
57 typedef enum {
58         CAM_CMD_NONE            = 0x00000000,
59         CAM_CMD_DEVLIST         = 0x00000001,
60         CAM_CMD_TUR             = 0x00000002,
61         CAM_CMD_INQUIRY         = 0x00000003,
62         CAM_CMD_STARTSTOP       = 0x00000004,
63         CAM_CMD_RESCAN          = 0x00000005,
64         CAM_CMD_READ_DEFECTS    = 0x00000006,
65         CAM_CMD_MODE_PAGE       = 0x00000007,
66         CAM_CMD_SCSI_CMD        = 0x00000008,
67         CAM_CMD_DEVTREE         = 0x00000009,
68         CAM_CMD_USAGE           = 0x0000000a,
69         CAM_CMD_DEBUG           = 0x0000000b,
70         CAM_CMD_RESET           = 0x0000000c,
71         CAM_CMD_FORMAT          = 0x0000000d,
72         CAM_CMD_TAG             = 0x0000000e,
73         CAM_CMD_RATE            = 0x0000000f,
74         CAM_CMD_DETACH          = 0x00000010,
75         CAM_CMD_REPORTLUNS      = 0x00000011,
76         CAM_CMD_READCAP         = 0x00000012,
77         CAM_CMD_IDENTIFY        = 0x00000013,
78         CAM_CMD_IDLE            = 0x00000014,
79         CAM_CMD_STANDBY         = 0x00000015,
80         CAM_CMD_SLEEP           = 0x00000016
81 } cam_cmdmask;
82
83 typedef enum {
84         CAM_ARG_NONE            = 0x00000000,
85         CAM_ARG_VERBOSE         = 0x00000001,
86         CAM_ARG_DEVICE          = 0x00000002,
87         CAM_ARG_BUS             = 0x00000004,
88         CAM_ARG_TARGET          = 0x00000008,
89         CAM_ARG_LUN             = 0x00000010,
90         CAM_ARG_EJECT           = 0x00000020,
91         CAM_ARG_UNIT            = 0x00000040,
92         CAM_ARG_FORMAT_BLOCK    = 0x00000080,
93         CAM_ARG_FORMAT_BFI      = 0x00000100,
94         CAM_ARG_FORMAT_PHYS     = 0x00000200,
95         CAM_ARG_PLIST           = 0x00000400,
96         CAM_ARG_GLIST           = 0x00000800,
97         CAM_ARG_GET_SERIAL      = 0x00001000,
98         CAM_ARG_GET_STDINQ      = 0x00002000,
99         CAM_ARG_GET_XFERRATE    = 0x00004000,
100         CAM_ARG_INQ_MASK        = 0x00007000,
101         CAM_ARG_MODE_EDIT       = 0x00008000,
102         CAM_ARG_PAGE_CNTL       = 0x00010000,
103         CAM_ARG_TIMEOUT         = 0x00020000,
104         CAM_ARG_CMD_IN          = 0x00040000,
105         CAM_ARG_CMD_OUT         = 0x00080000,
106         CAM_ARG_DBD             = 0x00100000,
107         CAM_ARG_ERR_RECOVER     = 0x00200000,
108         CAM_ARG_RETRIES         = 0x00400000,
109         CAM_ARG_START_UNIT      = 0x00800000,
110         CAM_ARG_DEBUG_INFO      = 0x01000000,
111         CAM_ARG_DEBUG_TRACE     = 0x02000000,
112         CAM_ARG_DEBUG_SUBTRACE  = 0x04000000,
113         CAM_ARG_DEBUG_CDB       = 0x08000000,
114         CAM_ARG_DEBUG_XPT       = 0x10000000,
115         CAM_ARG_DEBUG_PERIPH    = 0x20000000,
116 } cam_argmask;
117
118 struct camcontrol_opts {
119         const char      *optname;
120         cam_cmdmask     cmdnum;
121         cam_argmask     argnum;
122         const char      *subopt;
123 };
124
125 #ifndef MINIMALISTIC
126 static const char scsicmd_opts[] = "a:c:dfi:o:r";
127 static const char readdefect_opts[] = "f:GP";
128 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
129 #endif
130
131 struct camcontrol_opts option_table[] = {
132 #ifndef MINIMALISTIC
133         {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
134         {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
135         {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
136         {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
137         {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
138         {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
139         {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
140         {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
141         {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
142 #endif /* MINIMALISTIC */
143         {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
144         {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
145 #ifndef MINIMALISTIC
146         {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
147         {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
148         {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
149         {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
150 #endif /* MINIMALISTIC */
151         {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
152 #ifndef MINIMALISTIC
153         {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
154         {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
155         {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
156         {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
157         {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
158         {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
159         {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
160         {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
161         {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
162         {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
163 #endif /* MINIMALISTIC */
164         {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
165         {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
166         {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
167         {NULL, 0, 0, NULL}
168 };
169
170 typedef enum {
171         CC_OR_NOT_FOUND,
172         CC_OR_AMBIGUOUS,
173         CC_OR_FOUND
174 } camcontrol_optret;
175
176 cam_cmdmask cmdlist;
177 cam_argmask arglist;
178
179
180 camcontrol_optret getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
181                             const char **subopt);
182 #ifndef MINIMALISTIC
183 static int getdevlist(struct cam_device *device);
184 #endif /* MINIMALISTIC */
185 static int getdevtree(void);
186 #ifndef MINIMALISTIC
187 static int testunitready(struct cam_device *device, int retry_count,
188                          int timeout, int quiet);
189 static int scsistart(struct cam_device *device, int startstop, int loadeject,
190                      int retry_count, int timeout);
191 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
192                          char *combinedopt, int retry_count, int timeout);
193 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
194 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
195 static int camxferrate(struct cam_device *device);
196 #endif /* MINIMALISTIC */
197 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
198                      cam_argmask *arglst);
199 static int dorescan_or_reset(int argc, char **argv, int rescan);
200 static int rescan_or_reset_bus(int bus, int rescan);
201 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
202 #ifndef MINIMALISTIC
203 static int readdefects(struct cam_device *device, int argc, char **argv,
204                        char *combinedopt, int retry_count, int timeout);
205 static void modepage(struct cam_device *device, int argc, char **argv,
206                      char *combinedopt, int retry_count, int timeout);
207 static int scsicmd(struct cam_device *device, int argc, char **argv,
208                    char *combinedopt, int retry_count, int timeout);
209 static int tagcontrol(struct cam_device *device, int argc, char **argv,
210                       char *combinedopt);
211 static void cts_print(struct cam_device *device,
212                       struct ccb_trans_settings *cts);
213 static void cpi_print(struct ccb_pathinq *cpi);
214 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
215 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
216 static int get_print_cts(struct cam_device *device, int user_settings,
217                          int quiet, struct ccb_trans_settings *cts);
218 static int ratecontrol(struct cam_device *device, int retry_count,
219                        int timeout, int argc, char **argv, char *combinedopt);
220 static int scsiformat(struct cam_device *device, int argc, char **argv,
221                       char *combinedopt, int retry_count, int timeout);
222 static int scsireportluns(struct cam_device *device, int argc, char **argv,
223                           char *combinedopt, int retry_count, int timeout);
224 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
225                             char *combinedopt, int retry_count, int timeout);
226 static int atapm(struct cam_device *device, int argc, char **argv,
227                             char *combinedopt, int retry_count, int timeout);
228 #endif /* MINIMALISTIC */
229 #ifndef min
230 #define min(a,b) (((a)<(b))?(a):(b))
231 #endif
232 #ifndef max
233 #define max(a,b) (((a)>(b))?(a):(b))
234 #endif
235
236 camcontrol_optret
237 getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
238           const char **subopt)
239 {
240         struct camcontrol_opts *opts;
241         int num_matches = 0;
242
243         for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
244              opts++) {
245                 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
246                         *cmdnum = opts->cmdnum;
247                         *argnum = opts->argnum;
248                         *subopt = opts->subopt;
249                         if (++num_matches > 1)
250                                 return(CC_OR_AMBIGUOUS);
251                 }
252         }
253
254         if (num_matches > 0)
255                 return(CC_OR_FOUND);
256         else
257                 return(CC_OR_NOT_FOUND);
258 }
259
260 #ifndef MINIMALISTIC
261 static int
262 getdevlist(struct cam_device *device)
263 {
264         union ccb *ccb;
265         char status[32];
266         int error = 0;
267
268         ccb = cam_getccb(device);
269
270         ccb->ccb_h.func_code = XPT_GDEVLIST;
271         ccb->ccb_h.flags = CAM_DIR_NONE;
272         ccb->ccb_h.retry_count = 1;
273         ccb->cgdl.index = 0;
274         ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
275         while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
276                 if (cam_send_ccb(device, ccb) < 0) {
277                         perror("error getting device list");
278                         cam_freeccb(ccb);
279                         return(1);
280                 }
281
282                 status[0] = '\0';
283
284                 switch (ccb->cgdl.status) {
285                         case CAM_GDEVLIST_MORE_DEVS:
286                                 strcpy(status, "MORE");
287                                 break;
288                         case CAM_GDEVLIST_LAST_DEVICE:
289                                 strcpy(status, "LAST");
290                                 break;
291                         case CAM_GDEVLIST_LIST_CHANGED:
292                                 strcpy(status, "CHANGED");
293                                 break;
294                         case CAM_GDEVLIST_ERROR:
295                                 strcpy(status, "ERROR");
296                                 error = 1;
297                                 break;
298                 }
299
300                 fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
301                         ccb->cgdl.periph_name,
302                         ccb->cgdl.unit_number,
303                         ccb->cgdl.generation,
304                         ccb->cgdl.index,
305                         status);
306
307                 /*
308                  * If the list has changed, we need to start over from the
309                  * beginning.
310                  */
311                 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
312                         ccb->cgdl.index = 0;
313         }
314
315         cam_freeccb(ccb);
316
317         return(error);
318 }
319 #endif /* MINIMALISTIC */
320
321 static int
322 getdevtree(void)
323 {
324         union ccb ccb;
325         int bufsize, fd;
326         unsigned int i;
327         int need_close = 0;
328         int error = 0;
329         int skip_device = 0;
330
331         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
332                 warn("couldn't open %s", XPT_DEVICE);
333                 return(1);
334         }
335
336         bzero(&ccb, sizeof(union ccb));
337
338         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
339         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
340         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
341
342         ccb.ccb_h.func_code = XPT_DEV_MATCH;
343         bufsize = sizeof(struct dev_match_result) * 100;
344         ccb.cdm.match_buf_len = bufsize;
345         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
346         if (ccb.cdm.matches == NULL) {
347                 warnx("can't malloc memory for matches");
348                 close(fd);
349                 return(1);
350         }
351         ccb.cdm.num_matches = 0;
352
353         /*
354          * We fetch all nodes, since we display most of them in the default
355          * case, and all in the verbose case.
356          */
357         ccb.cdm.num_patterns = 0;
358         ccb.cdm.pattern_buf_len = 0;
359
360         /*
361          * We do the ioctl multiple times if necessary, in case there are
362          * more than 100 nodes in the EDT.
363          */
364         do {
365                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
366                         warn("error sending CAMIOCOMMAND ioctl");
367                         error = 1;
368                         break;
369                 }
370
371                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
372                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
373                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
374                         warnx("got CAM error %#x, CDM error %d\n",
375                               ccb.ccb_h.status, ccb.cdm.status);
376                         error = 1;
377                         break;
378                 }
379
380                 for (i = 0; i < ccb.cdm.num_matches; i++) {
381                         switch (ccb.cdm.matches[i].type) {
382                         case DEV_MATCH_BUS: {
383                                 struct bus_match_result *bus_result;
384
385                                 /*
386                                  * Only print the bus information if the
387                                  * user turns on the verbose flag.
388                                  */
389                                 if ((arglist & CAM_ARG_VERBOSE) == 0)
390                                         break;
391
392                                 bus_result =
393                                         &ccb.cdm.matches[i].result.bus_result;
394
395                                 if (need_close) {
396                                         fprintf(stdout, ")\n");
397                                         need_close = 0;
398                                 }
399
400                                 fprintf(stdout, "scbus%d on %s%d bus %d:\n",
401                                         bus_result->path_id,
402                                         bus_result->dev_name,
403                                         bus_result->unit_number,
404                                         bus_result->bus_id);
405                                 break;
406                         }
407                         case DEV_MATCH_DEVICE: {
408                                 struct device_match_result *dev_result;
409                                 char vendor[16], product[48], revision[16];
410                                 char tmpstr[256];
411
412                                 dev_result =
413                                      &ccb.cdm.matches[i].result.device_result;
414
415                                 if ((dev_result->flags
416                                      & DEV_RESULT_UNCONFIGURED)
417                                  && ((arglist & CAM_ARG_VERBOSE) == 0)) {
418                                         skip_device = 1;
419                                         break;
420                                 } else
421                                         skip_device = 0;
422
423                                 if (dev_result->protocol == PROTO_SCSI) {
424                                     cam_strvis(vendor, dev_result->inq_data.vendor,
425                                            sizeof(dev_result->inq_data.vendor),
426                                            sizeof(vendor));
427                                     cam_strvis(product,
428                                            dev_result->inq_data.product,
429                                            sizeof(dev_result->inq_data.product),
430                                            sizeof(product));
431                                     cam_strvis(revision,
432                                            dev_result->inq_data.revision,
433                                           sizeof(dev_result->inq_data.revision),
434                                            sizeof(revision));
435                                     sprintf(tmpstr, "<%s %s %s>", vendor, product,
436                                         revision);
437                                 } else if (dev_result->protocol == PROTO_ATA ||
438                                     dev_result->protocol == PROTO_SATAPM) {
439                                     cam_strvis(product,
440                                            dev_result->ident_data.model,
441                                            sizeof(dev_result->ident_data.model),
442                                            sizeof(product));
443                                     cam_strvis(revision,
444                                            dev_result->ident_data.revision,
445                                           sizeof(dev_result->ident_data.revision),
446                                            sizeof(revision));
447                                     sprintf(tmpstr, "<%s %s>", product,
448                                         revision);
449                                 } else {
450                                     sprintf(tmpstr, "<>");
451                                 }
452                                 if (need_close) {
453                                         fprintf(stdout, ")\n");
454                                         need_close = 0;
455                                 }
456
457                                 fprintf(stdout, "%-33s  at scbus%d "
458                                         "target %d lun %d (",
459                                         tmpstr,
460                                         dev_result->path_id,
461                                         dev_result->target_id,
462                                         dev_result->target_lun);
463
464                                 need_close = 1;
465
466                                 break;
467                         }
468                         case DEV_MATCH_PERIPH: {
469                                 struct periph_match_result *periph_result;
470
471                                 periph_result =
472                                       &ccb.cdm.matches[i].result.periph_result;
473
474                                 if (skip_device != 0)
475                                         break;
476
477                                 if (need_close > 1)
478                                         fprintf(stdout, ",");
479
480                                 fprintf(stdout, "%s%d",
481                                         periph_result->periph_name,
482                                         periph_result->unit_number);
483
484                                 need_close++;
485                                 break;
486                         }
487                         default:
488                                 fprintf(stdout, "unknown match type\n");
489                                 break;
490                         }
491                 }
492
493         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
494                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
495
496         if (need_close)
497                 fprintf(stdout, ")\n");
498
499         close(fd);
500
501         return(error);
502 }
503
504 #ifndef MINIMALISTIC
505 static int
506 testunitready(struct cam_device *device, int retry_count, int timeout,
507               int quiet)
508 {
509         int error = 0;
510         union ccb *ccb;
511
512         ccb = cam_getccb(device);
513
514         scsi_test_unit_ready(&ccb->csio,
515                              /* retries */ retry_count,
516                              /* cbfcnp */ NULL,
517                              /* tag_action */ MSG_SIMPLE_Q_TAG,
518                              /* sense_len */ SSD_FULL_SIZE,
519                              /* timeout */ timeout ? timeout : 5000);
520
521         /* Disable freezing the device queue */
522         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
523
524         if (arglist & CAM_ARG_ERR_RECOVER)
525                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
526
527         if (cam_send_ccb(device, ccb) < 0) {
528                 if (quiet == 0)
529                         perror("error sending test unit ready");
530
531                 if (arglist & CAM_ARG_VERBOSE) {
532                         cam_error_print(device, ccb, CAM_ESF_ALL,
533                                         CAM_EPF_ALL, stderr);
534                 }
535
536                 cam_freeccb(ccb);
537                 return(1);
538         }
539
540         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
541                 if (quiet == 0)
542                         fprintf(stdout, "Unit is ready\n");
543         } else {
544                 if (quiet == 0)
545                         fprintf(stdout, "Unit is not ready\n");
546                 error = 1;
547
548                 if (arglist & CAM_ARG_VERBOSE) {
549                         cam_error_print(device, ccb, CAM_ESF_ALL,
550                                         CAM_EPF_ALL, stderr);
551                 }
552         }
553
554         cam_freeccb(ccb);
555
556         return(error);
557 }
558
559 static int
560 scsistart(struct cam_device *device, int startstop, int loadeject,
561           int retry_count, int timeout)
562 {
563         union ccb *ccb;
564         int error = 0;
565
566         ccb = cam_getccb(device);
567
568         /*
569          * If we're stopping, send an ordered tag so the drive in question
570          * will finish any previously queued writes before stopping.  If
571          * the device isn't capable of tagged queueing, or if tagged
572          * queueing is turned off, the tag action is a no-op.
573          */
574         scsi_start_stop(&ccb->csio,
575                         /* retries */ retry_count,
576                         /* cbfcnp */ NULL,
577                         /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
578                                                      MSG_ORDERED_Q_TAG,
579                         /* start/stop */ startstop,
580                         /* load_eject */ loadeject,
581                         /* immediate */ 0,
582                         /* sense_len */ SSD_FULL_SIZE,
583                         /* timeout */ timeout ? timeout : 120000);
584
585         /* Disable freezing the device queue */
586         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
587
588         if (arglist & CAM_ARG_ERR_RECOVER)
589                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
590
591         if (cam_send_ccb(device, ccb) < 0) {
592                 perror("error sending start unit");
593
594                 if (arglist & CAM_ARG_VERBOSE) {
595                         cam_error_print(device, ccb, CAM_ESF_ALL,
596                                         CAM_EPF_ALL, stderr);
597                 }
598
599                 cam_freeccb(ccb);
600                 return(1);
601         }
602
603         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
604                 if (startstop) {
605                         fprintf(stdout, "Unit started successfully");
606                         if (loadeject)
607                                 fprintf(stdout,", Media loaded\n");
608                         else
609                                 fprintf(stdout,"\n");
610                 } else {
611                         fprintf(stdout, "Unit stopped successfully");
612                         if (loadeject)
613                                 fprintf(stdout, ", Media ejected\n");
614                         else
615                                 fprintf(stdout, "\n");
616                 }
617         else {
618                 error = 1;
619                 if (startstop)
620                         fprintf(stdout,
621                                 "Error received from start unit command\n");
622                 else
623                         fprintf(stdout,
624                                 "Error received from stop unit command\n");
625
626                 if (arglist & CAM_ARG_VERBOSE) {
627                         cam_error_print(device, ccb, CAM_ESF_ALL,
628                                         CAM_EPF_ALL, stderr);
629                 }
630         }
631
632         cam_freeccb(ccb);
633
634         return(error);
635 }
636
637 static int
638 scsidoinquiry(struct cam_device *device, int argc, char **argv,
639               char *combinedopt, int retry_count, int timeout)
640 {
641         int c;
642         int error = 0;
643
644         while ((c = getopt(argc, argv, combinedopt)) != -1) {
645                 switch(c) {
646                 case 'D':
647                         arglist |= CAM_ARG_GET_STDINQ;
648                         break;
649                 case 'R':
650                         arglist |= CAM_ARG_GET_XFERRATE;
651                         break;
652                 case 'S':
653                         arglist |= CAM_ARG_GET_SERIAL;
654                         break;
655                 default:
656                         break;
657                 }
658         }
659
660         /*
661          * If the user didn't specify any inquiry options, he wants all of
662          * them.
663          */
664         if ((arglist & CAM_ARG_INQ_MASK) == 0)
665                 arglist |= CAM_ARG_INQ_MASK;
666
667         if (arglist & CAM_ARG_GET_STDINQ)
668                 error = scsiinquiry(device, retry_count, timeout);
669
670         if (error != 0)
671                 return(error);
672
673         if (arglist & CAM_ARG_GET_SERIAL)
674                 scsiserial(device, retry_count, timeout);
675
676         if (error != 0)
677                 return(error);
678
679         if (arglist & CAM_ARG_GET_XFERRATE)
680                 error = camxferrate(device);
681
682         return(error);
683 }
684
685 static int
686 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
687 {
688         union ccb *ccb;
689         struct scsi_inquiry_data *inq_buf;
690         int error = 0;
691
692         ccb = cam_getccb(device);
693
694         if (ccb == NULL) {
695                 warnx("couldn't allocate CCB");
696                 return(1);
697         }
698
699         /* cam_getccb cleans up the header, caller has to zero the payload */
700         bzero(&(&ccb->ccb_h)[1],
701               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
702
703         inq_buf = (struct scsi_inquiry_data *)malloc(
704                 sizeof(struct scsi_inquiry_data));
705
706         if (inq_buf == NULL) {
707                 cam_freeccb(ccb);
708                 warnx("can't malloc memory for inquiry\n");
709                 return(1);
710         }
711         bzero(inq_buf, sizeof(*inq_buf));
712
713         /*
714          * Note that although the size of the inquiry buffer is the full
715          * 256 bytes specified in the SCSI spec, we only tell the device
716          * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
717          * two reasons for this:
718          *
719          *  - The SCSI spec says that when a length field is only 1 byte,
720          *    a value of 0 will be interpreted as 256.  Therefore
721          *    scsi_inquiry() will convert an inq_len (which is passed in as
722          *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
723          *    to 0.  Evidently, very few devices meet the spec in that
724          *    regard.  Some devices, like many Seagate disks, take the 0 as
725          *    0, and don't return any data.  One Pioneer DVD-R drive
726          *    returns more data than the command asked for.
727          *
728          *    So, since there are numerous devices that just don't work
729          *    right with the full inquiry size, we don't send the full size.
730          *
731          *  - The second reason not to use the full inquiry data length is
732          *    that we don't need it here.  The only reason we issue a
733          *    standard inquiry is to get the vendor name, device name,
734          *    and revision so scsi_print_inquiry() can print them.
735          *
736          * If, at some point in the future, more inquiry data is needed for
737          * some reason, this code should use a procedure similar to the
738          * probe code.  i.e., issue a short inquiry, and determine from
739          * the additional length passed back from the device how much
740          * inquiry data the device supports.  Once the amount the device
741          * supports is determined, issue an inquiry for that amount and no
742          * more.
743          *
744          * KDM, 2/18/2000
745          */
746         scsi_inquiry(&ccb->csio,
747                      /* retries */ retry_count,
748                      /* cbfcnp */ NULL,
749                      /* tag_action */ MSG_SIMPLE_Q_TAG,
750                      /* inq_buf */ (u_int8_t *)inq_buf,
751                      /* inq_len */ SHORT_INQUIRY_LENGTH,
752                      /* evpd */ 0,
753                      /* page_code */ 0,
754                      /* sense_len */ SSD_FULL_SIZE,
755                      /* timeout */ timeout ? timeout : 5000);
756
757         /* Disable freezing the device queue */
758         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
759
760         if (arglist & CAM_ARG_ERR_RECOVER)
761                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
762
763         if (cam_send_ccb(device, ccb) < 0) {
764                 perror("error sending SCSI inquiry");
765
766                 if (arglist & CAM_ARG_VERBOSE) {
767                         cam_error_print(device, ccb, CAM_ESF_ALL,
768                                         CAM_EPF_ALL, stderr);
769                 }
770
771                 cam_freeccb(ccb);
772                 return(1);
773         }
774
775         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
776                 error = 1;
777
778                 if (arglist & CAM_ARG_VERBOSE) {
779                         cam_error_print(device, ccb, CAM_ESF_ALL,
780                                         CAM_EPF_ALL, stderr);
781                 }
782         }
783
784         cam_freeccb(ccb);
785
786         if (error != 0) {
787                 free(inq_buf);
788                 return(error);
789         }
790
791         fprintf(stdout, "%s%d: ", device->device_name,
792                 device->dev_unit_num);
793         scsi_print_inquiry(inq_buf);
794
795         free(inq_buf);
796
797         return(0);
798 }
799
800 static int
801 scsiserial(struct cam_device *device, int retry_count, int timeout)
802 {
803         union ccb *ccb;
804         struct scsi_vpd_unit_serial_number *serial_buf;
805         char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
806         int error = 0;
807
808         ccb = cam_getccb(device);
809
810         if (ccb == NULL) {
811                 warnx("couldn't allocate CCB");
812                 return(1);
813         }
814
815         /* cam_getccb cleans up the header, caller has to zero the payload */
816         bzero(&(&ccb->ccb_h)[1],
817               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
818
819         serial_buf = (struct scsi_vpd_unit_serial_number *)
820                 malloc(sizeof(*serial_buf));
821
822         if (serial_buf == NULL) {
823                 cam_freeccb(ccb);
824                 warnx("can't malloc memory for serial number");
825                 return(1);
826         }
827
828         scsi_inquiry(&ccb->csio,
829                      /*retries*/ retry_count,
830                      /*cbfcnp*/ NULL,
831                      /* tag_action */ MSG_SIMPLE_Q_TAG,
832                      /* inq_buf */ (u_int8_t *)serial_buf,
833                      /* inq_len */ sizeof(*serial_buf),
834                      /* evpd */ 1,
835                      /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
836                      /* sense_len */ SSD_FULL_SIZE,
837                      /* timeout */ timeout ? timeout : 5000);
838
839         /* Disable freezing the device queue */
840         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
841
842         if (arglist & CAM_ARG_ERR_RECOVER)
843                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
844
845         if (cam_send_ccb(device, ccb) < 0) {
846                 warn("error getting serial number");
847
848                 if (arglist & CAM_ARG_VERBOSE) {
849                         cam_error_print(device, ccb, CAM_ESF_ALL,
850                                         CAM_EPF_ALL, stderr);
851                 }
852
853                 cam_freeccb(ccb);
854                 free(serial_buf);
855                 return(1);
856         }
857
858         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
859                 error = 1;
860
861                 if (arglist & CAM_ARG_VERBOSE) {
862                         cam_error_print(device, ccb, CAM_ESF_ALL,
863                                         CAM_EPF_ALL, stderr);
864                 }
865         }
866
867         cam_freeccb(ccb);
868
869         if (error != 0) {
870                 free(serial_buf);
871                 return(error);
872         }
873
874         bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
875         serial_num[serial_buf->length] = '\0';
876
877         if ((arglist & CAM_ARG_GET_STDINQ)
878          || (arglist & CAM_ARG_GET_XFERRATE))
879                 fprintf(stdout, "%s%d: Serial Number ",
880                         device->device_name, device->dev_unit_num);
881
882         fprintf(stdout, "%.60s\n", serial_num);
883
884         free(serial_buf);
885
886         return(0);
887 }
888
889 static int
890 camxferrate(struct cam_device *device)
891 {
892         struct ccb_pathinq cpi;
893         u_int32_t freq = 0;
894         u_int32_t speed = 0;
895         union ccb *ccb;
896         u_int mb;
897         int retval = 0;
898
899         if ((retval = get_cpi(device, &cpi)) != 0)
900                 return (1);
901
902         ccb = cam_getccb(device);
903
904         if (ccb == NULL) {
905                 warnx("couldn't allocate CCB");
906                 return(1);
907         }
908
909         bzero(&(&ccb->ccb_h)[1],
910               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
911
912         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
913         ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
914
915         if (((retval = cam_send_ccb(device, ccb)) < 0)
916          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
917                 const char error_string[] = "error getting transfer settings";
918
919                 if (retval < 0)
920                         warn(error_string);
921                 else
922                         warnx(error_string);
923
924                 if (arglist & CAM_ARG_VERBOSE)
925                         cam_error_print(device, ccb, CAM_ESF_ALL,
926                                         CAM_EPF_ALL, stderr);
927
928                 retval = 1;
929
930                 goto xferrate_bailout;
931
932         }
933
934         speed = cpi.base_transfer_speed;
935         freq = 0;
936         if (ccb->cts.transport == XPORT_SPI) {
937                 struct ccb_trans_settings_spi *spi =
938                     &ccb->cts.xport_specific.spi;
939
940                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
941                         freq = scsi_calc_syncsrate(spi->sync_period);
942                         speed = freq;
943                 }
944                 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
945                         speed *= (0x01 << spi->bus_width);
946                 }
947         } else if (ccb->cts.transport == XPORT_FC) {
948                 struct ccb_trans_settings_fc *fc =
949                     &ccb->cts.xport_specific.fc;
950
951                 if (fc->valid & CTS_FC_VALID_SPEED)
952                         speed = fc->bitrate;
953         } else if (ccb->cts.transport == XPORT_SAS) {
954                 struct ccb_trans_settings_sas *sas =
955                     &ccb->cts.xport_specific.sas;
956
957                 if (sas->valid & CTS_SAS_VALID_SPEED)
958                         speed = sas->bitrate;
959         } else if (ccb->cts.transport == XPORT_ATA) {
960                 struct ccb_trans_settings_pata *pata =
961                     &ccb->cts.xport_specific.ata;
962
963                 if (pata->valid & CTS_ATA_VALID_MODE)
964                         speed = ata_mode2speed(pata->mode);
965         } else if (ccb->cts.transport == XPORT_SATA) {
966                 struct  ccb_trans_settings_sata *sata =
967                     &ccb->cts.xport_specific.sata;
968
969                 if (sata->valid & CTS_SATA_VALID_REVISION)
970                         speed = ata_revision2speed(sata->revision);
971         }
972
973         mb = speed / 1000;
974         if (mb > 0) {
975                 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
976                         device->device_name, device->dev_unit_num,
977                         mb, speed % 1000);
978         } else {
979                 fprintf(stdout, "%s%d: %dKB/s transfers",
980                         device->device_name, device->dev_unit_num,
981                         speed);
982         }
983
984         if (ccb->cts.transport == XPORT_SPI) {
985                 struct ccb_trans_settings_spi *spi =
986                     &ccb->cts.xport_specific.spi;
987
988                 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
989                  && (spi->sync_offset != 0))
990                         fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
991                                 freq % 1000, spi->sync_offset);
992
993                 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
994                  && (spi->bus_width > 0)) {
995                         if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
996                          && (spi->sync_offset != 0)) {
997                                 fprintf(stdout, ", ");
998                         } else {
999                                 fprintf(stdout, " (");
1000                         }
1001                         fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1002                 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1003                  && (spi->sync_offset != 0)) {
1004                         fprintf(stdout, ")");
1005                 }
1006         } else if (ccb->cts.transport == XPORT_ATA) {
1007                 struct ccb_trans_settings_pata *pata =
1008                     &ccb->cts.xport_specific.ata;
1009
1010                 printf(" (");
1011                 if (pata->valid & CTS_ATA_VALID_MODE)
1012                         printf("%s, ", ata_mode2string(pata->mode));
1013                 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1014                         printf("ATAPI %dbytes, ", pata->atapi);
1015                 if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1016                         printf("PIO %dbytes", pata->bytecount);
1017                 printf(")");
1018         } else if (ccb->cts.transport == XPORT_SATA) {
1019                 struct ccb_trans_settings_sata *sata =
1020                     &ccb->cts.xport_specific.sata;
1021
1022                 printf(" (");
1023                 if (sata->valid & CTS_SATA_VALID_REVISION)
1024                         printf("SATA %d.x, ", sata->revision);
1025                 else
1026                         printf("SATA, ");
1027                 if (sata->valid & CTS_SATA_VALID_MODE)
1028                         printf("%s, ", ata_mode2string(sata->mode));
1029                 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1030                         printf("ATAPI %dbytes, ", sata->atapi);
1031                 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1032                         printf("PIO %dbytes", sata->bytecount);
1033                 printf(")");
1034         }
1035
1036         if (ccb->cts.protocol == PROTO_SCSI) {
1037                 struct ccb_trans_settings_scsi *scsi =
1038                     &ccb->cts.proto_specific.scsi;
1039                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1040                         if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1041                                 fprintf(stdout, ", Command Queueing Enabled");
1042                         }
1043                 }
1044         }
1045
1046         fprintf(stdout, "\n");
1047
1048 xferrate_bailout:
1049
1050         cam_freeccb(ccb);
1051
1052         return(retval);
1053 }
1054
1055 static void
1056 atacapprint(struct ata_params *parm)
1057 {
1058         u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1059                                 ((u_int32_t)parm->lba_size_2 << 16);
1060
1061         u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1062                                 ((u_int64_t)parm->lba_size48_2 << 16) |
1063                                 ((u_int64_t)parm->lba_size48_3 << 32) |
1064                                 ((u_int64_t)parm->lba_size48_4 << 48);
1065
1066         printf("\n");
1067         printf("protocol              ");
1068         printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1069         if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1070                 if (parm->satacapabilities & ATA_SATA_GEN3)
1071                         printf(" SATA 3.x\n");
1072                 else if (parm->satacapabilities & ATA_SATA_GEN2)
1073                         printf(" SATA 2.x\n");
1074                 else if (parm->satacapabilities & ATA_SATA_GEN1)
1075                         printf(" SATA 1.x\n");
1076                 else
1077                         printf(" SATA\n");
1078         }
1079         else
1080                 printf("\n");
1081         printf("device model          %.40s\n", parm->model);
1082         printf("firmware revision     %.8s\n", parm->revision);
1083         printf("serial number         %.20s\n", parm->serial);
1084         if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1085                 printf("WWN                   %04x%04x%04x%04x\n",
1086                     parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1087         }
1088         if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1089                 printf("media serial number   %.30s\n",
1090                     parm->media_serial);
1091         }
1092
1093         printf("cylinders             %d\n", parm->cylinders);
1094         printf("heads                 %d\n", parm->heads);
1095         printf("sectors/track         %d\n", parm->sectors);
1096         printf("sector size           logical %u, physical %lu, offset %lu\n",
1097             ata_logical_sector_size(parm),
1098             (unsigned long)ata_physical_sector_size(parm),
1099             (unsigned long)ata_logical_sector_offset(parm));
1100
1101         if (parm->config == ATA_PROTO_CFA ||
1102             (parm->support.command2 & ATA_SUPPORT_CFA))
1103                 printf("CFA supported\n");
1104
1105         printf("LBA%ssupported         ",
1106                 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1107         if (lbasize)
1108                 printf("%d sectors\n", lbasize);
1109         else
1110                 printf("\n");
1111
1112         printf("LBA48%ssupported       ",
1113                 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1114         if (lbasize48)
1115                 printf("%ju sectors\n", (uintmax_t)lbasize48);
1116         else
1117                 printf("\n");
1118
1119         printf("PIO supported         PIO");
1120         switch (ata_max_pmode(parm)) {
1121         case ATA_PIO4:
1122                 printf("4");
1123                 break;
1124         case ATA_PIO3:
1125                 printf("3");
1126                 break;
1127         case ATA_PIO2:
1128                 printf("2");
1129                 break;
1130         case ATA_PIO1:
1131                 printf("1");
1132                 break;
1133         default:
1134                 printf("0");
1135         }
1136         if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1137                 printf(" w/o IORDY");
1138         printf("\n");
1139
1140         printf("DMA%ssupported         ",
1141                 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1142         if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1143                 if (parm->mwdmamodes & 0xff) {
1144                         printf("WDMA");
1145                         if (parm->mwdmamodes & 0x04)
1146                                 printf("2");
1147                         else if (parm->mwdmamodes & 0x02)
1148                                 printf("1");
1149                         else if (parm->mwdmamodes & 0x01)
1150                                 printf("0");
1151                         printf(" ");
1152                 }
1153                 if ((parm->atavalid & ATA_FLAG_88) &&
1154                     (parm->udmamodes & 0xff)) {
1155                         printf("UDMA");
1156                         if (parm->udmamodes & 0x40)
1157                                 printf("6");
1158                         else if (parm->udmamodes & 0x20)
1159                                 printf("5");
1160                         else if (parm->udmamodes & 0x10)
1161                                 printf("4");
1162                         else if (parm->udmamodes & 0x08)
1163                                 printf("3");
1164                         else if (parm->udmamodes & 0x04)
1165                                 printf("2");
1166                         else if (parm->udmamodes & 0x02)
1167                                 printf("1");
1168                         else if (parm->udmamodes & 0x01)
1169                                 printf("0");
1170                         printf(" ");
1171                 }
1172         }
1173         printf("\n");
1174
1175         if (parm->media_rotation_rate == 1) {
1176                 printf("media RPM             non-rotating\n");
1177         } else if (parm->media_rotation_rate >= 0x0401 &&
1178             parm->media_rotation_rate <= 0xFFFE) {
1179                 printf("media RPM             %d\n",
1180                         parm->media_rotation_rate);
1181         }
1182
1183         printf("\nFeature                      "
1184                 "Support  Enabled   Value           Vendor\n");
1185         printf("read ahead                     %s       %s\n",
1186                 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1187                 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1188         printf("write cache                    %s       %s\n",
1189                 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1190                 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1191         printf("flush cache                    %s       %s\n",
1192                 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1193                 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1194         printf("overlap                        %s\n",
1195                 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1196         printf("Tagged Command Queuing (TCQ)   %s       %s",
1197                 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1198                 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1199                 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1200                         printf("        %d tags\n",
1201                             ATA_QUEUE_LEN(parm->queue) + 1);
1202                 } else
1203                         printf("\n");
1204         printf("Native Command Queuing (NCQ)   ");
1205         if (parm->satacapabilities != 0xffff &&
1206             (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1207                 printf("yes             %d tags\n",
1208                     ATA_QUEUE_LEN(parm->queue) + 1);
1209         } else
1210                 printf("no\n");
1211         printf("SMART                          %s       %s\n",
1212                 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1213                 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1214         printf("microcode download             %s       %s\n",
1215                 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1216                 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1217         printf("security                       %s       %s\n",
1218                 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1219                 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1220         printf("power management               %s       %s\n",
1221                 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1222                 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1223         printf("advanced power management      %s       %s",
1224                 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1225                 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1226                 if (parm->support.command2 & ATA_SUPPORT_APM) {
1227                         printf("        %d/0x%02X\n",
1228                             parm->apm_value, parm->apm_value);
1229                 } else
1230                         printf("\n");
1231         printf("automatic acoustic management  %s       %s",
1232                 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1233                 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1234                 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1235                         printf("        %d/0x%02X       %d/0x%02X\n",
1236                             ATA_ACOUSTIC_CURRENT(parm->acoustic),
1237                             ATA_ACOUSTIC_CURRENT(parm->acoustic),
1238                             ATA_ACOUSTIC_VENDOR(parm->acoustic),
1239                             ATA_ACOUSTIC_VENDOR(parm->acoustic));
1240                 } else
1241                         printf("\n");
1242         printf("media status notification      %s       %s\n",
1243                 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1244                 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1245         printf("power-up in Standby            %s       %s\n",
1246                 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1247                 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1248         printf("write-read-verify              %s       %s",
1249                 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1250                 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1251                 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1252                         printf("        %d/0x%x\n",
1253                             parm->wrv_mode, parm->wrv_mode);
1254                 } else
1255                         printf("\n");
1256         printf("unload                         %s       %s\n",
1257                 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1258                 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1259         printf("free-fall                      %s       %s\n",
1260                 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1261                 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1262         printf("data set management (TRIM)     %s\n",
1263                 parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1264 }
1265
1266 static int
1267 ataidentify(struct cam_device *device, int retry_count, int timeout)
1268 {
1269         union ccb *ccb;
1270         struct ata_params *ident_buf;
1271         struct ccb_getdev cgd;
1272         u_int i, error = 0;
1273         int16_t *ptr;
1274
1275         if (get_cgd(device, &cgd) != 0) {
1276                 warnx("couldn't get CGD");
1277                 return(1);
1278         }
1279         ccb = cam_getccb(device);
1280
1281         if (ccb == NULL) {
1282                 warnx("couldn't allocate CCB");
1283                 return(1);
1284         }
1285
1286         /* cam_getccb cleans up the header, caller has to zero the payload */
1287         bzero(&(&ccb->ccb_h)[1],
1288               sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1289
1290         ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1291
1292         if (ptr == NULL) {
1293                 cam_freeccb(ccb);
1294                 warnx("can't malloc memory for identify\n");
1295                 return(1);
1296         }
1297         bzero(ptr, sizeof(struct ata_params));
1298
1299         cam_fill_ataio(&ccb->ataio,
1300                       retry_count,
1301                       NULL,
1302                       /*flags*/CAM_DIR_IN,
1303                       MSG_SIMPLE_Q_TAG,
1304                       /*data_ptr*/(u_int8_t *)ptr,
1305                       /*dxfer_len*/sizeof(struct ata_params),
1306                       timeout ? timeout : 30 * 1000);
1307         if (cgd.protocol == PROTO_ATA)
1308                 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1309         else
1310                 ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1311
1312         /* Disable freezing the device queue */
1313         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1314
1315         if (arglist & CAM_ARG_ERR_RECOVER)
1316                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1317
1318         if (cam_send_ccb(device, ccb) < 0) {
1319                 perror("error sending ATA identify");
1320
1321                 if (arglist & CAM_ARG_VERBOSE) {
1322                         cam_error_print(device, ccb, CAM_ESF_ALL,
1323                                         CAM_EPF_ALL, stderr);
1324                 }
1325
1326                 free(ptr);
1327                 cam_freeccb(ccb);
1328                 return(1);
1329         }
1330
1331         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1332                 error = 1;
1333
1334                 if (arglist & CAM_ARG_VERBOSE) {
1335                         cam_error_print(device, ccb, CAM_ESF_ALL,
1336                                         CAM_EPF_ALL, stderr);
1337                 }
1338         }
1339
1340         cam_freeccb(ccb);
1341
1342         if (error != 0) {
1343                 free(ptr);
1344                 return(error);
1345         }
1346
1347         for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1348                 ptr[i] = le16toh(ptr[i]);
1349         if (arglist & CAM_ARG_VERBOSE) {
1350                 fprintf(stdout, "%s%d: Raw identify data:\n",
1351                     device->device_name, device->dev_unit_num);
1352                 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1353                         if ((i % 8) == 0)
1354                             fprintf(stdout, " %3d: ", i);
1355                         fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1356                         if ((i % 8) == 7)
1357                             fprintf(stdout, "\n");
1358                 }
1359         }
1360         ident_buf = (struct ata_params *)ptr;
1361         if (strncmp(ident_buf->model, "FX", 2) &&
1362             strncmp(ident_buf->model, "NEC", 3) &&
1363             strncmp(ident_buf->model, "Pioneer", 7) &&
1364             strncmp(ident_buf->model, "SHARP", 5)) {
1365                 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1366                 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1367                 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1368                 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1369         }
1370         ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1371         ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1372         ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1373         ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1374         ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1375         ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1376         ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1377         ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1378             sizeof(ident_buf->media_serial));
1379
1380         fprintf(stdout, "%s%d: ", device->device_name,
1381                 device->dev_unit_num);
1382         ata_print_ident(ident_buf);
1383         camxferrate(device);
1384         atacapprint(ident_buf);
1385
1386         free(ident_buf);
1387
1388         return(0);
1389 }
1390 #endif /* MINIMALISTIC */
1391
1392 /*
1393  * Parse out a bus, or a bus, target and lun in the following
1394  * format:
1395  * bus
1396  * bus:target
1397  * bus:target:lun
1398  *
1399  * Returns the number of parsed components, or 0.
1400  */
1401 static int
1402 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1403 {
1404         char *tmpstr;
1405         int convs = 0;
1406
1407         while (isspace(*tstr) && (*tstr != '\0'))
1408                 tstr++;
1409
1410         tmpstr = (char *)strtok(tstr, ":");
1411         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1412                 *bus = strtol(tmpstr, NULL, 0);
1413                 *arglst |= CAM_ARG_BUS;
1414                 convs++;
1415                 tmpstr = (char *)strtok(NULL, ":");
1416                 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1417                         *target = strtol(tmpstr, NULL, 0);
1418                         *arglst |= CAM_ARG_TARGET;
1419                         convs++;
1420                         tmpstr = (char *)strtok(NULL, ":");
1421                         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1422                                 *lun = strtol(tmpstr, NULL, 0);
1423                                 *arglst |= CAM_ARG_LUN;
1424                                 convs++;
1425                         }
1426                 }
1427         }
1428
1429         return convs;
1430 }
1431
1432 static int
1433 dorescan_or_reset(int argc, char **argv, int rescan)
1434 {
1435         static const char must[] =
1436                 "you must specify \"all\", a bus, or a bus:target:lun to %s";
1437         int rv, error = 0;
1438         int bus = -1, target = -1, lun = -1;
1439         char *tstr;
1440
1441         if (argc < 3) {
1442                 warnx(must, rescan? "rescan" : "reset");
1443                 return(1);
1444         }
1445
1446         tstr = argv[optind];
1447         while (isspace(*tstr) && (*tstr != '\0'))
1448                 tstr++;
1449         if (strncasecmp(tstr, "all", strlen("all")) == 0)
1450                 arglist |= CAM_ARG_BUS;
1451         else {
1452                 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1453                 if (rv != 1 && rv != 3) {
1454                         warnx(must, rescan? "rescan" : "reset");
1455                         return(1);
1456                 }
1457         }
1458
1459         if ((arglist & CAM_ARG_BUS)
1460             && (arglist & CAM_ARG_TARGET)
1461             && (arglist & CAM_ARG_LUN))
1462                 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1463         else
1464                 error = rescan_or_reset_bus(bus, rescan);
1465
1466         return(error);
1467 }
1468
1469 static int
1470 rescan_or_reset_bus(int bus, int rescan)
1471 {
1472         union ccb ccb, matchccb;
1473         int fd, retval;
1474         int bufsize;
1475
1476         retval = 0;
1477
1478         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1479                 warnx("error opening transport layer device %s", XPT_DEVICE);
1480                 warn("%s", XPT_DEVICE);
1481                 return(1);
1482         }
1483
1484         if (bus != -1) {
1485                 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1486                 ccb.ccb_h.path_id = bus;
1487                 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1488                 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1489                 ccb.crcn.flags = CAM_FLAG_NONE;
1490
1491                 /* run this at a low priority */
1492                 ccb.ccb_h.pinfo.priority = 5;
1493
1494                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1495                         warn("CAMIOCOMMAND ioctl failed");
1496                         close(fd);
1497                         return(1);
1498                 }
1499
1500                 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1501                         fprintf(stdout, "%s of bus %d was successful\n",
1502                             rescan ? "Re-scan" : "Reset", bus);
1503                 } else {
1504                         fprintf(stdout, "%s of bus %d returned error %#x\n",
1505                                 rescan ? "Re-scan" : "Reset", bus,
1506                                 ccb.ccb_h.status & CAM_STATUS_MASK);
1507                         retval = 1;
1508                 }
1509
1510                 close(fd);
1511                 return(retval);
1512
1513         }
1514
1515
1516         /*
1517          * The right way to handle this is to modify the xpt so that it can
1518          * handle a wildcarded bus in a rescan or reset CCB.  At the moment
1519          * that isn't implemented, so instead we enumerate the busses and
1520          * send the rescan or reset to those busses in the case where the
1521          * given bus is -1 (wildcard).  We don't send a rescan or reset
1522          * to the xpt bus; sending a rescan to the xpt bus is effectively a
1523          * no-op, sending a rescan to the xpt bus would result in a status of
1524          * CAM_REQ_INVALID.
1525          */
1526         bzero(&(&matchccb.ccb_h)[1],
1527               sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1528         matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1529         matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
1530         bufsize = sizeof(struct dev_match_result) * 20;
1531         matchccb.cdm.match_buf_len = bufsize;
1532         matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1533         if (matchccb.cdm.matches == NULL) {
1534                 warnx("can't malloc memory for matches");
1535                 retval = 1;
1536                 goto bailout;
1537         }
1538         matchccb.cdm.num_matches = 0;
1539
1540         matchccb.cdm.num_patterns = 1;
1541         matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1542
1543         matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1544                 matchccb.cdm.pattern_buf_len);
1545         if (matchccb.cdm.patterns == NULL) {
1546                 warnx("can't malloc memory for patterns");
1547                 retval = 1;
1548                 goto bailout;
1549         }
1550         matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1551         matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1552
1553         do {
1554                 unsigned int i;
1555
1556                 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1557                         warn("CAMIOCOMMAND ioctl failed");
1558                         retval = 1;
1559                         goto bailout;
1560                 }
1561
1562                 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1563                  || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1564                    && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1565                         warnx("got CAM error %#x, CDM error %d\n",
1566                               matchccb.ccb_h.status, matchccb.cdm.status);
1567                         retval = 1;
1568                         goto bailout;
1569                 }
1570
1571                 for (i = 0; i < matchccb.cdm.num_matches; i++) {
1572                         struct bus_match_result *bus_result;
1573
1574                         /* This shouldn't happen. */
1575                         if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1576                                 continue;
1577
1578                         bus_result = &matchccb.cdm.matches[i].result.bus_result;
1579
1580                         /*
1581                          * We don't want to rescan or reset the xpt bus.
1582                          * See above.
1583                          */
1584                         if ((int)bus_result->path_id == -1)
1585                                 continue;
1586
1587                         ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1588                                                        XPT_RESET_BUS;
1589                         ccb.ccb_h.path_id = bus_result->path_id;
1590                         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1591                         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1592                         ccb.crcn.flags = CAM_FLAG_NONE;
1593
1594                         /* run this at a low priority */
1595                         ccb.ccb_h.pinfo.priority = 5;
1596
1597                         if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1598                                 warn("CAMIOCOMMAND ioctl failed");
1599                                 retval = 1;
1600                                 goto bailout;
1601                         }
1602
1603                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1604                                 fprintf(stdout, "%s of bus %d was successful\n",
1605                                         rescan? "Re-scan" : "Reset",
1606                                         bus_result->path_id);
1607                         } else {
1608                                 /*
1609                                  * Don't bail out just yet, maybe the other
1610                                  * rescan or reset commands will complete
1611                                  * successfully.
1612                                  */
1613                                 fprintf(stderr, "%s of bus %d returned error "
1614                                         "%#x\n", rescan? "Re-scan" : "Reset",
1615                                         bus_result->path_id,
1616                                         ccb.ccb_h.status & CAM_STATUS_MASK);
1617                                 retval = 1;
1618                         }
1619                 }
1620         } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1621                  && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1622
1623 bailout:
1624
1625         if (fd != -1)
1626                 close(fd);
1627
1628         if (matchccb.cdm.patterns != NULL)
1629                 free(matchccb.cdm.patterns);
1630         if (matchccb.cdm.matches != NULL)
1631                 free(matchccb.cdm.matches);
1632
1633         return(retval);
1634 }
1635
1636 static int
1637 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1638 {
1639         union ccb ccb;
1640         struct cam_device *device;
1641         int fd;
1642
1643         device = NULL;
1644
1645         if (bus < 0) {
1646                 warnx("invalid bus number %d", bus);
1647                 return(1);
1648         }
1649
1650         if (target < 0) {
1651                 warnx("invalid target number %d", target);
1652                 return(1);
1653         }
1654
1655         if (lun < 0) {
1656                 warnx("invalid lun number %d", lun);
1657                 return(1);
1658         }
1659
1660         fd = -1;
1661
1662         bzero(&ccb, sizeof(union ccb));
1663
1664         if (scan) {
1665                 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1666                         warnx("error opening transport layer device %s\n",
1667                             XPT_DEVICE);
1668                         warn("%s", XPT_DEVICE);
1669                         return(1);
1670                 }
1671         } else {
1672                 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1673                 if (device == NULL) {
1674                         warnx("%s", cam_errbuf);
1675                         return(1);
1676                 }
1677         }
1678
1679         ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1680         ccb.ccb_h.path_id = bus;
1681         ccb.ccb_h.target_id = target;
1682         ccb.ccb_h.target_lun = lun;
1683         ccb.ccb_h.timeout = 5000;
1684         ccb.crcn.flags = CAM_FLAG_NONE;
1685
1686         /* run this at a low priority */
1687         ccb.ccb_h.pinfo.priority = 5;
1688
1689         if (scan) {
1690                 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1691                         warn("CAMIOCOMMAND ioctl failed");
1692                         close(fd);
1693                         return(1);
1694                 }
1695         } else {
1696                 if (cam_send_ccb(device, &ccb) < 0) {
1697                         warn("error sending XPT_RESET_DEV CCB");
1698                         cam_close_device(device);
1699                         return(1);
1700                 }
1701         }
1702
1703         if (scan)
1704                 close(fd);
1705         else
1706                 cam_close_device(device);
1707
1708         /*
1709          * An error code of CAM_BDR_SENT is normal for a BDR request.
1710          */
1711         if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1712          || ((!scan)
1713           && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1714                 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1715                     scan? "Re-scan" : "Reset", bus, target, lun);
1716                 return(0);
1717         } else {
1718                 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1719                     scan? "Re-scan" : "Reset", bus, target, lun,
1720                     ccb.ccb_h.status & CAM_STATUS_MASK);
1721                 return(1);
1722         }
1723 }
1724
1725 #ifndef MINIMALISTIC
1726 static int
1727 readdefects(struct cam_device *device, int argc, char **argv,
1728             char *combinedopt, int retry_count, int timeout)
1729 {
1730         union ccb *ccb = NULL;
1731         struct scsi_read_defect_data_10 *rdd_cdb;
1732         u_int8_t *defect_list = NULL;
1733         u_int32_t dlist_length = 65000;
1734         u_int32_t returned_length = 0;
1735         u_int32_t num_returned = 0;
1736         u_int8_t returned_format;
1737         unsigned int i;
1738         int c, error = 0;
1739         int lists_specified = 0;
1740
1741         while ((c = getopt(argc, argv, combinedopt)) != -1) {
1742                 switch(c){
1743                 case 'f':
1744                 {
1745                         char *tstr;
1746                         tstr = optarg;
1747                         while (isspace(*tstr) && (*tstr != '\0'))
1748                                 tstr++;
1749                         if (strcmp(tstr, "block") == 0)
1750                                 arglist |= CAM_ARG_FORMAT_BLOCK;
1751                         else if (strcmp(tstr, "bfi") == 0)
1752                                 arglist |= CAM_ARG_FORMAT_BFI;
1753                         else if (strcmp(tstr, "phys") == 0)
1754                                 arglist |= CAM_ARG_FORMAT_PHYS;
1755                         else {
1756                                 error = 1;
1757                                 warnx("invalid defect format %s", tstr);
1758                                 goto defect_bailout;
1759                         }
1760                         break;
1761                 }
1762                 case 'G':
1763                         arglist |= CAM_ARG_GLIST;
1764                         break;
1765                 case 'P':
1766                         arglist |= CAM_ARG_PLIST;
1767                         break;
1768                 default:
1769                         break;
1770                 }
1771         }
1772
1773         ccb = cam_getccb(device);
1774
1775         /*
1776          * Hopefully 65000 bytes is enough to hold the defect list.  If it
1777          * isn't, the disk is probably dead already.  We'd have to go with
1778          * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1779          * to hold them all.
1780          */
1781         defect_list = malloc(dlist_length);
1782         if (defect_list == NULL) {
1783                 warnx("can't malloc memory for defect list");
1784                 error = 1;
1785                 goto defect_bailout;
1786         }
1787
1788         rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1789
1790         /*
1791          * cam_getccb() zeros the CCB header only.  So we need to zero the
1792          * payload portion of the ccb.
1793          */
1794         bzero(&(&ccb->ccb_h)[1],
1795               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1796
1797         cam_fill_csio(&ccb->csio,
1798                       /*retries*/ retry_count,
1799                       /*cbfcnp*/ NULL,
1800                       /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1801                                               CAM_PASS_ERR_RECOVER : 0),
1802                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
1803                       /*data_ptr*/ defect_list,
1804                       /*dxfer_len*/ dlist_length,
1805                       /*sense_len*/ SSD_FULL_SIZE,
1806                       /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1807                       /*timeout*/ timeout ? timeout : 5000);
1808
1809         rdd_cdb->opcode = READ_DEFECT_DATA_10;
1810         if (arglist & CAM_ARG_FORMAT_BLOCK)
1811                 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1812         else if (arglist & CAM_ARG_FORMAT_BFI)
1813                 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1814         else if (arglist & CAM_ARG_FORMAT_PHYS)
1815                 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1816         else {
1817                 error = 1;
1818                 warnx("no defect list format specified");
1819                 goto defect_bailout;
1820         }
1821         if (arglist & CAM_ARG_PLIST) {
1822                 rdd_cdb->format |= SRDD10_PLIST;
1823                 lists_specified++;
1824         }
1825
1826         if (arglist & CAM_ARG_GLIST) {
1827                 rdd_cdb->format |= SRDD10_GLIST;
1828                 lists_specified++;
1829         }
1830
1831         scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1832
1833         /* Disable freezing the device queue */
1834         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1835
1836         if (cam_send_ccb(device, ccb) < 0) {
1837                 perror("error reading defect list");
1838
1839                 if (arglist & CAM_ARG_VERBOSE) {
1840                         cam_error_print(device, ccb, CAM_ESF_ALL,
1841                                         CAM_EPF_ALL, stderr);
1842                 }
1843
1844                 error = 1;
1845                 goto defect_bailout;
1846         }
1847
1848         returned_length = scsi_2btoul(((struct
1849                 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1850
1851         returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1852                         defect_list)->format;
1853
1854         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1855          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1856          && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1857                 struct scsi_sense_data *sense;
1858                 int error_code, sense_key, asc, ascq;
1859
1860                 sense = &ccb->csio.sense_data;
1861                 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1862
1863                 /*
1864                  * According to the SCSI spec, if the disk doesn't support
1865                  * the requested format, it will generally return a sense
1866                  * key of RECOVERED ERROR, and an additional sense code
1867                  * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1868                  * also check to make sure that the returned length is
1869                  * greater than 0, and then print out whatever format the
1870                  * disk gave us.
1871                  */
1872                 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1873                  && (asc == 0x1c) && (ascq == 0x00)
1874                  && (returned_length > 0)) {
1875                         warnx("requested defect format not available");
1876                         switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1877                         case SRDD10_BLOCK_FORMAT:
1878                                 warnx("Device returned block format");
1879                                 break;
1880                         case SRDD10_BYTES_FROM_INDEX_FORMAT:
1881                                 warnx("Device returned bytes from index"
1882                                       " format");
1883                                 break;
1884                         case SRDD10_PHYSICAL_SECTOR_FORMAT:
1885                                 warnx("Device returned physical sector format");
1886                                 break;
1887                         default:
1888                                 error = 1;
1889                                 warnx("Device returned unknown defect"
1890                                      " data format %#x", returned_format);
1891                                 goto defect_bailout;
1892                                 break; /* NOTREACHED */
1893                         }
1894                 } else {
1895                         error = 1;
1896                         warnx("Error returned from read defect data command");
1897                         if (arglist & CAM_ARG_VERBOSE)
1898                                 cam_error_print(device, ccb, CAM_ESF_ALL,
1899                                                 CAM_EPF_ALL, stderr);
1900                         goto defect_bailout;
1901                 }
1902         } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1903                 error = 1;
1904                 warnx("Error returned from read defect data command");
1905                 if (arglist & CAM_ARG_VERBOSE)
1906                         cam_error_print(device, ccb, CAM_ESF_ALL,
1907                                         CAM_EPF_ALL, stderr);
1908                 goto defect_bailout;
1909         }
1910
1911         /*
1912          * XXX KDM  I should probably clean up the printout format for the
1913          * disk defects.
1914          */
1915         switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1916                 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1917                 {
1918                         struct scsi_defect_desc_phys_sector *dlist;
1919
1920                         dlist = (struct scsi_defect_desc_phys_sector *)
1921                                 (defect_list +
1922                                 sizeof(struct scsi_read_defect_data_hdr_10));
1923
1924                         num_returned = returned_length /
1925                                 sizeof(struct scsi_defect_desc_phys_sector);
1926
1927                         fprintf(stderr, "Got %d defect", num_returned);
1928
1929                         if ((lists_specified == 0) || (num_returned == 0)) {
1930                                 fprintf(stderr, "s.\n");
1931                                 break;
1932                         } else if (num_returned == 1)
1933                                 fprintf(stderr, ":\n");
1934                         else
1935                                 fprintf(stderr, "s:\n");
1936
1937                         for (i = 0; i < num_returned; i++) {
1938                                 fprintf(stdout, "%d:%d:%d\n",
1939                                         scsi_3btoul(dlist[i].cylinder),
1940                                         dlist[i].head,
1941                                         scsi_4btoul(dlist[i].sector));
1942                         }
1943                         break;
1944                 }
1945                 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1946                 {
1947                         struct scsi_defect_desc_bytes_from_index *dlist;
1948
1949                         dlist = (struct scsi_defect_desc_bytes_from_index *)
1950                                 (defect_list +
1951                                 sizeof(struct scsi_read_defect_data_hdr_10));
1952
1953                         num_returned = returned_length /
1954                               sizeof(struct scsi_defect_desc_bytes_from_index);
1955
1956                         fprintf(stderr, "Got %d defect", num_returned);
1957
1958                         if ((lists_specified == 0) || (num_returned == 0)) {
1959                                 fprintf(stderr, "s.\n");
1960                                 break;
1961                         } else if (num_returned == 1)
1962                                 fprintf(stderr, ":\n");
1963                         else
1964                                 fprintf(stderr, "s:\n");
1965
1966                         for (i = 0; i < num_returned; i++) {
1967                                 fprintf(stdout, "%d:%d:%d\n",
1968                                         scsi_3btoul(dlist[i].cylinder),
1969                                         dlist[i].head,
1970                                         scsi_4btoul(dlist[i].bytes_from_index));
1971                         }
1972                         break;
1973                 }
1974                 case SRDDH10_BLOCK_FORMAT:
1975                 {
1976                         struct scsi_defect_desc_block *dlist;
1977
1978                         dlist = (struct scsi_defect_desc_block *)(defect_list +
1979                                 sizeof(struct scsi_read_defect_data_hdr_10));
1980
1981                         num_returned = returned_length /
1982                               sizeof(struct scsi_defect_desc_block);
1983
1984                         fprintf(stderr, "Got %d defect", num_returned);
1985
1986                         if ((lists_specified == 0) || (num_returned == 0)) {
1987                                 fprintf(stderr, "s.\n");
1988                                 break;
1989                         } else if (num_returned == 1)
1990                                 fprintf(stderr, ":\n");
1991                         else
1992                                 fprintf(stderr, "s:\n");
1993
1994                         for (i = 0; i < num_returned; i++)
1995                                 fprintf(stdout, "%u\n",
1996                                         scsi_4btoul(dlist[i].address));
1997                         break;
1998                 }
1999                 default:
2000                         fprintf(stderr, "Unknown defect format %d\n",
2001                                 returned_format & SRDDH10_DLIST_FORMAT_MASK);
2002                         error = 1;
2003                         break;
2004         }
2005 defect_bailout:
2006
2007         if (defect_list != NULL)
2008                 free(defect_list);
2009
2010         if (ccb != NULL)
2011                 cam_freeccb(ccb);
2012
2013         return(error);
2014 }
2015 #endif /* MINIMALISTIC */
2016
2017 #if 0
2018 void
2019 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2020 {
2021         union ccb *ccb;
2022
2023         ccb = cam_getccb(device);
2024
2025         cam_freeccb(ccb);
2026 }
2027 #endif
2028
2029 #ifndef MINIMALISTIC
2030 void
2031 mode_sense(struct cam_device *device, int mode_page, int page_control,
2032            int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2033 {
2034         union ccb *ccb;
2035         int retval;
2036
2037         ccb = cam_getccb(device);
2038
2039         if (ccb == NULL)
2040                 errx(1, "mode_sense: couldn't allocate CCB");
2041
2042         bzero(&(&ccb->ccb_h)[1],
2043               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2044
2045         scsi_mode_sense(&ccb->csio,
2046                         /* retries */ retry_count,
2047                         /* cbfcnp */ NULL,
2048                         /* tag_action */ MSG_SIMPLE_Q_TAG,
2049                         /* dbd */ dbd,
2050                         /* page_code */ page_control << 6,
2051                         /* page */ mode_page,
2052                         /* param_buf */ data,
2053                         /* param_len */ datalen,
2054                         /* sense_len */ SSD_FULL_SIZE,
2055                         /* timeout */ timeout ? timeout : 5000);
2056
2057         if (arglist & CAM_ARG_ERR_RECOVER)
2058                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2059
2060         /* Disable freezing the device queue */
2061         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2062
2063         if (((retval = cam_send_ccb(device, ccb)) < 0)
2064          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2065                 if (arglist & CAM_ARG_VERBOSE) {
2066                         cam_error_print(device, ccb, CAM_ESF_ALL,
2067                                         CAM_EPF_ALL, stderr);
2068                 }
2069                 cam_freeccb(ccb);
2070                 cam_close_device(device);
2071                 if (retval < 0)
2072                         err(1, "error sending mode sense command");
2073                 else
2074                         errx(1, "error sending mode sense command");
2075         }
2076
2077         cam_freeccb(ccb);
2078 }
2079
2080 void
2081 mode_select(struct cam_device *device, int save_pages, int retry_count,
2082            int timeout, u_int8_t *data, int datalen)
2083 {
2084         union ccb *ccb;
2085         int retval;
2086
2087         ccb = cam_getccb(device);
2088
2089         if (ccb == NULL)
2090                 errx(1, "mode_select: couldn't allocate CCB");
2091
2092         bzero(&(&ccb->ccb_h)[1],
2093               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2094
2095         scsi_mode_select(&ccb->csio,
2096                          /* retries */ retry_count,
2097                          /* cbfcnp */ NULL,
2098                          /* tag_action */ MSG_SIMPLE_Q_TAG,
2099                          /* scsi_page_fmt */ 1,
2100                          /* save_pages */ save_pages,
2101                          /* param_buf */ data,
2102                          /* param_len */ datalen,
2103                          /* sense_len */ SSD_FULL_SIZE,
2104                          /* timeout */ timeout ? timeout : 5000);
2105
2106         if (arglist & CAM_ARG_ERR_RECOVER)
2107                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2108
2109         /* Disable freezing the device queue */
2110         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2111
2112         if (((retval = cam_send_ccb(device, ccb)) < 0)
2113          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2114                 if (arglist & CAM_ARG_VERBOSE) {
2115                         cam_error_print(device, ccb, CAM_ESF_ALL,
2116                                         CAM_EPF_ALL, stderr);
2117                 }
2118                 cam_freeccb(ccb);
2119                 cam_close_device(device);
2120
2121                 if (retval < 0)
2122                         err(1, "error sending mode select command");
2123                 else
2124                         errx(1, "error sending mode select command");
2125
2126         }
2127
2128         cam_freeccb(ccb);
2129 }
2130
2131 void
2132 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2133          int retry_count, int timeout)
2134 {
2135         int c, mode_page = -1, page_control = 0;
2136         int binary = 0, list = 0;
2137
2138         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2139                 switch(c) {
2140                 case 'b':
2141                         binary = 1;
2142                         break;
2143                 case 'd':
2144                         arglist |= CAM_ARG_DBD;
2145                         break;
2146                 case 'e':
2147                         arglist |= CAM_ARG_MODE_EDIT;
2148                         break;
2149                 case 'l':
2150                         list = 1;
2151                         break;
2152                 case 'm':
2153                         mode_page = strtol(optarg, NULL, 0);
2154                         if (mode_page < 0)
2155                                 errx(1, "invalid mode page %d", mode_page);
2156                         break;
2157                 case 'P':
2158                         page_control = strtol(optarg, NULL, 0);
2159                         if ((page_control < 0) || (page_control > 3))
2160                                 errx(1, "invalid page control field %d",
2161                                      page_control);
2162                         arglist |= CAM_ARG_PAGE_CNTL;
2163                         break;
2164                 default:
2165                         break;
2166                 }
2167         }
2168
2169         if (mode_page == -1 && list == 0)
2170                 errx(1, "you must specify a mode page!");
2171
2172         if (list) {
2173                 mode_list(device, page_control, arglist & CAM_ARG_DBD,
2174                     retry_count, timeout);
2175         } else {
2176                 mode_edit(device, mode_page, page_control,
2177                     arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2178                     retry_count, timeout);
2179         }
2180 }
2181
2182 static int
2183 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2184         int retry_count, int timeout)
2185 {
2186         union ccb *ccb;
2187         u_int32_t flags = CAM_DIR_NONE;
2188         u_int8_t *data_ptr = NULL;
2189         u_int8_t cdb[20];
2190         u_int8_t atacmd[12];
2191         struct get_hook hook;
2192         int c, data_bytes = 0;
2193         int cdb_len = 0;
2194         int atacmd_len = 0;
2195         int dmacmd = 0;
2196         int fpdmacmd = 0;
2197         int need_res = 0;
2198         char *datastr = NULL, *tstr, *resstr = NULL;
2199         int error = 0;
2200         int fd_data = 0, fd_res = 0;
2201         int retval;
2202
2203         ccb = cam_getccb(device);
2204
2205         if (ccb == NULL) {
2206                 warnx("scsicmd: error allocating ccb");
2207                 return(1);
2208         }
2209
2210         bzero(&(&ccb->ccb_h)[1],
2211               sizeof(union ccb) - sizeof(struct ccb_hdr));
2212
2213         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2214                 switch(c) {
2215                 case 'a':
2216                         tstr = optarg;
2217                         while (isspace(*tstr) && (*tstr != '\0'))
2218                                 tstr++;
2219                         hook.argc = argc - optind;
2220                         hook.argv = argv + optind;
2221                         hook.got = 0;
2222                         atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2223                                                     iget, &hook);
2224                         /*
2225                          * Increment optind by the number of arguments the
2226                          * encoding routine processed.  After each call to
2227                          * getopt(3), optind points to the argument that
2228                          * getopt should process _next_.  In this case,
2229                          * that means it points to the first command string
2230                          * argument, if there is one.  Once we increment
2231                          * this, it should point to either the next command
2232                          * line argument, or it should be past the end of
2233                          * the list.
2234                          */
2235                         optind += hook.got;
2236                         break;
2237                 case 'c':
2238                         tstr = optarg;
2239                         while (isspace(*tstr) && (*tstr != '\0'))
2240                                 tstr++;
2241                         hook.argc = argc - optind;
2242                         hook.argv = argv + optind;
2243                         hook.got = 0;
2244                         cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2245                                                     iget, &hook);
2246                         /*
2247                          * Increment optind by the number of arguments the
2248                          * encoding routine processed.  After each call to
2249                          * getopt(3), optind points to the argument that
2250                          * getopt should process _next_.  In this case,
2251                          * that means it points to the first command string
2252                          * argument, if there is one.  Once we increment
2253                          * this, it should point to either the next command
2254                          * line argument, or it should be past the end of
2255                          * the list.
2256                          */
2257                         optind += hook.got;
2258                         break;
2259                 case 'd':
2260                         dmacmd = 1;
2261                         break;
2262                 case 'f':
2263                         fpdmacmd = 1;
2264                         break;
2265                 case 'i':
2266                         if (arglist & CAM_ARG_CMD_OUT) {
2267                                 warnx("command must either be "
2268                                       "read or write, not both");
2269                                 error = 1;
2270                                 goto scsicmd_bailout;
2271                         }
2272                         arglist |= CAM_ARG_CMD_IN;
2273                         flags = CAM_DIR_IN;
2274                         data_bytes = strtol(optarg, NULL, 0);
2275                         if (data_bytes <= 0) {
2276                                 warnx("invalid number of input bytes %d",
2277                                       data_bytes);
2278                                 error = 1;
2279                                 goto scsicmd_bailout;
2280                         }
2281                         hook.argc = argc - optind;
2282                         hook.argv = argv + optind;
2283                         hook.got = 0;
2284                         optind++;
2285                         datastr = cget(&hook, NULL);
2286                         /*
2287                          * If the user supplied "-" instead of a format, he
2288                          * wants the data to be written to stdout.
2289                          */
2290                         if ((datastr != NULL)
2291                          && (datastr[0] == '-'))
2292                                 fd_data = 1;
2293
2294                         data_ptr = (u_int8_t *)malloc(data_bytes);
2295                         if (data_ptr == NULL) {
2296                                 warnx("can't malloc memory for data_ptr");
2297                                 error = 1;
2298                                 goto scsicmd_bailout;
2299                         }
2300                         break;
2301                 case 'o':
2302                         if (arglist & CAM_ARG_CMD_IN) {
2303                                 warnx("command must either be "
2304                                       "read or write, not both");
2305                                 error = 1;
2306                                 goto scsicmd_bailout;
2307                         }
2308                         arglist |= CAM_ARG_CMD_OUT;
2309                         flags = CAM_DIR_OUT;
2310                         data_bytes = strtol(optarg, NULL, 0);
2311                         if (data_bytes <= 0) {
2312                                 warnx("invalid number of output bytes %d",
2313                                       data_bytes);
2314                                 error = 1;
2315                                 goto scsicmd_bailout;
2316                         }
2317                         hook.argc = argc - optind;
2318                         hook.argv = argv + optind;
2319                         hook.got = 0;
2320                         datastr = cget(&hook, NULL);
2321                         data_ptr = (u_int8_t *)malloc(data_bytes);
2322                         if (data_ptr == NULL) {
2323                                 warnx("can't malloc memory for data_ptr");
2324                                 error = 1;
2325                                 goto scsicmd_bailout;
2326                         }
2327                         bzero(data_ptr, data_bytes);
2328                         /*
2329                          * If the user supplied "-" instead of a format, he
2330                          * wants the data to be read from stdin.
2331                          */
2332                         if ((datastr != NULL)
2333                          && (datastr[0] == '-'))
2334                                 fd_data = 1;
2335                         else
2336                                 buff_encode_visit(data_ptr, data_bytes, datastr,
2337                                                   iget, &hook);
2338                         optind += hook.got;
2339                         break;
2340                 case 'r':
2341                         need_res = 1;
2342                         hook.argc = argc - optind;
2343                         hook.argv = argv + optind;
2344                         hook.got = 0;
2345                         resstr = cget(&hook, NULL);
2346                         if ((resstr != NULL) && (resstr[0] == '-'))
2347                                 fd_res = 1;
2348                         optind += hook.got;
2349                         break;
2350                 default:
2351                         break;
2352                 }
2353         }
2354
2355         /*
2356          * If fd_data is set, and we're writing to the device, we need to
2357          * read the data the user wants written from stdin.
2358          */
2359         if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2360                 ssize_t amt_read;
2361                 int amt_to_read = data_bytes;
2362                 u_int8_t *buf_ptr = data_ptr;
2363
2364                 for (amt_read = 0; amt_to_read > 0;
2365                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2366                         if (amt_read == -1) {
2367                                 warn("error reading data from stdin");
2368                                 error = 1;
2369                                 goto scsicmd_bailout;
2370                         }
2371                         amt_to_read -= amt_read;
2372                         buf_ptr += amt_read;
2373                 }
2374         }
2375
2376         if (arglist & CAM_ARG_ERR_RECOVER)
2377                 flags |= CAM_PASS_ERR_RECOVER;
2378
2379         /* Disable freezing the device queue */
2380         flags |= CAM_DEV_QFRZDIS;
2381
2382         if (cdb_len) {
2383                 /*
2384                  * This is taken from the SCSI-3 draft spec.
2385                  * (T10/1157D revision 0.3)
2386                  * The top 3 bits of an opcode are the group code.
2387                  * The next 5 bits are the command code.
2388                  * Group 0:  six byte commands
2389                  * Group 1:  ten byte commands
2390                  * Group 2:  ten byte commands
2391                  * Group 3:  reserved
2392                  * Group 4:  sixteen byte commands
2393                  * Group 5:  twelve byte commands
2394                  * Group 6:  vendor specific
2395                  * Group 7:  vendor specific
2396                  */
2397                 switch((cdb[0] >> 5) & 0x7) {
2398                         case 0:
2399                                 cdb_len = 6;
2400                                 break;
2401                         case 1:
2402                         case 2:
2403                                 cdb_len = 10;
2404                                 break;
2405                         case 3:
2406                         case 6:
2407                         case 7:
2408                                 /* computed by buff_encode_visit */
2409                                 break;
2410                         case 4:
2411                                 cdb_len = 16;
2412                                 break;
2413                         case 5:
2414                                 cdb_len = 12;
2415                                 break;
2416                 }
2417
2418                 /*
2419                  * We should probably use csio_build_visit or something like that
2420                  * here, but it's easier to encode arguments as you go.  The
2421                  * alternative would be skipping the CDB argument and then encoding
2422                  * it here, since we've got the data buffer argument by now.
2423                  */
2424                 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2425
2426                 cam_fill_csio(&ccb->csio,
2427                       /*retries*/ retry_count,
2428                       /*cbfcnp*/ NULL,
2429                       /*flags*/ flags,
2430                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
2431                       /*data_ptr*/ data_ptr,
2432                       /*dxfer_len*/ data_bytes,
2433                       /*sense_len*/ SSD_FULL_SIZE,
2434                       /*cdb_len*/ cdb_len,
2435                       /*timeout*/ timeout ? timeout : 5000);
2436         } else {
2437                 atacmd_len = 12;
2438                 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2439                 if (need_res)
2440                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2441                 if (dmacmd)
2442                         ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2443                 if (fpdmacmd)
2444                         ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2445
2446                 cam_fill_ataio(&ccb->ataio,
2447                       /*retries*/ retry_count,
2448                       /*cbfcnp*/ NULL,
2449                       /*flags*/ flags,
2450                       /*tag_action*/ 0,
2451                       /*data_ptr*/ data_ptr,
2452                       /*dxfer_len*/ data_bytes,
2453                       /*timeout*/ timeout ? timeout : 5000);
2454         }
2455
2456         if (((retval = cam_send_ccb(device, ccb)) < 0)
2457          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2458                 if (retval < 0)
2459                         warn("error sending command");
2460                 else
2461                         warnx("error sending command");
2462
2463                 if (arglist & CAM_ARG_VERBOSE) {
2464                         cam_error_print(device, ccb, CAM_ESF_ALL,
2465                                         CAM_EPF_ALL, stderr);
2466                 }
2467
2468                 error = 1;
2469                 goto scsicmd_bailout;
2470         }
2471
2472         if (atacmd_len && need_res) {
2473                 if (fd_res == 0) {
2474                         buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2475                                           arg_put, NULL);
2476                         fprintf(stdout, "\n");
2477                 } else {
2478                         fprintf(stdout,
2479                             "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2480                             ccb->ataio.res.status,
2481                             ccb->ataio.res.error,
2482                             ccb->ataio.res.lba_low,
2483                             ccb->ataio.res.lba_mid,
2484                             ccb->ataio.res.lba_high,
2485                             ccb->ataio.res.device,
2486                             ccb->ataio.res.lba_low_exp,
2487                             ccb->ataio.res.lba_mid_exp,
2488                             ccb->ataio.res.lba_high_exp,
2489                             ccb->ataio.res.sector_count,
2490                             ccb->ataio.res.sector_count_exp);
2491                         fflush(stdout);
2492                 }
2493         }
2494
2495         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2496          && (arglist & CAM_ARG_CMD_IN)
2497          && (data_bytes > 0)) {
2498                 if (fd_data == 0) {
2499                         buff_decode_visit(data_ptr, data_bytes, datastr,
2500                                           arg_put, NULL);
2501                         fprintf(stdout, "\n");
2502                 } else {
2503                         ssize_t amt_written;
2504                         int amt_to_write = data_bytes;
2505                         u_int8_t *buf_ptr = data_ptr;
2506
2507                         for (amt_written = 0; (amt_to_write > 0) &&
2508                              (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2509                                 amt_to_write -= amt_written;
2510                                 buf_ptr += amt_written;
2511                         }
2512                         if (amt_written == -1) {
2513                                 warn("error writing data to stdout");
2514                                 error = 1;
2515                                 goto scsicmd_bailout;
2516                         } else if ((amt_written == 0)
2517                                 && (amt_to_write > 0)) {
2518                                 warnx("only wrote %u bytes out of %u",
2519                                       data_bytes - amt_to_write, data_bytes);
2520                         }
2521                 }
2522         }
2523
2524 scsicmd_bailout:
2525
2526         if ((data_bytes > 0) && (data_ptr != NULL))
2527                 free(data_ptr);
2528
2529         cam_freeccb(ccb);
2530
2531         return(error);
2532 }
2533
2534 static int
2535 camdebug(int argc, char **argv, char *combinedopt)
2536 {
2537         int c, fd;
2538         int bus = -1, target = -1, lun = -1;
2539         char *tstr, *tmpstr = NULL;
2540         union ccb ccb;
2541         int error = 0;
2542
2543         bzero(&ccb, sizeof(union ccb));
2544
2545         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2546                 switch(c) {
2547                 case 'I':
2548                         arglist |= CAM_ARG_DEBUG_INFO;
2549                         ccb.cdbg.flags |= CAM_DEBUG_INFO;
2550                         break;
2551                 case 'P':
2552                         arglist |= CAM_ARG_DEBUG_PERIPH;
2553                         ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2554                         break;
2555                 case 'S':
2556                         arglist |= CAM_ARG_DEBUG_SUBTRACE;
2557                         ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2558                         break;
2559                 case 'T':
2560                         arglist |= CAM_ARG_DEBUG_TRACE;
2561                         ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2562                         break;
2563                 case 'X':
2564                         arglist |= CAM_ARG_DEBUG_XPT;
2565                         ccb.cdbg.flags |= CAM_DEBUG_XPT;
2566                         break;
2567                 case 'c':
2568                         arglist |= CAM_ARG_DEBUG_CDB;
2569                         ccb.cdbg.flags |= CAM_DEBUG_CDB;
2570                         break;
2571                 default:
2572                         break;
2573                 }
2574         }
2575
2576         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2577                 warnx("error opening transport layer device %s", XPT_DEVICE);
2578                 warn("%s", XPT_DEVICE);
2579                 return(1);
2580         }
2581         argc -= optind;
2582         argv += optind;
2583
2584         if (argc <= 0) {
2585                 warnx("you must specify \"off\", \"all\" or a bus,");
2586                 warnx("bus:target, or bus:target:lun");
2587                 close(fd);
2588                 return(1);
2589         }
2590
2591         tstr = *argv;
2592
2593         while (isspace(*tstr) && (*tstr != '\0'))
2594                 tstr++;
2595
2596         if (strncmp(tstr, "off", 3) == 0) {
2597                 ccb.cdbg.flags = CAM_DEBUG_NONE;
2598                 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2599                              CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2600                              CAM_ARG_DEBUG_XPT);
2601         } else if (strncmp(tstr, "all", 3) != 0) {
2602                 tmpstr = (char *)strtok(tstr, ":");
2603                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2604                         bus = strtol(tmpstr, NULL, 0);
2605                         arglist |= CAM_ARG_BUS;
2606                         tmpstr = (char *)strtok(NULL, ":");
2607                         if ((tmpstr != NULL) && (*tmpstr != '\0')){
2608                                 target = strtol(tmpstr, NULL, 0);
2609                                 arglist |= CAM_ARG_TARGET;
2610                                 tmpstr = (char *)strtok(NULL, ":");
2611                                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2612                                         lun = strtol(tmpstr, NULL, 0);
2613                                         arglist |= CAM_ARG_LUN;
2614                                 }
2615                         }
2616                 } else {
2617                         error = 1;
2618                         warnx("you must specify \"all\", \"off\", or a bus,");
2619                         warnx("bus:target, or bus:target:lun to debug");
2620                 }
2621         }
2622
2623         if (error == 0) {
2624
2625                 ccb.ccb_h.func_code = XPT_DEBUG;
2626                 ccb.ccb_h.path_id = bus;
2627                 ccb.ccb_h.target_id = target;
2628                 ccb.ccb_h.target_lun = lun;
2629
2630                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2631                         warn("CAMIOCOMMAND ioctl failed");
2632                         error = 1;
2633                 }
2634
2635                 if (error == 0) {
2636                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2637                              CAM_FUNC_NOTAVAIL) {
2638                                 warnx("CAM debugging not available");
2639                                 warnx("you need to put options CAMDEBUG in"
2640                                       " your kernel config file!");
2641                                 error = 1;
2642                         } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2643                                     CAM_REQ_CMP) {
2644                                 warnx("XPT_DEBUG CCB failed with status %#x",
2645                                       ccb.ccb_h.status);
2646                                 error = 1;
2647                         } else {
2648                                 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2649                                         fprintf(stderr,
2650                                                 "Debugging turned off\n");
2651                                 } else {
2652                                         fprintf(stderr,
2653                                                 "Debugging enabled for "
2654                                                 "%d:%d:%d\n",
2655                                                 bus, target, lun);
2656                                 }
2657                         }
2658                 }
2659                 close(fd);
2660         }
2661
2662         return(error);
2663 }
2664
2665 static int
2666 tagcontrol(struct cam_device *device, int argc, char **argv,
2667            char *combinedopt)
2668 {
2669         int c;
2670         union ccb *ccb;
2671         int numtags = -1;
2672         int retval = 0;
2673         int quiet = 0;
2674         char pathstr[1024];
2675
2676         ccb = cam_getccb(device);
2677
2678         if (ccb == NULL) {
2679                 warnx("tagcontrol: error allocating ccb");
2680                 return(1);
2681         }
2682
2683         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2684                 switch(c) {
2685                 case 'N':
2686                         numtags = strtol(optarg, NULL, 0);
2687                         if (numtags < 0) {
2688                                 warnx("tag count %d is < 0", numtags);
2689                                 retval = 1;
2690                                 goto tagcontrol_bailout;
2691                         }
2692                         break;
2693                 case 'q':
2694                         quiet++;
2695                         break;
2696                 default:
2697                         break;
2698                 }
2699         }
2700
2701         cam_path_string(device, pathstr, sizeof(pathstr));
2702
2703         if (numtags >= 0) {
2704                 bzero(&(&ccb->ccb_h)[1],
2705                       sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2706                 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2707                 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2708                 ccb->crs.openings = numtags;
2709
2710
2711                 if (cam_send_ccb(device, ccb) < 0) {
2712                         perror("error sending XPT_REL_SIMQ CCB");
2713                         retval = 1;
2714                         goto tagcontrol_bailout;
2715                 }
2716
2717                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2718                         warnx("XPT_REL_SIMQ CCB failed");
2719                         cam_error_print(device, ccb, CAM_ESF_ALL,
2720                                         CAM_EPF_ALL, stderr);
2721                         retval = 1;
2722                         goto tagcontrol_bailout;
2723                 }
2724
2725
2726                 if (quiet == 0)
2727                         fprintf(stdout, "%stagged openings now %d\n",
2728                                 pathstr, ccb->crs.openings);
2729         }
2730
2731         bzero(&(&ccb->ccb_h)[1],
2732               sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2733
2734         ccb->ccb_h.func_code = XPT_GDEV_STATS;
2735
2736         if (cam_send_ccb(device, ccb) < 0) {
2737                 perror("error sending XPT_GDEV_STATS CCB");
2738                 retval = 1;
2739                 goto tagcontrol_bailout;
2740         }
2741
2742         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2743                 warnx("XPT_GDEV_STATS CCB failed");
2744                 cam_error_print(device, ccb, CAM_ESF_ALL,
2745                                 CAM_EPF_ALL, stderr);
2746                 retval = 1;
2747                 goto tagcontrol_bailout;
2748         }
2749
2750         if (arglist & CAM_ARG_VERBOSE) {
2751                 fprintf(stdout, "%s", pathstr);
2752                 fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2753                 fprintf(stdout, "%s", pathstr);
2754                 fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2755                 fprintf(stdout, "%s", pathstr);
2756                 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2757                 fprintf(stdout, "%s", pathstr);
2758                 fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2759                 fprintf(stdout, "%s", pathstr);
2760                 fprintf(stdout, "held          %d\n", ccb->cgds.held);
2761                 fprintf(stdout, "%s", pathstr);
2762                 fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2763                 fprintf(stdout, "%s", pathstr);
2764                 fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2765         } else {
2766                 if (quiet == 0) {
2767                         fprintf(stdout, "%s", pathstr);
2768                         fprintf(stdout, "device openings: ");
2769                 }
2770                 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2771                         ccb->cgds.dev_active);
2772         }
2773
2774 tagcontrol_bailout:
2775
2776         cam_freeccb(ccb);
2777         return(retval);
2778 }
2779
2780 static void
2781 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2782 {
2783         char pathstr[1024];
2784
2785         cam_path_string(device, pathstr, sizeof(pathstr));
2786
2787         if (cts->transport == XPORT_SPI) {
2788                 struct ccb_trans_settings_spi *spi =
2789                     &cts->xport_specific.spi;
2790
2791                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2792
2793                         fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2794                                 spi->sync_period);
2795
2796                         if (spi->sync_offset != 0) {
2797                                 u_int freq;
2798
2799                                 freq = scsi_calc_syncsrate(spi->sync_period);
2800                                 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2801                                         pathstr, freq / 1000, freq % 1000);
2802                         }
2803                 }
2804
2805                 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2806                         fprintf(stdout, "%soffset: %d\n", pathstr,
2807                             spi->sync_offset);
2808                 }
2809
2810                 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2811                         fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2812                                 (0x01 << spi->bus_width) * 8);
2813                 }
2814
2815                 if (spi->valid & CTS_SPI_VALID_DISC) {
2816                         fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2817                                 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2818                                 "enabled" : "disabled");
2819                 }
2820         }
2821         if (cts->transport == XPORT_FC) {
2822                 struct ccb_trans_settings_fc *fc =
2823                     &cts->xport_specific.fc;
2824
2825                 if (fc->valid & CTS_FC_VALID_WWNN)
2826                         fprintf(stdout, "%sWWNN: 0x%llx", pathstr,
2827                             (long long) fc->wwnn);
2828                 if (fc->valid & CTS_FC_VALID_WWPN)
2829                         fprintf(stdout, "%sWWPN: 0x%llx", pathstr,
2830                             (long long) fc->wwpn);
2831                 if (fc->valid & CTS_FC_VALID_PORT)
2832                         fprintf(stdout, "%sPortID: 0x%x", pathstr, fc->port);
2833                 if (fc->valid & CTS_FC_VALID_SPEED)
2834                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2835                             pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
2836         }
2837         if (cts->transport == XPORT_SAS) {
2838                 struct ccb_trans_settings_sas *sas =
2839                     &cts->xport_specific.sas;
2840
2841                 if (sas->valid & CTS_SAS_VALID_SPEED)
2842                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2843                             pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
2844         }
2845         if (cts->transport == XPORT_ATA) {
2846                 struct ccb_trans_settings_pata *pata =
2847                     &cts->xport_specific.ata;
2848
2849                 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
2850                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
2851                                 ata_mode2string(pata->mode));
2852                 }
2853                 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2854                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2855                                 pata->atapi);
2856                 }
2857                 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2858                         fprintf(stdout, "%sPIO transaction length: %d\n",
2859                                 pathstr, pata->bytecount);
2860                 }
2861         }
2862         if (cts->transport == XPORT_SATA) {
2863                 struct ccb_trans_settings_sata *sata =
2864                     &cts->xport_specific.sata;
2865
2866                 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2867                         fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2868                                 sata->revision);
2869                 }
2870                 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2871                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
2872                                 ata_mode2string(sata->mode));
2873                 }
2874                 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2875                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2876                                 sata->atapi);
2877                 }
2878                 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2879                         fprintf(stdout, "%sPIO transaction length: %d\n",
2880                                 pathstr, sata->bytecount);
2881                 }
2882                 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2883                         fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2884                                 sata->pm_present);
2885                 }
2886                 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2887                         fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2888                                 sata->tags);
2889                 }
2890                 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2891                         fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2892                                 sata->caps);
2893                 }
2894         }
2895         if (cts->protocol == PROTO_ATA) {
2896                 struct ccb_trans_settings_ata *ata=
2897                     &cts->proto_specific.ata;
2898
2899                 if (ata->valid & CTS_ATA_VALID_TQ) {
2900                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
2901                                 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
2902                                 "enabled" : "disabled");
2903                 }
2904         }
2905         if (cts->protocol == PROTO_SCSI) {
2906                 struct ccb_trans_settings_scsi *scsi=
2907                     &cts->proto_specific.scsi;
2908
2909                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2910                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
2911                                 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2912                                 "enabled" : "disabled");
2913                 }
2914         }
2915
2916 }
2917
2918 /*
2919  * Get a path inquiry CCB for the specified device.
2920  */
2921 static int
2922 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2923 {
2924         union ccb *ccb;
2925         int retval = 0;
2926
2927         ccb = cam_getccb(device);
2928         if (ccb == NULL) {
2929                 warnx("get_cpi: couldn't allocate CCB");
2930                 return(1);
2931         }
2932         bzero(&(&ccb->ccb_h)[1],
2933               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2934         ccb->ccb_h.func_code = XPT_PATH_INQ;
2935         if (cam_send_ccb(device, ccb) < 0) {
2936                 warn("get_cpi: error sending Path Inquiry CCB");
2937                 if (arglist & CAM_ARG_VERBOSE)
2938                         cam_error_print(device, ccb, CAM_ESF_ALL,
2939                                         CAM_EPF_ALL, stderr);
2940                 retval = 1;
2941                 goto get_cpi_bailout;
2942         }
2943         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2944                 if (arglist & CAM_ARG_VERBOSE)
2945                         cam_error_print(device, ccb, CAM_ESF_ALL,
2946                                         CAM_EPF_ALL, stderr);
2947                 retval = 1;
2948                 goto get_cpi_bailout;
2949         }
2950         bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2951
2952 get_cpi_bailout:
2953         cam_freeccb(ccb);
2954         return(retval);
2955 }
2956
2957 /*
2958  * Get a get device CCB for the specified device.
2959  */
2960 static int
2961 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
2962 {
2963         union ccb *ccb;
2964         int retval = 0;
2965
2966         ccb = cam_getccb(device);
2967         if (ccb == NULL) {
2968                 warnx("get_cgd: couldn't allocate CCB");
2969                 return(1);
2970         }
2971         bzero(&(&ccb->ccb_h)[1],
2972               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2973         ccb->ccb_h.func_code = XPT_GDEV_TYPE;
2974         if (cam_send_ccb(device, ccb) < 0) {
2975                 warn("get_cgd: error sending Path Inquiry CCB");
2976                 if (arglist & CAM_ARG_VERBOSE)
2977                         cam_error_print(device, ccb, CAM_ESF_ALL,
2978                                         CAM_EPF_ALL, stderr);
2979                 retval = 1;
2980                 goto get_cgd_bailout;
2981         }
2982         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2983                 if (arglist & CAM_ARG_VERBOSE)
2984                         cam_error_print(device, ccb, CAM_ESF_ALL,
2985                                         CAM_EPF_ALL, stderr);
2986                 retval = 1;
2987                 goto get_cgd_bailout;
2988         }
2989         bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
2990
2991 get_cgd_bailout:
2992         cam_freeccb(ccb);
2993         return(retval);
2994 }
2995
2996 static void
2997 cpi_print(struct ccb_pathinq *cpi)
2998 {
2999         char adapter_str[1024];
3000         int i;
3001
3002         snprintf(adapter_str, sizeof(adapter_str),
3003                  "%s%d:", cpi->dev_name, cpi->unit_number);
3004
3005         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3006                 cpi->version_num);
3007
3008         for (i = 1; i < 0xff; i = i << 1) {
3009                 const char *str;
3010
3011                 if ((i & cpi->hba_inquiry) == 0)
3012                         continue;
3013
3014                 fprintf(stdout, "%s supports ", adapter_str);
3015
3016                 switch(i) {
3017                 case PI_MDP_ABLE:
3018                         str = "MDP message";
3019                         break;
3020                 case PI_WIDE_32:
3021                         str = "32 bit wide SCSI";
3022                         break;
3023                 case PI_WIDE_16:
3024                         str = "16 bit wide SCSI";
3025                         break;
3026                 case PI_SDTR_ABLE:
3027                         str = "SDTR message";
3028                         break;
3029                 case PI_LINKED_CDB:
3030                         str = "linked CDBs";
3031                         break;
3032                 case PI_TAG_ABLE:
3033                         str = "tag queue messages";
3034                         break;
3035                 case PI_SOFT_RST:
3036                         str = "soft reset alternative";
3037                         break;
3038                 case PI_SATAPM:
3039                         str = "SATA Port Multiplier";
3040                         break;
3041                 default:
3042                         str = "unknown PI bit set";
3043                         break;
3044                 }
3045                 fprintf(stdout, "%s\n", str);
3046         }
3047
3048         for (i = 1; i < 0xff; i = i << 1) {
3049                 const char *str;
3050
3051                 if ((i & cpi->hba_misc) == 0)
3052                         continue;
3053
3054                 fprintf(stdout, "%s ", adapter_str);
3055
3056                 switch(i) {
3057                 case PIM_SCANHILO:
3058                         str = "bus scans from high ID to low ID";
3059                         break;
3060                 case PIM_NOREMOVE:
3061                         str = "removable devices not included in scan";
3062                         break;
3063                 case PIM_NOINITIATOR:
3064                         str = "initiator role not supported";
3065                         break;
3066                 case PIM_NOBUSRESET:
3067                         str = "user has disabled initial BUS RESET or"
3068                               " controller is in target/mixed mode";
3069                         break;
3070                 case PIM_NO_6_BYTE:
3071                         str = "do not send 6-byte commands";
3072                         break;
3073                 case PIM_SEQSCAN:
3074                         str = "scan bus sequentially";
3075                         break;
3076                 default:
3077                         str = "unknown PIM bit set";
3078                         break;
3079                 }
3080                 fprintf(stdout, "%s\n", str);
3081         }
3082
3083         for (i = 1; i < 0xff; i = i << 1) {
3084                 const char *str;
3085
3086                 if ((i & cpi->target_sprt) == 0)
3087                         continue;
3088
3089                 fprintf(stdout, "%s supports ", adapter_str);
3090                 switch(i) {
3091                 case PIT_PROCESSOR:
3092                         str = "target mode processor mode";
3093                         break;
3094                 case PIT_PHASE:
3095                         str = "target mode phase cog. mode";
3096                         break;
3097                 case PIT_DISCONNECT:
3098                         str = "disconnects in target mode";
3099                         break;
3100                 case PIT_TERM_IO:
3101                         str = "terminate I/O message in target mode";
3102                         break;
3103                 case PIT_GRP_6:
3104                         str = "group 6 commands in target mode";
3105                         break;
3106                 case PIT_GRP_7:
3107                         str = "group 7 commands in target mode";
3108                         break;
3109                 default:
3110                         str = "unknown PIT bit set";
3111                         break;
3112                 }
3113
3114                 fprintf(stdout, "%s\n", str);
3115         }
3116         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3117                 cpi->hba_eng_cnt);
3118         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3119                 cpi->max_target);
3120         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3121                 cpi->max_lun);
3122         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3123                 adapter_str, cpi->hpath_id);
3124         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3125                 cpi->initiator_id);
3126         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3127         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3128         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3129         fprintf(stdout, "%s base transfer speed: ", adapter_str);
3130         if (cpi->base_transfer_speed > 1000)
3131                 fprintf(stdout, "%d.%03dMB/sec\n",
3132                         cpi->base_transfer_speed / 1000,
3133                         cpi->base_transfer_speed % 1000);
3134         else
3135                 fprintf(stdout, "%dKB/sec\n",
3136                         (cpi->base_transfer_speed % 1000) * 1000);
3137 }
3138
3139 static int
3140 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3141               struct ccb_trans_settings *cts)
3142 {
3143         int retval;
3144         union ccb *ccb;
3145
3146         retval = 0;
3147         ccb = cam_getccb(device);
3148
3149         if (ccb == NULL) {
3150                 warnx("get_print_cts: error allocating ccb");
3151                 return(1);
3152         }
3153
3154         bzero(&(&ccb->ccb_h)[1],
3155               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3156
3157         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3158
3159         if (user_settings == 0)
3160                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3161         else
3162                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3163
3164         if (cam_send_ccb(device, ccb) < 0) {
3165                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3166                 if (arglist & CAM_ARG_VERBOSE)
3167                         cam_error_print(device, ccb, CAM_ESF_ALL,
3168                                         CAM_EPF_ALL, stderr);
3169                 retval = 1;
3170                 goto get_print_cts_bailout;
3171         }
3172
3173         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3174                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3175                 if (arglist & CAM_ARG_VERBOSE)
3176                         cam_error_print(device, ccb, CAM_ESF_ALL,
3177                                         CAM_EPF_ALL, stderr);
3178                 retval = 1;
3179                 goto get_print_cts_bailout;
3180         }
3181
3182         if (quiet == 0)
3183                 cts_print(device, &ccb->cts);
3184
3185         if (cts != NULL)
3186                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3187
3188 get_print_cts_bailout:
3189
3190         cam_freeccb(ccb);
3191
3192         return(retval);
3193 }
3194
3195 static int
3196 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3197             int argc, char **argv, char *combinedopt)
3198 {
3199         int c;
3200         union ccb *ccb;
3201         int user_settings = 0;
3202         int retval = 0;
3203         int disc_enable = -1, tag_enable = -1;
3204         int mode = -1;
3205         int offset = -1;
3206         double syncrate = -1;
3207         int bus_width = -1;
3208         int quiet = 0;
3209         int change_settings = 0, send_tur = 0;
3210         struct ccb_pathinq cpi;
3211
3212         ccb = cam_getccb(device);
3213         if (ccb == NULL) {
3214                 warnx("ratecontrol: error allocating ccb");
3215                 return(1);
3216         }
3217         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3218                 switch(c){
3219                 case 'a':
3220                         send_tur = 1;
3221                         break;
3222                 case 'c':
3223                         user_settings = 0;
3224                         break;
3225                 case 'D':
3226                         if (strncasecmp(optarg, "enable", 6) == 0)
3227                                 disc_enable = 1;
3228                         else if (strncasecmp(optarg, "disable", 7) == 0)
3229                                 disc_enable = 0;
3230                         else {
3231                                 warnx("-D argument \"%s\" is unknown", optarg);
3232                                 retval = 1;
3233                                 goto ratecontrol_bailout;
3234                         }
3235                         change_settings = 1;
3236                         break;
3237                 case 'M':
3238                         mode = ata_string2mode(optarg);
3239                         if (mode < 0) {
3240                                 warnx("unknown mode '%s'", optarg);
3241                                 retval = 1;
3242                                 goto ratecontrol_bailout;
3243                         }
3244                         change_settings = 1;
3245                         break;
3246                 case 'O':
3247                         offset = strtol(optarg, NULL, 0);
3248                         if (offset < 0) {
3249                                 warnx("offset value %d is < 0", offset);
3250                                 retval = 1;
3251                                 goto ratecontrol_bailout;
3252                         }
3253                         change_settings = 1;
3254                         break;
3255                 case 'q':
3256                         quiet++;
3257                         break;
3258                 case 'R':
3259                         syncrate = atof(optarg);
3260                         if (syncrate < 0) {
3261                                 warnx("sync rate %f is < 0", syncrate);
3262                                 retval = 1;
3263                                 goto ratecontrol_bailout;
3264                         }
3265                         change_settings = 1;
3266                         break;
3267                 case 'T':
3268                         if (strncasecmp(optarg, "enable", 6) == 0)
3269                                 tag_enable = 1;
3270                         else if (strncasecmp(optarg, "disable", 7) == 0)
3271                                 tag_enable = 0;
3272                         else {
3273                                 warnx("-T argument \"%s\" is unknown", optarg);
3274                                 retval = 1;
3275                                 goto ratecontrol_bailout;
3276                         }
3277                         change_settings = 1;
3278                         break;
3279                 case 'U':
3280                         user_settings = 1;
3281                         break;
3282                 case 'W':
3283                         bus_width = strtol(optarg, NULL, 0);
3284                         if (bus_width < 0) {
3285                                 warnx("bus width %d is < 0", bus_width);
3286                                 retval = 1;
3287                                 goto ratecontrol_bailout;
3288                         }
3289                         change_settings = 1;
3290                         break;
3291                 default:
3292                         break;
3293                 }
3294         }
3295         bzero(&(&ccb->ccb_h)[1],
3296               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3297         /*
3298          * Grab path inquiry information, so we can determine whether
3299          * or not the initiator is capable of the things that the user
3300          * requests.
3301          */
3302         ccb->ccb_h.func_code = XPT_PATH_INQ;
3303         if (cam_send_ccb(device, ccb) < 0) {
3304                 perror("error sending XPT_PATH_INQ CCB");
3305                 if (arglist & CAM_ARG_VERBOSE) {
3306                         cam_error_print(device, ccb, CAM_ESF_ALL,
3307                                         CAM_EPF_ALL, stderr);
3308                 }
3309                 retval = 1;
3310                 goto ratecontrol_bailout;
3311         }
3312         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3313                 warnx("XPT_PATH_INQ CCB failed");
3314                 if (arglist & CAM_ARG_VERBOSE) {
3315                         cam_error_print(device, ccb, CAM_ESF_ALL,
3316                                         CAM_EPF_ALL, stderr);
3317                 }
3318                 retval = 1;
3319                 goto ratecontrol_bailout;
3320         }
3321         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3322         bzero(&(&ccb->ccb_h)[1],
3323               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3324         if (quiet == 0) {
3325                 fprintf(stdout, "%s parameters:\n",
3326                     user_settings ? "User" : "Current");
3327         }
3328         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3329         if (retval != 0)
3330                 goto ratecontrol_bailout;
3331
3332         if (arglist & CAM_ARG_VERBOSE)
3333                 cpi_print(&cpi);
3334
3335         if (change_settings) {
3336                 int didsettings = 0;
3337                 struct ccb_trans_settings_spi *spi = NULL;
3338                 struct ccb_trans_settings_pata *pata = NULL;
3339                 struct ccb_trans_settings_sata *sata = NULL;
3340                 struct ccb_trans_settings_ata *ata = NULL;
3341                 struct ccb_trans_settings_scsi *scsi = NULL;
3342
3343                 if (ccb->cts.transport == XPORT_SPI)
3344                         spi = &ccb->cts.xport_specific.spi;
3345                 if (ccb->cts.transport == XPORT_ATA)
3346                         pata = &ccb->cts.xport_specific.ata;
3347                 if (ccb->cts.transport == XPORT_SATA)
3348                         sata = &ccb->cts.xport_specific.sata;
3349                 if (ccb->cts.protocol == PROTO_ATA)
3350                         ata = &ccb->cts.proto_specific.ata;
3351                 if (ccb->cts.protocol == PROTO_SCSI)
3352                         scsi = &ccb->cts.proto_specific.scsi;
3353                 ccb->cts.xport_specific.valid = 0;
3354                 ccb->cts.proto_specific.valid = 0;
3355                 if (spi && disc_enable != -1) {
3356                         spi->valid |= CTS_SPI_VALID_DISC;
3357                         if (disc_enable == 0)
3358                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3359                         else
3360                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3361                         didsettings++;
3362                 }
3363                 if (tag_enable != -1) {
3364                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3365                                 warnx("HBA does not support tagged queueing, "
3366                                       "so you cannot modify tag settings");
3367                                 retval = 1;
3368                                 goto ratecontrol_bailout;
3369                         }
3370                         if (ata) {
3371                                 ata->valid |= CTS_SCSI_VALID_TQ;
3372                                 if (tag_enable == 0)
3373                                         ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
3374                                 else
3375                                         ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
3376                                 didsettings++;
3377                         } else if (scsi) {
3378                                 scsi->valid |= CTS_SCSI_VALID_TQ;
3379                                 if (tag_enable == 0)
3380                                         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3381                                 else
3382                                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3383                                 didsettings++;
3384                         }
3385                 }
3386                 if (spi && offset != -1) {
3387                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3388                                 warnx("HBA is not capable of changing offset");
3389                                 retval = 1;
3390                                 goto ratecontrol_bailout;
3391                         }
3392                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3393                         spi->sync_offset = offset;
3394                         didsettings++;
3395                 }
3396                 if (spi && syncrate != -1) {
3397                         int prelim_sync_period;
3398                         u_int freq;
3399
3400                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3401                                 warnx("HBA is not capable of changing "
3402                                       "transfer rates");
3403                                 retval = 1;
3404                                 goto ratecontrol_bailout;
3405                         }
3406                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3407                         /*
3408                          * The sync rate the user gives us is in MHz.
3409                          * We need to translate it into KHz for this
3410                          * calculation.
3411                          */
3412                         syncrate *= 1000;
3413                         /*
3414                          * Next, we calculate a "preliminary" sync period
3415                          * in tenths of a nanosecond.
3416                          */
3417                         if (syncrate == 0)
3418                                 prelim_sync_period = 0;
3419                         else
3420                                 prelim_sync_period = 10000000 / syncrate;
3421                         spi->sync_period =
3422                                 scsi_calc_syncparam(prelim_sync_period);
3423                         freq = scsi_calc_syncsrate(spi->sync_period);
3424                         didsettings++;
3425                 }
3426                 if (sata && syncrate != -1) {
3427                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3428                                 warnx("HBA is not capable of changing "
3429                                       "transfer rates");
3430                                 retval = 1;
3431                                 goto ratecontrol_bailout;
3432                         }
3433                         if  (!user_settings) {
3434                                 warnx("You can modify only user rate "
3435                                     "settings for SATA");
3436                                 retval = 1;
3437                                 goto ratecontrol_bailout;
3438                         }
3439                         sata->revision = ata_speed2revision(syncrate * 100);
3440                         if (sata->revision < 0) {
3441                                 warnx("Invalid rate %f", syncrate);
3442                                 retval = 1;
3443                                 goto ratecontrol_bailout;
3444                         }
3445                         sata->valid |= CTS_SATA_VALID_REVISION;
3446                         didsettings++;
3447                 }
3448                 if ((pata || sata) && mode != -1) {
3449                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3450                                 warnx("HBA is not capable of changing "
3451                                       "transfer rates");
3452                                 retval = 1;
3453                                 goto ratecontrol_bailout;
3454                         }
3455                         if  (!user_settings) {
3456                                 warnx("You can modify only user mode "
3457                                     "settings for ATA/SATA");
3458                                 retval = 1;
3459                                 goto ratecontrol_bailout;
3460                         }
3461                         if (pata) {
3462                                 pata->mode = mode;
3463                                 pata->valid |= CTS_ATA_VALID_MODE;
3464                         } else {
3465                                 sata->mode = mode;
3466                                 sata->valid |= CTS_SATA_VALID_MODE;
3467                         }
3468                         didsettings++;
3469                 }
3470                 /*
3471                  * The bus_width argument goes like this:
3472                  * 0 == 8 bit
3473                  * 1 == 16 bit
3474                  * 2 == 32 bit
3475                  * Therefore, if you shift the number of bits given on the
3476                  * command line right by 4, you should get the correct
3477                  * number.
3478                  */
3479                 if (spi && bus_width != -1) {
3480                         /*
3481                          * We might as well validate things here with a
3482                          * decipherable error message, rather than what
3483                          * will probably be an indecipherable error message
3484                          * by the time it gets back to us.
3485                          */
3486                         if ((bus_width == 16)
3487                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3488                                 warnx("HBA does not support 16 bit bus width");
3489                                 retval = 1;
3490                                 goto ratecontrol_bailout;
3491                         } else if ((bus_width == 32)
3492                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3493                                 warnx("HBA does not support 32 bit bus width");
3494                                 retval = 1;
3495                                 goto ratecontrol_bailout;
3496                         } else if ((bus_width != 8)
3497                                 && (bus_width != 16)
3498                                 && (bus_width != 32)) {
3499                                 warnx("Invalid bus width %d", bus_width);
3500                                 retval = 1;
3501                                 goto ratecontrol_bailout;
3502                         }
3503                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3504                         spi->bus_width = bus_width >> 4;
3505                         didsettings++;
3506                 }
3507                 if  (didsettings == 0) {
3508                         goto ratecontrol_bailout;
3509                 }
3510                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3511                 if (cam_send_ccb(device, ccb) < 0) {
3512                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3513                         if (arglist & CAM_ARG_VERBOSE) {
3514                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3515                                                 CAM_EPF_ALL, stderr);
3516                         }
3517                         retval = 1;
3518                         goto ratecontrol_bailout;
3519                 }
3520                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3521                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3522                         if (arglist & CAM_ARG_VERBOSE) {
3523                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3524                                                 CAM_EPF_ALL, stderr);
3525                         }
3526                         retval = 1;
3527                         goto ratecontrol_bailout;
3528                 }
3529         }
3530         if (send_tur) {
3531                 retval = testunitready(device, retry_count, timeout,
3532                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3533                 /*
3534                  * If the TUR didn't succeed, just bail.
3535                  */
3536                 if (retval != 0) {
3537                         if (quiet == 0)
3538                                 fprintf(stderr, "Test Unit Ready failed\n");
3539                         goto ratecontrol_bailout;
3540                 }
3541         }
3542         if ((change_settings || send_tur) && !quiet &&
3543             (ccb->cts.transport == XPORT_ATA ||
3544              ccb->cts.transport == XPORT_SATA || send_tur)) {
3545                 fprintf(stdout, "New parameters:\n");
3546                 retval = get_print_cts(device, user_settings, 0, NULL);
3547         }
3548
3549 ratecontrol_bailout:
3550         cam_freeccb(ccb);
3551         return(retval);
3552 }
3553
3554 static int
3555 scsiformat(struct cam_device *device, int argc, char **argv,
3556            char *combinedopt, int retry_count, int timeout)
3557 {
3558         union ccb *ccb;
3559         int c;
3560         int ycount = 0, quiet = 0;
3561         int error = 0, response = 0, retval = 0;
3562         int use_timeout = 10800 * 1000;
3563         int immediate = 1;
3564         struct format_defect_list_header fh;
3565         u_int8_t *data_ptr = NULL;
3566         u_int32_t dxfer_len = 0;
3567         u_int8_t byte2 = 0;
3568         int num_warnings = 0;
3569         int reportonly = 0;
3570
3571         ccb = cam_getccb(device);
3572
3573         if (ccb == NULL) {
3574                 warnx("scsiformat: error allocating ccb");
3575                 return(1);
3576         }
3577
3578         bzero(&(&ccb->ccb_h)[1],
3579               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3580
3581         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3582                 switch(c) {
3583                 case 'q':
3584                         quiet++;
3585                         break;
3586                 case 'r':
3587                         reportonly = 1;
3588                         break;
3589                 case 'w':
3590                         immediate = 0;
3591                         break;
3592                 case 'y':
3593                         ycount++;
3594                         break;
3595                 }
3596         }
3597
3598         if (reportonly)
3599                 goto doreport;
3600
3601         if (quiet == 0) {
3602                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3603                         "following device:\n");
3604
3605                 error = scsidoinquiry(device, argc, argv, combinedopt,
3606                                       retry_count, timeout);
3607
3608                 if (error != 0) {
3609                         warnx("scsiformat: error sending inquiry");
3610                         goto scsiformat_bailout;
3611                 }
3612         }
3613
3614         if (ycount == 0) {
3615
3616                 do {
3617                         char str[1024];
3618
3619                         fprintf(stdout, "Are you SURE you want to do "
3620                                 "this? (yes/no) ");
3621
3622                         if (fgets(str, sizeof(str), stdin) != NULL) {
3623
3624                                 if (strncasecmp(str, "yes", 3) == 0)
3625                                         response = 1;
3626                                 else if (strncasecmp(str, "no", 2) == 0)
3627                                         response = -1;
3628                                 else {
3629                                         fprintf(stdout, "Please answer"
3630                                                 " \"yes\" or \"no\"\n");
3631                                 }
3632                         }
3633                 } while (response == 0);
3634
3635                 if (response == -1) {
3636                         error = 1;
3637                         goto scsiformat_bailout;
3638                 }
3639         }
3640
3641         if (timeout != 0)
3642                 use_timeout = timeout;
3643
3644         if (quiet == 0) {
3645                 fprintf(stdout, "Current format timeout is %d seconds\n",
3646                         use_timeout / 1000);
3647         }
3648
3649         /*
3650          * If the user hasn't disabled questions and didn't specify a
3651          * timeout on the command line, ask them if they want the current
3652          * timeout.
3653          */
3654         if ((ycount == 0)
3655          && (timeout == 0)) {
3656                 char str[1024];
3657                 int new_timeout = 0;
3658
3659                 fprintf(stdout, "Enter new timeout in seconds or press\n"
3660                         "return to keep the current timeout [%d] ",
3661                         use_timeout / 1000);
3662
3663                 if (fgets(str, sizeof(str), stdin) != NULL) {
3664                         if (str[0] != '\0')
3665                                 new_timeout = atoi(str);
3666                 }
3667
3668                 if (new_timeout != 0) {
3669                         use_timeout = new_timeout * 1000;
3670                         fprintf(stdout, "Using new timeout value %d\n",
3671                                 use_timeout / 1000);
3672                 }
3673         }
3674
3675         /*
3676          * Keep this outside the if block below to silence any unused
3677          * variable warnings.
3678          */
3679         bzero(&fh, sizeof(fh));
3680
3681         /*
3682          * If we're in immediate mode, we've got to include the format
3683          * header
3684          */
3685         if (immediate != 0) {
3686                 fh.byte2 = FU_DLH_IMMED;
3687                 data_ptr = (u_int8_t *)&fh;
3688                 dxfer_len = sizeof(fh);
3689                 byte2 = FU_FMT_DATA;
3690         } else if (quiet == 0) {
3691                 fprintf(stdout, "Formatting...");
3692                 fflush(stdout);
3693         }
3694
3695         scsi_format_unit(&ccb->csio,
3696                          /* retries */ retry_count,
3697                          /* cbfcnp */ NULL,
3698                          /* tag_action */ MSG_SIMPLE_Q_TAG,
3699                          /* byte2 */ byte2,
3700                          /* ileave */ 0,
3701                          /* data_ptr */ data_ptr,
3702                          /* dxfer_len */ dxfer_len,
3703                          /* sense_len */ SSD_FULL_SIZE,
3704                          /* timeout */ use_timeout);
3705
3706         /* Disable freezing the device queue */
3707         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3708
3709         if (arglist & CAM_ARG_ERR_RECOVER)
3710                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3711
3712         if (((retval = cam_send_ccb(device, ccb)) < 0)
3713          || ((immediate == 0)
3714            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3715                 const char errstr[] = "error sending format command";
3716
3717                 if (retval < 0)
3718                         warn(errstr);
3719                 else
3720                         warnx(errstr);
3721
3722                 if (arglist & CAM_ARG_VERBOSE) {
3723                         cam_error_print(device, ccb, CAM_ESF_ALL,
3724                                         CAM_EPF_ALL, stderr);
3725                 }
3726                 error = 1;
3727                 goto scsiformat_bailout;
3728         }
3729
3730         /*
3731          * If we ran in non-immediate mode, we already checked for errors
3732          * above and printed out any necessary information.  If we're in
3733          * immediate mode, we need to loop through and get status
3734          * information periodically.
3735          */
3736         if (immediate == 0) {
3737                 if (quiet == 0) {
3738                         fprintf(stdout, "Format Complete\n");
3739                 }
3740                 goto scsiformat_bailout;
3741         }
3742
3743 doreport:
3744         do {
3745                 cam_status status;
3746
3747                 bzero(&(&ccb->ccb_h)[1],
3748                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3749
3750                 /*
3751                  * There's really no need to do error recovery or
3752                  * retries here, since we're just going to sit in a
3753                  * loop and wait for the device to finish formatting.
3754                  */
3755                 scsi_test_unit_ready(&ccb->csio,
3756                                      /* retries */ 0,
3757                                      /* cbfcnp */ NULL,
3758                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
3759                                      /* sense_len */ SSD_FULL_SIZE,
3760                                      /* timeout */ 5000);
3761
3762                 /* Disable freezing the device queue */
3763                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3764
3765                 retval = cam_send_ccb(device, ccb);
3766
3767                 /*
3768                  * If we get an error from the ioctl, bail out.  SCSI
3769                  * errors are expected.
3770                  */
3771                 if (retval < 0) {
3772                         warn("error sending CAMIOCOMMAND ioctl");
3773                         if (arglist & CAM_ARG_VERBOSE) {
3774                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3775                                                 CAM_EPF_ALL, stderr);
3776                         }
3777                         error = 1;
3778                         goto scsiformat_bailout;
3779                 }
3780
3781                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3782
3783                 if ((status != CAM_REQ_CMP)
3784                  && (status == CAM_SCSI_STATUS_ERROR)
3785                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3786                         struct scsi_sense_data *sense;
3787                         int error_code, sense_key, asc, ascq;
3788
3789                         sense = &ccb->csio.sense_data;
3790                         scsi_extract_sense(sense, &error_code, &sense_key,
3791                                            &asc, &ascq);
3792
3793                         /*
3794                          * According to the SCSI-2 and SCSI-3 specs, a
3795                          * drive that is in the middle of a format should
3796                          * return NOT READY with an ASC of "logical unit
3797                          * not ready, format in progress".  The sense key
3798                          * specific bytes will then be a progress indicator.
3799                          */
3800                         if ((sense_key == SSD_KEY_NOT_READY)
3801                          && (asc == 0x04) && (ascq == 0x04)) {
3802                                 if ((sense->extra_len >= 10)
3803                                  && ((sense->sense_key_spec[0] &
3804                                       SSD_SCS_VALID) != 0)
3805                                  && (quiet == 0)) {
3806                                         int val;
3807                                         u_int64_t percentage;
3808
3809                                         val = scsi_2btoul(
3810                                                 &sense->sense_key_spec[1]);
3811                                         percentage = 10000 * val;
3812
3813                                         fprintf(stdout,
3814                                                 "\rFormatting:  %ju.%02u %% "
3815                                                 "(%d/%d) done",
3816                                                 (uintmax_t)(percentage /
3817                                                 (0x10000 * 100)),
3818                                                 (unsigned)((percentage /
3819                                                 0x10000) % 100),
3820                                                 val, 0x10000);
3821                                         fflush(stdout);
3822                                 } else if ((quiet == 0)
3823                                         && (++num_warnings <= 1)) {
3824                                         warnx("Unexpected SCSI Sense Key "
3825                                               "Specific value returned "
3826                                               "during format:");
3827                                         scsi_sense_print(device, &ccb->csio,
3828                                                          stderr);
3829                                         warnx("Unable to print status "
3830                                               "information, but format will "
3831                                               "proceed.");
3832                                         warnx("will exit when format is "
3833                                               "complete");
3834                                 }
3835                                 sleep(1);
3836                         } else {
3837                                 warnx("Unexpected SCSI error during format");
3838                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3839                                                 CAM_EPF_ALL, stderr);
3840                                 error = 1;
3841                                 goto scsiformat_bailout;
3842                         }
3843
3844                 } else if (status != CAM_REQ_CMP) {
3845                         warnx("Unexpected CAM status %#x", status);
3846                         if (arglist & CAM_ARG_VERBOSE)
3847                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3848                                                 CAM_EPF_ALL, stderr);
3849                         error = 1;
3850                         goto scsiformat_bailout;
3851                 }
3852
3853         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3854
3855         if (quiet == 0)
3856                 fprintf(stdout, "\nFormat Complete\n");
3857
3858 scsiformat_bailout:
3859
3860         cam_freeccb(ccb);
3861
3862         return(error);
3863 }
3864
3865 static int
3866 scsireportluns(struct cam_device *device, int argc, char **argv,
3867                char *combinedopt, int retry_count, int timeout)
3868 {
3869         union ccb *ccb;
3870         int c, countonly, lunsonly;
3871         struct scsi_report_luns_data *lundata;
3872         int alloc_len;
3873         uint8_t report_type;
3874         uint32_t list_len, i, j;
3875         int retval;
3876
3877         retval = 0;
3878         lundata = NULL;
3879         report_type = RPL_REPORT_DEFAULT;
3880         ccb = cam_getccb(device);
3881
3882         if (ccb == NULL) {
3883                 warnx("%s: error allocating ccb", __func__);
3884                 return (1);
3885         }
3886
3887         bzero(&(&ccb->ccb_h)[1],
3888               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3889
3890         countonly = 0;
3891         lunsonly = 0;
3892
3893         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3894                 switch (c) {
3895                 case 'c':
3896                         countonly++;
3897                         break;
3898                 case 'l':
3899                         lunsonly++;
3900                         break;
3901                 case 'r':
3902                         if (strcasecmp(optarg, "default") == 0)
3903                                 report_type = RPL_REPORT_DEFAULT;
3904                         else if (strcasecmp(optarg, "wellknown") == 0)
3905                                 report_type = RPL_REPORT_WELLKNOWN;
3906                         else if (strcasecmp(optarg, "all") == 0)
3907                                 report_type = RPL_REPORT_ALL;
3908                         else {
3909                                 warnx("%s: invalid report type \"%s\"",
3910                                       __func__, optarg);
3911                                 retval = 1;
3912                                 goto bailout;
3913                         }
3914                         break;
3915                 default:
3916                         break;
3917                 }
3918         }
3919
3920         if ((countonly != 0)
3921          && (lunsonly != 0)) {
3922                 warnx("%s: you can only specify one of -c or -l", __func__);
3923                 retval = 1;
3924                 goto bailout;
3925         }
3926         /*
3927          * According to SPC-4, the allocation length must be at least 16
3928          * bytes -- enough for the header and one LUN.
3929          */
3930         alloc_len = sizeof(*lundata) + 8;
3931
3932 retry:
3933
3934         lundata = malloc(alloc_len);
3935
3936         if (lundata == NULL) {
3937                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
3938                 retval = 1;
3939                 goto bailout;
3940         }
3941
3942         scsi_report_luns(&ccb->csio,
3943                          /*retries*/ retry_count,
3944                          /*cbfcnp*/ NULL,
3945                          /*tag_action*/ MSG_SIMPLE_Q_TAG,
3946                          /*select_report*/ report_type,
3947                          /*rpl_buf*/ lundata,
3948                          /*alloc_len*/ alloc_len,
3949                          /*sense_len*/ SSD_FULL_SIZE,
3950                          /*timeout*/ timeout ? timeout : 5000);
3951
3952         /* Disable freezing the device queue */
3953         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3954
3955         if (arglist & CAM_ARG_ERR_RECOVER)
3956                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3957
3958         if (cam_send_ccb(device, ccb) < 0) {
3959                 warn("error sending REPORT LUNS command");
3960
3961                 if (arglist & CAM_ARG_VERBOSE)
3962                         cam_error_print(device, ccb, CAM_ESF_ALL,
3963                                         CAM_EPF_ALL, stderr);
3964
3965                 retval = 1;
3966                 goto bailout;
3967         }
3968
3969         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3970                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3971                 retval = 1;
3972                 goto bailout;
3973         }
3974
3975
3976         list_len = scsi_4btoul(lundata->length);
3977
3978         /*
3979          * If we need to list the LUNs, and our allocation
3980          * length was too short, reallocate and retry.
3981          */
3982         if ((countonly == 0)
3983          && (list_len > (alloc_len - sizeof(*lundata)))) {
3984                 alloc_len = list_len + sizeof(*lundata);
3985                 free(lundata);
3986                 goto retry;
3987         }
3988
3989         if (lunsonly == 0)
3990                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
3991                         ((list_len / 8) > 1) ? "s" : "");
3992
3993         if (countonly != 0)
3994                 goto bailout;
3995
3996         for (i = 0; i < (list_len / 8); i++) {
3997                 int no_more;
3998
3999                 no_more = 0;
4000                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4001                         if (j != 0)
4002                                 fprintf(stdout, ",");
4003                         switch (lundata->luns[i].lundata[j] &
4004                                 RPL_LUNDATA_ATYP_MASK) {
4005                         case RPL_LUNDATA_ATYP_PERIPH:
4006                                 if ((lundata->luns[i].lundata[j] &
4007                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4008                                         fprintf(stdout, "%d:",
4009                                                 lundata->luns[i].lundata[j] &
4010                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
4011                                 else if ((j == 0)
4012                                       && ((lundata->luns[i].lundata[j+2] &
4013                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4014                                         no_more = 1;
4015
4016                                 fprintf(stdout, "%d",
4017                                         lundata->luns[i].lundata[j+1]);
4018                                 break;
4019                         case RPL_LUNDATA_ATYP_FLAT: {
4020                                 uint8_t tmplun[2];
4021                                 tmplun[0] = lundata->luns[i].lundata[j] &
4022                                         RPL_LUNDATA_FLAT_LUN_MASK;
4023                                 tmplun[1] = lundata->luns[i].lundata[j+1];
4024
4025                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
4026                                 no_more = 1;
4027                                 break;
4028                         }
4029                         case RPL_LUNDATA_ATYP_LUN:
4030                                 fprintf(stdout, "%d:%d:%d",
4031                                         (lundata->luns[i].lundata[j+1] &
4032                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4033                                         lundata->luns[i].lundata[j] &
4034                                         RPL_LUNDATA_LUN_TARG_MASK,
4035                                         lundata->luns[i].lundata[j+1] &
4036                                         RPL_LUNDATA_LUN_LUN_MASK);
4037                                 break;
4038                         case RPL_LUNDATA_ATYP_EXTLUN: {
4039                                 int field_len, field_len_code, eam_code;
4040
4041                                 eam_code = lundata->luns[i].lundata[j] &
4042                                         RPL_LUNDATA_EXT_EAM_MASK;
4043                                 field_len_code = (lundata->luns[i].lundata[j] &
4044                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4045                                 field_len = field_len_code * 2;
4046
4047                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4048                                  && (field_len_code == 0x00)) {
4049                                         fprintf(stdout, "%d",
4050                                                 lundata->luns[i].lundata[j+1]);
4051                                 } else if ((eam_code ==
4052                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4053                                         && (field_len_code == 0x03)) {
4054                                         uint8_t tmp_lun[8];
4055
4056                                         /*
4057                                          * This format takes up all 8 bytes.
4058                                          * If we aren't starting at offset 0,
4059                                          * that's a bug.
4060                                          */
4061                                         if (j != 0) {
4062                                                 fprintf(stdout, "Invalid "
4063                                                         "offset %d for "
4064                                                         "Extended LUN not "
4065                                                         "specified format", j);
4066                                                 no_more = 1;
4067                                                 break;
4068                                         }
4069                                         bzero(tmp_lun, sizeof(tmp_lun));
4070                                         bcopy(&lundata->luns[i].lundata[j+1],
4071                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
4072                                         fprintf(stdout, "%#jx",
4073                                                (intmax_t)scsi_8btou64(tmp_lun));
4074                                         no_more = 1;
4075                                 } else {
4076                                         fprintf(stderr, "Unknown Extended LUN"
4077                                                 "Address method %#x, length "
4078                                                 "code %#x", eam_code,
4079                                                 field_len_code);
4080                                         no_more = 1;
4081                                 }
4082                                 break;
4083                         }
4084                         default:
4085                                 fprintf(stderr, "Unknown LUN address method "
4086                                         "%#x\n", lundata->luns[i].lundata[0] &
4087                                         RPL_LUNDATA_ATYP_MASK);
4088                                 break;
4089                         }
4090                         /*
4091                          * For the flat addressing method, there are no
4092                          * other levels after it.
4093                          */
4094                         if (no_more != 0)
4095                                 break;
4096                 }
4097                 fprintf(stdout, "\n");
4098         }
4099
4100 bailout:
4101
4102         cam_freeccb(ccb);
4103
4104         free(lundata);
4105
4106         return (retval);
4107 }
4108
4109 static int
4110 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4111                  char *combinedopt, int retry_count, int timeout)
4112 {
4113         union ccb *ccb;
4114         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4115         struct scsi_read_capacity_data rcap;
4116         struct scsi_read_capacity_data_long rcaplong;
4117         uint64_t maxsector;
4118         uint32_t block_len;
4119         int retval;
4120         int c;
4121
4122         blocksizeonly = 0;
4123         humanize = 0;
4124         numblocks = 0;
4125         quiet = 0;
4126         sizeonly = 0;
4127         baseten = 0;
4128         retval = 0;
4129
4130         ccb = cam_getccb(device);
4131
4132         if (ccb == NULL) {
4133                 warnx("%s: error allocating ccb", __func__);
4134                 return (1);
4135         }
4136
4137         bzero(&(&ccb->ccb_h)[1],
4138               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4139
4140         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4141                 switch (c) {
4142                 case 'b':
4143                         blocksizeonly++;
4144                         break;
4145                 case 'h':
4146                         humanize++;
4147                         baseten = 0;
4148                         break;
4149                 case 'H':
4150                         humanize++;
4151                         baseten++;
4152                         break;
4153                 case 'N':
4154                         numblocks++;
4155                         break;
4156                 case 'q':
4157                         quiet++;
4158                         break;
4159                 case 's':
4160                         sizeonly++;
4161                         break;
4162                 default:
4163                         break;
4164                 }
4165         }
4166
4167         if ((blocksizeonly != 0)
4168          && (numblocks != 0)) {
4169                 warnx("%s: you can only specify one of -b or -N", __func__);
4170                 retval = 1;
4171                 goto bailout;
4172         }
4173
4174         if ((blocksizeonly != 0)
4175          && (sizeonly != 0)) {
4176                 warnx("%s: you can only specify one of -b or -s", __func__);
4177                 retval = 1;
4178                 goto bailout;
4179         }
4180
4181         if ((humanize != 0)
4182          && (quiet != 0)) {
4183                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
4184                 retval = 1;
4185                 goto bailout;
4186         }
4187
4188         if ((humanize != 0)
4189          && (blocksizeonly != 0)) {
4190                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
4191                 retval = 1;
4192                 goto bailout;
4193         }
4194
4195         scsi_read_capacity(&ccb->csio,
4196                            /*retries*/ retry_count,
4197                            /*cbfcnp*/ NULL,
4198                            /*tag_action*/ MSG_SIMPLE_Q_TAG,
4199                            &rcap,
4200                            SSD_FULL_SIZE,
4201                            /*timeout*/ timeout ? timeout : 5000);
4202
4203         /* Disable freezing the device queue */
4204         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4205
4206         if (arglist & CAM_ARG_ERR_RECOVER)
4207                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4208
4209         if (cam_send_ccb(device, ccb) < 0) {
4210                 warn("error sending READ CAPACITY command");
4211
4212                 if (arglist & CAM_ARG_VERBOSE)
4213                         cam_error_print(device, ccb, CAM_ESF_ALL,
4214                                         CAM_EPF_ALL, stderr);
4215
4216                 retval = 1;
4217                 goto bailout;
4218         }
4219
4220         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4221                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4222                 retval = 1;
4223                 goto bailout;
4224         }
4225
4226         maxsector = scsi_4btoul(rcap.addr);
4227         block_len = scsi_4btoul(rcap.length);
4228
4229         /*
4230          * A last block of 2^32-1 means that the true capacity is over 2TB,
4231          * and we need to issue the long READ CAPACITY to get the real
4232          * capacity.  Otherwise, we're all set.
4233          */
4234         if (maxsector != 0xffffffff)
4235                 goto do_print;
4236
4237         scsi_read_capacity_16(&ccb->csio,
4238                               /*retries*/ retry_count,
4239                               /*cbfcnp*/ NULL,
4240                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
4241                               /*lba*/ 0,
4242                               /*reladdr*/ 0,
4243                               /*pmi*/ 0,
4244                               &rcaplong,
4245                               /*sense_len*/ SSD_FULL_SIZE,
4246                               /*timeout*/ timeout ? timeout : 5000);
4247
4248         /* Disable freezing the device queue */
4249         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4250
4251         if (arglist & CAM_ARG_ERR_RECOVER)
4252                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4253
4254         if (cam_send_ccb(device, ccb) < 0) {
4255                 warn("error sending READ CAPACITY (16) command");
4256
4257                 if (arglist & CAM_ARG_VERBOSE)
4258                         cam_error_print(device, ccb, CAM_ESF_ALL,
4259                                         CAM_EPF_ALL, stderr);
4260
4261                 retval = 1;
4262                 goto bailout;
4263         }
4264
4265         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4266                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4267                 retval = 1;
4268                 goto bailout;
4269         }
4270
4271         maxsector = scsi_8btou64(rcaplong.addr);
4272         block_len = scsi_4btoul(rcaplong.length);
4273
4274 do_print:
4275         if (blocksizeonly == 0) {
4276                 /*
4277                  * Humanize implies !quiet, and also implies numblocks.
4278                  */
4279                 if (humanize != 0) {
4280                         char tmpstr[6];
4281                         int64_t tmpbytes;
4282                         int ret;
4283
4284                         tmpbytes = (maxsector + 1) * block_len;
4285                         ret = humanize_number(tmpstr, sizeof(tmpstr),
4286                                               tmpbytes, "", HN_AUTOSCALE,
4287                                               HN_B | HN_DECIMAL |
4288                                               ((baseten != 0) ?
4289                                               HN_DIVISOR_1000 : 0));
4290                         if (ret == -1) {
4291                                 warnx("%s: humanize_number failed!", __func__);
4292                                 retval = 1;
4293                                 goto bailout;
4294                         }
4295                         fprintf(stdout, "Device Size: %s%s", tmpstr,
4296                                 (sizeonly == 0) ?  ", " : "\n");
4297                 } else if (numblocks != 0) {
4298                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4299                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
4300                                 (sizeonly == 0) ? ", " : "\n");
4301                 } else {
4302                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4303                                 "Last Block: " : "", (uintmax_t)maxsector,
4304                                 (sizeonly == 0) ? ", " : "\n");
4305                 }
4306         }
4307         if (sizeonly == 0)
4308                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4309                         "Block Length: " : "", block_len, (quiet == 0) ?
4310                         " bytes" : "");
4311 bailout:
4312         cam_freeccb(ccb);
4313
4314         return (retval);
4315 }
4316
4317 static int
4318 atapm(struct cam_device *device, int argc, char **argv,
4319                  char *combinedopt, int retry_count, int timeout)
4320 {
4321         union ccb *ccb;
4322         int retval = 0;
4323         int t = -1;
4324         int c;
4325         u_char cmd, sc;
4326
4327         ccb = cam_getccb(device);
4328
4329         if (ccb == NULL) {
4330                 warnx("%s: error allocating ccb", __func__);
4331                 return (1);
4332         }
4333
4334         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4335                 switch (c) {
4336                 case 't':
4337                         t = atoi(optarg);
4338                         break;
4339                 default:
4340                         break;
4341                 }
4342         }
4343         if (strcmp(argv[1], "idle") == 0) {
4344                 if (t == -1)
4345                         cmd = ATA_IDLE_IMMEDIATE;
4346                 else
4347                         cmd = ATA_IDLE_CMD;
4348         } else if (strcmp(argv[1], "standby") == 0) {
4349                 if (t == -1)
4350                         cmd = ATA_STANDBY_IMMEDIATE;
4351                 else
4352                         cmd = ATA_STANDBY_CMD;
4353         } else {
4354                 cmd = ATA_SLEEP;
4355                 t = -1;
4356         }
4357
4358         if (t < 0)
4359                 sc = 0;
4360         else if (t <= (240 * 5))
4361                 sc = (t + 4) / 5;
4362         else if (t <= (252 * 5))
4363                 /* special encoding for 21 minutes */
4364                 sc = 252;
4365         else if (t <= (11 * 30 * 60))
4366                 sc = (t - 1) / (30 * 60) + 241;
4367         else
4368                 sc = 253;
4369
4370         cam_fill_ataio(&ccb->ataio,
4371                       retry_count,
4372                       NULL,
4373                       /*flags*/CAM_DIR_NONE,
4374                       MSG_SIMPLE_Q_TAG,
4375                       /*data_ptr*/NULL,
4376                       /*dxfer_len*/0,
4377                       timeout ? timeout : 30 * 1000);
4378         ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
4379
4380         /* Disable freezing the device queue */
4381         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4382
4383         if (arglist & CAM_ARG_ERR_RECOVER)
4384                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4385
4386         if (cam_send_ccb(device, ccb) < 0) {
4387                 warn("error sending command");
4388
4389                 if (arglist & CAM_ARG_VERBOSE)
4390                         cam_error_print(device, ccb, CAM_ESF_ALL,
4391                                         CAM_EPF_ALL, stderr);
4392
4393                 retval = 1;
4394                 goto bailout;
4395         }
4396
4397         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4398                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4399                 retval = 1;
4400                 goto bailout;
4401         }
4402 bailout:
4403         cam_freeccb(ccb);
4404         return (retval);
4405 }
4406
4407 #endif /* MINIMALISTIC */
4408
4409 void
4410 usage(int verbose)
4411 {
4412         fprintf(verbose ? stdout : stderr,
4413 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
4414 "        camcontrol devlist    [-v]\n"
4415 #ifndef MINIMALISTIC
4416 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
4417 "        camcontrol tur        [dev_id][generic args]\n"
4418 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
4419 "        camcontrol identify   [dev_id][generic args] [-v]\n"
4420 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
4421 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
4422 "                              [-q] [-s]\n"
4423 "        camcontrol start      [dev_id][generic args]\n"
4424 "        camcontrol stop       [dev_id][generic args]\n"
4425 "        camcontrol load       [dev_id][generic args]\n"
4426 "        camcontrol eject      [dev_id][generic args]\n"
4427 #endif /* MINIMALISTIC */
4428 "        camcontrol rescan     <all | bus[:target:lun]>\n"
4429 "        camcontrol reset      <all | bus[:target:lun]>\n"
4430 #ifndef MINIMALISTIC
4431 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
4432 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
4433 "                              [-P pagectl][-e | -b][-d]\n"
4434 "        camcontrol cmd        [dev_id][generic args]\n"
4435 "                              <-a cmd [args] | -c cmd [args]>\n"
4436 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
4437 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
4438 "                              <all|bus[:target[:lun]]|off>\n"
4439 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
4440 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
4441 "                              [-D <enable|disable>][-M mode][-O offset]\n"
4442 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
4443 "                              [-U][-W bus_width]\n"
4444 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
4445 "        camcontrol idle       [dev_id][generic args][-t time]\n"
4446 "        camcontrol standby    [dev_id][generic args][-t time]\n"
4447 "        camcontrol sleep      [dev_id][generic args]\n"
4448 #endif /* MINIMALISTIC */
4449 "        camcontrol help\n");
4450         if (!verbose)
4451                 return;
4452 #ifndef MINIMALISTIC
4453         fprintf(stdout,
4454 "Specify one of the following options:\n"
4455 "devlist     list all CAM devices\n"
4456 "periphlist  list all CAM peripheral drivers attached to a device\n"
4457 "tur         send a test unit ready to the named device\n"
4458 "inquiry     send a SCSI inquiry command to the named device\n"
4459 "identify    send a ATA identify command to the named device\n"
4460 "reportluns  send a SCSI report luns command to the device\n"
4461 "readcap     send a SCSI read capacity command to the device\n"
4462 "start       send a Start Unit command to the device\n"
4463 "stop        send a Stop Unit command to the device\n"
4464 "load        send a Start Unit command to the device with the load bit set\n"
4465 "eject       send a Stop Unit command to the device with the eject bit set\n"
4466 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
4467 "reset       reset all busses, the given bus, or bus:target:lun\n"
4468 "defects     read the defect list of the specified device\n"
4469 "modepage    display or edit (-e) the given mode page\n"
4470 "cmd         send the given scsi command, may need -i or -o as well\n"
4471 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
4472 "tags        report or set the number of transaction slots for a device\n"
4473 "negotiate   report or set device negotiation parameters\n"
4474 "format      send the SCSI FORMAT UNIT command to the named device\n"
4475 "idle        send the ATA IDLE command to the named device\n"
4476 "standby     send the ATA STANDBY command to the named device\n"
4477 "sleep       send the ATA SLEEP command to the named device\n"
4478 "help        this message\n"
4479 "Device Identifiers:\n"
4480 "bus:target        specify the bus and target, lun defaults to 0\n"
4481 "bus:target:lun    specify the bus, target and lun\n"
4482 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
4483 "Generic arguments:\n"
4484 "-v                be verbose, print out sense information\n"
4485 "-t timeout        command timeout in seconds, overrides default timeout\n"
4486 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
4487 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
4488 "-E                have the kernel attempt to perform SCSI error recovery\n"
4489 "-C count          specify the SCSI command retry count (needs -E to work)\n"
4490 "modepage arguments:\n"
4491 "-l                list all available mode pages\n"
4492 "-m page           specify the mode page to view or edit\n"
4493 "-e                edit the specified mode page\n"
4494 "-b                force view to binary mode\n"
4495 "-d                disable block descriptors for mode sense\n"
4496 "-P pgctl          page control field 0-3\n"
4497 "defects arguments:\n"
4498 "-f format         specify defect list format (block, bfi or phys)\n"
4499 "-G                get the grown defect list\n"
4500 "-P                get the permanant defect list\n"
4501 "inquiry arguments:\n"
4502 "-D                get the standard inquiry data\n"
4503 "-S                get the serial number\n"
4504 "-R                get the transfer rate, etc.\n"
4505 "reportluns arguments:\n"
4506 "-c                only report a count of available LUNs\n"
4507 "-l                only print out luns, and not a count\n"
4508 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
4509 "readcap arguments\n"
4510 "-b                only report the blocksize\n"
4511 "-h                human readable device size, base 2\n"
4512 "-H                human readable device size, base 10\n"
4513 "-N                print the number of blocks instead of last block\n"
4514 "-q                quiet, print numbers only\n"
4515 "-s                only report the last block/device size\n"
4516 "cmd arguments:\n"
4517 "-c cdb [args]     specify the SCSI CDB\n"
4518 "-i len fmt        specify input data and input data format\n"
4519 "-o len fmt [args] specify output data and output data fmt\n"
4520 "debug arguments:\n"
4521 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
4522 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
4523 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
4524 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
4525 "tags arguments:\n"
4526 "-N tags           specify the number of tags to use for this device\n"
4527 "-q                be quiet, don't report the number of tags\n"
4528 "-v                report a number of tag-related parameters\n"
4529 "negotiate arguments:\n"
4530 "-a                send a test unit ready after negotiation\n"
4531 "-c                report/set current negotiation settings\n"
4532 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
4533 "-M mode           set ATA mode\n"
4534 "-O offset         set command delay offset\n"
4535 "-q                be quiet, don't report anything\n"
4536 "-R syncrate       synchronization rate in MHz\n"
4537 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
4538 "-U                report/set user negotiation settings\n"
4539 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
4540 "-v                also print a Path Inquiry CCB for the controller\n"
4541 "format arguments:\n"
4542 "-q                be quiet, don't print status messages\n"
4543 "-r                run in report only mode\n"
4544 "-w                don't send immediate format command\n"
4545 "-y                don't ask any questions\n"
4546 "idle/standby arguments:\n"
4547 "-t <arg>          number of seconds before respective state.\n");
4548 #endif /* MINIMALISTIC */
4549 }
4550
4551 int
4552 main(int argc, char **argv)
4553 {
4554         int c;
4555         char *device = NULL;
4556         int unit = 0;
4557         struct cam_device *cam_dev = NULL;
4558         int timeout = 0, retry_count = 1;
4559         camcontrol_optret optreturn;
4560         char *tstr;
4561         const char *mainopt = "C:En:t:u:v";
4562         const char *subopt = NULL;
4563         char combinedopt[256];
4564         int error = 0, optstart = 2;
4565         int devopen = 1;
4566 #ifndef MINIMALISTIC
4567         int bus, target, lun;
4568 #endif /* MINIMALISTIC */
4569
4570         cmdlist = CAM_CMD_NONE;
4571         arglist = CAM_ARG_NONE;
4572
4573         if (argc < 2) {
4574                 usage(0);
4575                 exit(1);
4576         }
4577
4578         /*
4579          * Get the base option.
4580          */
4581         optreturn = getoption(argv[1], &cmdlist, &arglist, &subopt);
4582
4583         if (optreturn == CC_OR_AMBIGUOUS) {
4584                 warnx("ambiguous option %s", argv[1]);
4585                 usage(0);
4586                 exit(1);
4587         } else if (optreturn == CC_OR_NOT_FOUND) {
4588                 warnx("option %s not found", argv[1]);
4589                 usage(0);
4590                 exit(1);
4591         }
4592
4593         /*
4594          * Ahh, getopt(3) is a pain.
4595          *
4596          * This is a gross hack.  There really aren't many other good
4597          * options (excuse the pun) for parsing options in a situation like
4598          * this.  getopt is kinda braindead, so you end up having to run
4599          * through the options twice, and give each invocation of getopt
4600          * the option string for the other invocation.
4601          *
4602          * You would think that you could just have two groups of options.
4603          * The first group would get parsed by the first invocation of
4604          * getopt, and the second group would get parsed by the second
4605          * invocation of getopt.  It doesn't quite work out that way.  When
4606          * the first invocation of getopt finishes, it leaves optind pointing
4607          * to the argument _after_ the first argument in the second group.
4608          * So when the second invocation of getopt comes around, it doesn't
4609          * recognize the first argument it gets and then bails out.
4610          *
4611          * A nice alternative would be to have a flag for getopt that says
4612          * "just keep parsing arguments even when you encounter an unknown
4613          * argument", but there isn't one.  So there's no real clean way to
4614          * easily parse two sets of arguments without having one invocation
4615          * of getopt know about the other.
4616          *
4617          * Without this hack, the first invocation of getopt would work as
4618          * long as the generic arguments are first, but the second invocation
4619          * (in the subfunction) would fail in one of two ways.  In the case
4620          * where you don't set optreset, it would fail because optind may be
4621          * pointing to the argument after the one it should be pointing at.
4622          * In the case where you do set optreset, and reset optind, it would
4623          * fail because getopt would run into the first set of options, which
4624          * it doesn't understand.
4625          *
4626          * All of this would "sort of" work if you could somehow figure out
4627          * whether optind had been incremented one option too far.  The
4628          * mechanics of that, however, are more daunting than just giving
4629          * both invocations all of the expect options for either invocation.
4630          *
4631          * Needless to say, I wouldn't mind if someone invented a better
4632          * (non-GPL!) command line parsing interface than getopt.  I
4633          * wouldn't mind if someone added more knobs to getopt to make it
4634          * work better.  Who knows, I may talk myself into doing it someday,
4635          * if the standards weenies let me.  As it is, it just leads to
4636          * hackery like this and causes people to avoid it in some cases.
4637          *
4638          * KDM, September 8th, 1998
4639          */
4640         if (subopt != NULL)
4641                 sprintf(combinedopt, "%s%s", mainopt, subopt);
4642         else
4643                 sprintf(combinedopt, "%s", mainopt);
4644
4645         /*
4646          * For these options we do not parse optional device arguments and
4647          * we do not open a passthrough device.
4648          */
4649         if ((cmdlist == CAM_CMD_RESCAN)
4650          || (cmdlist == CAM_CMD_RESET)
4651          || (cmdlist == CAM_CMD_DEVTREE)
4652          || (cmdlist == CAM_CMD_USAGE)
4653          || (cmdlist == CAM_CMD_DEBUG))
4654                 devopen = 0;
4655
4656 #ifndef MINIMALISTIC
4657         if ((devopen == 1)
4658          && (argc > 2 && argv[2][0] != '-')) {
4659                 char name[30];
4660                 int rv;
4661
4662                 if (isdigit(argv[2][0])) {
4663                         /* device specified as bus:target[:lun] */
4664                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
4665                         if (rv < 2)
4666                                 errx(1, "numeric device specification must "
4667                                      "be either bus:target, or "
4668                                      "bus:target:lun");
4669                         /* default to 0 if lun was not specified */
4670                         if ((arglist & CAM_ARG_LUN) == 0) {
4671                                 lun = 0;
4672                                 arglist |= CAM_ARG_LUN;
4673                         }
4674                         optstart++;
4675                 } else {
4676                         if (cam_get_device(argv[2], name, sizeof name, &unit)
4677                             == -1)
4678                                 errx(1, "%s", cam_errbuf);
4679                         device = strdup(name);
4680                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
4681                         optstart++;
4682                 }
4683         }
4684 #endif /* MINIMALISTIC */
4685         /*
4686          * Start getopt processing at argv[2/3], since we've already
4687          * accepted argv[1..2] as the command name, and as a possible
4688          * device name.
4689          */
4690         optind = optstart;
4691
4692         /*
4693          * Now we run through the argument list looking for generic
4694          * options, and ignoring options that possibly belong to
4695          * subfunctions.
4696          */
4697         while ((c = getopt(argc, argv, combinedopt))!= -1){
4698                 switch(c) {
4699                         case 'C':
4700                                 retry_count = strtol(optarg, NULL, 0);
4701                                 if (retry_count < 0)
4702                                         errx(1, "retry count %d is < 0",
4703                                              retry_count);
4704                                 arglist |= CAM_ARG_RETRIES;
4705                                 break;
4706                         case 'E':
4707                                 arglist |= CAM_ARG_ERR_RECOVER;
4708                                 break;
4709                         case 'n':
4710                                 arglist |= CAM_ARG_DEVICE;
4711                                 tstr = optarg;
4712                                 while (isspace(*tstr) && (*tstr != '\0'))
4713                                         tstr++;
4714                                 device = (char *)strdup(tstr);
4715                                 break;
4716                         case 't':
4717                                 timeout = strtol(optarg, NULL, 0);
4718                                 if (timeout < 0)
4719                                         errx(1, "invalid timeout %d", timeout);
4720                                 /* Convert the timeout from seconds to ms */
4721                                 timeout *= 1000;
4722                                 arglist |= CAM_ARG_TIMEOUT;
4723                                 break;
4724                         case 'u':
4725                                 arglist |= CAM_ARG_UNIT;
4726                                 unit = strtol(optarg, NULL, 0);
4727                                 break;
4728                         case 'v':
4729                                 arglist |= CAM_ARG_VERBOSE;
4730                                 break;
4731                         default:
4732                                 break;
4733                 }
4734         }
4735
4736 #ifndef MINIMALISTIC
4737         /*
4738          * For most commands we'll want to open the passthrough device
4739          * associated with the specified device.  In the case of the rescan
4740          * commands, we don't use a passthrough device at all, just the
4741          * transport layer device.
4742          */
4743         if (devopen == 1) {
4744                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
4745                  && (((arglist & CAM_ARG_DEVICE) == 0)
4746                   || ((arglist & CAM_ARG_UNIT) == 0))) {
4747                         errx(1, "subcommand \"%s\" requires a valid device "
4748                              "identifier", argv[1]);
4749                 }
4750
4751                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
4752                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
4753                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
4754                      == NULL)
4755                         errx(1,"%s", cam_errbuf);
4756         }
4757 #endif /* MINIMALISTIC */
4758
4759         /*
4760          * Reset optind to 2, and reset getopt, so these routines can parse
4761          * the arguments again.
4762          */
4763         optind = optstart;
4764         optreset = 1;
4765
4766         switch(cmdlist) {
4767 #ifndef MINIMALISTIC
4768                 case CAM_CMD_DEVLIST:
4769                         error = getdevlist(cam_dev);
4770                         break;
4771 #endif /* MINIMALISTIC */
4772                 case CAM_CMD_DEVTREE:
4773                         error = getdevtree();
4774                         break;
4775 #ifndef MINIMALISTIC
4776                 case CAM_CMD_TUR:
4777                         error = testunitready(cam_dev, retry_count, timeout, 0);
4778                         break;
4779                 case CAM_CMD_INQUIRY:
4780                         error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
4781                                               retry_count, timeout);
4782                         break;
4783                 case CAM_CMD_IDENTIFY:
4784                         error = ataidentify(cam_dev, retry_count, timeout);
4785                         break;
4786                 case CAM_CMD_STARTSTOP:
4787                         error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
4788                                           arglist & CAM_ARG_EJECT, retry_count,
4789                                           timeout);
4790                         break;
4791 #endif /* MINIMALISTIC */
4792                 case CAM_CMD_RESCAN:
4793                         error = dorescan_or_reset(argc, argv, 1);
4794                         break;
4795                 case CAM_CMD_RESET:
4796                         error = dorescan_or_reset(argc, argv, 0);
4797                         break;
4798 #ifndef MINIMALISTIC
4799                 case CAM_CMD_READ_DEFECTS:
4800                         error = readdefects(cam_dev, argc, argv, combinedopt,
4801                                             retry_count, timeout);
4802                         break;
4803                 case CAM_CMD_MODE_PAGE:
4804                         modepage(cam_dev, argc, argv, combinedopt,
4805                                  retry_count, timeout);
4806                         break;
4807                 case CAM_CMD_SCSI_CMD:
4808                         error = scsicmd(cam_dev, argc, argv, combinedopt,
4809                                         retry_count, timeout);
4810                         break;
4811                 case CAM_CMD_DEBUG:
4812                         error = camdebug(argc, argv, combinedopt);
4813                         break;
4814                 case CAM_CMD_TAG:
4815                         error = tagcontrol(cam_dev, argc, argv, combinedopt);
4816                         break;
4817                 case CAM_CMD_RATE:
4818                         error = ratecontrol(cam_dev, retry_count, timeout,
4819                                             argc, argv, combinedopt);
4820                         break;
4821                 case CAM_CMD_FORMAT:
4822                         error = scsiformat(cam_dev, argc, argv,
4823                                            combinedopt, retry_count, timeout);
4824                         break;
4825                 case CAM_CMD_REPORTLUNS:
4826                         error = scsireportluns(cam_dev, argc, argv,
4827                                                combinedopt, retry_count,
4828                                                timeout);
4829                         break;
4830                 case CAM_CMD_READCAP:
4831                         error = scsireadcapacity(cam_dev, argc, argv,
4832                                                  combinedopt, retry_count,
4833                                                  timeout);
4834                         break;
4835                 case CAM_CMD_IDLE:
4836                 case CAM_CMD_STANDBY:
4837                 case CAM_CMD_SLEEP:
4838                         error = atapm(cam_dev, argc, argv,
4839                                                  combinedopt, retry_count,
4840                                                  timeout);
4841                         break;
4842 #endif /* MINIMALISTIC */
4843                 case CAM_CMD_USAGE:
4844                         usage(1);
4845                         break;
4846                 default:
4847                         usage(0);
4848                         error = 1;
4849                         break;
4850         }
4851
4852         if (cam_dev != NULL)
4853                 cam_close_device(cam_dev);
4854
4855         exit(error);
4856 }