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