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