]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sbin/camcontrol/camcontrol.c
MFC r204195:
[FreeBSD/stable/8.git] / sbin / camcontrol / camcontrol.c
1 /*
2  * Copyright (c) 1997-2007 Kenneth D. Merry
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/ioctl.h>
33 #include <sys/stdint.h>
34 #include <sys/types.h>
35 #include <sys/endian.h>
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <ctype.h>
43 #include <err.h>
44 #include <libutil.h>
45
46 #include <cam/cam.h>
47 #include <cam/cam_debug.h>
48 #include <cam/cam_ccb.h>
49 #include <cam/scsi/scsi_all.h>
50 #include <cam/scsi/scsi_da.h>
51 #include <cam/scsi/scsi_pass.h>
52 #include <cam/scsi/scsi_message.h>
53 #include <cam/ata/ata_all.h>
54 #include <camlib.h>
55 #include "camcontrol.h"
56
57 typedef enum {
58         CAM_CMD_NONE            = 0x00000000,
59         CAM_CMD_DEVLIST         = 0x00000001,
60         CAM_CMD_TUR             = 0x00000002,
61         CAM_CMD_INQUIRY         = 0x00000003,
62         CAM_CMD_STARTSTOP       = 0x00000004,
63         CAM_CMD_RESCAN          = 0x00000005,
64         CAM_CMD_READ_DEFECTS    = 0x00000006,
65         CAM_CMD_MODE_PAGE       = 0x00000007,
66         CAM_CMD_SCSI_CMD        = 0x00000008,
67         CAM_CMD_DEVTREE         = 0x00000009,
68         CAM_CMD_USAGE           = 0x0000000a,
69         CAM_CMD_DEBUG           = 0x0000000b,
70         CAM_CMD_RESET           = 0x0000000c,
71         CAM_CMD_FORMAT          = 0x0000000d,
72         CAM_CMD_TAG             = 0x0000000e,
73         CAM_CMD_RATE            = 0x0000000f,
74         CAM_CMD_DETACH          = 0x00000010,
75         CAM_CMD_REPORTLUNS      = 0x00000011,
76         CAM_CMD_READCAP         = 0x00000012,
77         CAM_CMD_IDENTIFY        = 0x00000013,
78         CAM_CMD_IDLE            = 0x00000014,
79         CAM_CMD_STANDBY         = 0x00000015,
80         CAM_CMD_SLEEP           = 0x00000016
81 } cam_cmdmask;
82
83 typedef enum {
84         CAM_ARG_NONE            = 0x00000000,
85         CAM_ARG_VERBOSE         = 0x00000001,
86         CAM_ARG_DEVICE          = 0x00000002,
87         CAM_ARG_BUS             = 0x00000004,
88         CAM_ARG_TARGET          = 0x00000008,
89         CAM_ARG_LUN             = 0x00000010,
90         CAM_ARG_EJECT           = 0x00000020,
91         CAM_ARG_UNIT            = 0x00000040,
92         CAM_ARG_FORMAT_BLOCK    = 0x00000080,
93         CAM_ARG_FORMAT_BFI      = 0x00000100,
94         CAM_ARG_FORMAT_PHYS     = 0x00000200,
95         CAM_ARG_PLIST           = 0x00000400,
96         CAM_ARG_GLIST           = 0x00000800,
97         CAM_ARG_GET_SERIAL      = 0x00001000,
98         CAM_ARG_GET_STDINQ      = 0x00002000,
99         CAM_ARG_GET_XFERRATE    = 0x00004000,
100         CAM_ARG_INQ_MASK        = 0x00007000,
101         CAM_ARG_MODE_EDIT       = 0x00008000,
102         CAM_ARG_PAGE_CNTL       = 0x00010000,
103         CAM_ARG_TIMEOUT         = 0x00020000,
104         CAM_ARG_CMD_IN          = 0x00040000,
105         CAM_ARG_CMD_OUT         = 0x00080000,
106         CAM_ARG_DBD             = 0x00100000,
107         CAM_ARG_ERR_RECOVER     = 0x00200000,
108         CAM_ARG_RETRIES         = 0x00400000,
109         CAM_ARG_START_UNIT      = 0x00800000,
110         CAM_ARG_DEBUG_INFO      = 0x01000000,
111         CAM_ARG_DEBUG_TRACE     = 0x02000000,
112         CAM_ARG_DEBUG_SUBTRACE  = 0x04000000,
113         CAM_ARG_DEBUG_CDB       = 0x08000000,
114         CAM_ARG_DEBUG_XPT       = 0x10000000,
115         CAM_ARG_DEBUG_PERIPH    = 0x20000000,
116 } cam_argmask;
117
118 struct camcontrol_opts {
119         const char      *optname;       
120         cam_cmdmask     cmdnum;
121         cam_argmask     argnum;
122         const char      *subopt;
123 };
124
125 #ifndef MINIMALISTIC
126 static const char scsicmd_opts[] = "a:c:i: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  Enable    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         if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1205                 printf("Native Command Queuing (NCQ)   %s       ",
1206                         parm->satacapabilities & ATA_SUPPORT_NCQ ?
1207                                 "yes" : "no");
1208                 if (parm->satacapabilities & ATA_SUPPORT_NCQ) {
1209                         printf("        %d tags\n",
1210                             ATA_QUEUE_LEN(parm->queue) + 1);
1211                 } else
1212                         printf("\n");
1213         }
1214         printf("SMART                          %s       %s\n",
1215                 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1216                 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1217         printf("microcode download             %s       %s\n",
1218                 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1219                 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1220         printf("security                       %s       %s\n",
1221                 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1222                 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1223         printf("power management               %s       %s\n",
1224                 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1225                 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1226         printf("advanced power management      %s       %s      %d/0x%02X\n",
1227                 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1228                 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1229                 parm->apm_value, parm->apm_value);
1230         printf("automatic acoustic management  %s       %s      "
1231                 "%d/0x%02X      %d/0x%02X\n",
1232                 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1233                 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1234                 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1235                 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1236                 ATA_ACOUSTIC_VENDOR(parm->acoustic),
1237                 ATA_ACOUSTIC_VENDOR(parm->acoustic));
1238         printf("media status notification      %s       %s\n",
1239                 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1240                 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1241         printf("power-up in Standby            %s       %s\n",
1242                 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1243                 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1244         printf("write-read-verify              %s       %s      %d/0x%x\n",
1245                 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1246                 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1247                 parm->wrv_mode, parm->wrv_mode);
1248         printf("unload                         %s       %s\n",
1249                 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1250                 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1251         printf("free-fall                      %s       %s\n",
1252                 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1253                 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1254         printf("data set management (TRIM)     %s\n",
1255                 parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1256 }
1257
1258
1259 static int
1260 ataidentify(struct cam_device *device, int retry_count, int timeout)
1261 {
1262         union ccb *ccb;
1263         struct ata_params *ident_buf;
1264         struct ccb_getdev cgd;
1265         u_int i, error = 0;
1266         int16_t *ptr;
1267
1268         if (get_cgd(device, &cgd) != 0) {
1269                 warnx("couldn't get CGD");
1270                 return(1);
1271         }
1272         ccb = cam_getccb(device);
1273
1274         if (ccb == NULL) {
1275                 warnx("couldn't allocate CCB");
1276                 return(1);
1277         }
1278
1279         /* cam_getccb cleans up the header, caller has to zero the payload */
1280         bzero(&(&ccb->ccb_h)[1],
1281               sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1282
1283         ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1284
1285         if (ptr == NULL) {
1286                 cam_freeccb(ccb);
1287                 warnx("can't malloc memory for identify\n");
1288                 return(1);
1289         }
1290         bzero(ptr, sizeof(struct ata_params));
1291
1292         cam_fill_ataio(&ccb->ataio,
1293                       retry_count,
1294                       NULL,
1295                       /*flags*/CAM_DIR_IN,
1296                       MSG_SIMPLE_Q_TAG,
1297                       /*data_ptr*/(u_int8_t *)ptr,
1298                       /*dxfer_len*/sizeof(struct ata_params),
1299                       timeout ? timeout : 30 * 1000);
1300         if (cgd.protocol == PROTO_ATA)
1301                 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1302         else
1303                 ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1304
1305         /* Disable freezing the device queue */
1306         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1307
1308         if (arglist & CAM_ARG_ERR_RECOVER)
1309                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1310
1311         if (cam_send_ccb(device, ccb) < 0) {
1312                 perror("error sending ATA identify");
1313
1314                 if (arglist & CAM_ARG_VERBOSE) {
1315                         cam_error_print(device, ccb, CAM_ESF_ALL,
1316                                         CAM_EPF_ALL, stderr);
1317                 }
1318
1319                 free(ptr);
1320                 cam_freeccb(ccb);
1321                 return(1);
1322         }
1323
1324         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1325                 error = 1;
1326
1327                 if (arglist & CAM_ARG_VERBOSE) {
1328                         cam_error_print(device, ccb, CAM_ESF_ALL,
1329                                         CAM_EPF_ALL, stderr);
1330                 }
1331         }
1332
1333         cam_freeccb(ccb);
1334
1335         if (error != 0) {
1336                 free(ptr);
1337                 return(error);
1338         }
1339
1340         for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1341                 ptr[i] = le16toh(ptr[i]);
1342         if (arglist & CAM_ARG_VERBOSE) {
1343                 fprintf(stdout, "%s%d: Raw identify data:\n",
1344                     device->device_name, device->dev_unit_num);
1345                 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1346                         if ((i % 8) == 0)
1347                             fprintf(stdout, " %3d: ", i);
1348                         fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1349                         if ((i % 8) == 7)
1350                             fprintf(stdout, "\n");
1351                 }
1352         }
1353         ident_buf = (struct ata_params *)ptr;
1354         if (strncmp(ident_buf->model, "FX", 2) &&
1355             strncmp(ident_buf->model, "NEC", 3) &&
1356             strncmp(ident_buf->model, "Pioneer", 7) &&
1357             strncmp(ident_buf->model, "SHARP", 5)) {
1358                 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1359                 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1360                 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1361                 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1362         }
1363         ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1364         ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1365         ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1366         ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1367         ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1368         ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1369         ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1370         ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1371             sizeof(ident_buf->media_serial));
1372
1373         fprintf(stdout, "%s%d: ", device->device_name,
1374                 device->dev_unit_num);
1375         ata_print_ident(ident_buf);
1376         camxferrate(device);
1377         atacapprint(ident_buf);
1378
1379         free(ident_buf);
1380
1381         return(0);
1382 }
1383 #endif /* MINIMALISTIC */
1384
1385 /*
1386  * Parse out a bus, or a bus, target and lun in the following
1387  * format:
1388  * bus
1389  * bus:target
1390  * bus:target:lun
1391  *
1392  * Returns the number of parsed components, or 0.
1393  */
1394 static int
1395 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1396 {
1397         char *tmpstr;
1398         int convs = 0;
1399
1400         while (isspace(*tstr) && (*tstr != '\0'))
1401                 tstr++;
1402
1403         tmpstr = (char *)strtok(tstr, ":");
1404         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1405                 *bus = strtol(tmpstr, NULL, 0);
1406                 *arglst |= CAM_ARG_BUS;
1407                 convs++;
1408                 tmpstr = (char *)strtok(NULL, ":");
1409                 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1410                         *target = strtol(tmpstr, NULL, 0);
1411                         *arglst |= CAM_ARG_TARGET;
1412                         convs++;
1413                         tmpstr = (char *)strtok(NULL, ":");
1414                         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1415                                 *lun = strtol(tmpstr, NULL, 0);
1416                                 *arglst |= CAM_ARG_LUN;
1417                                 convs++;
1418                         }
1419                 }
1420         }
1421
1422         return convs;
1423 }
1424
1425 static int
1426 dorescan_or_reset(int argc, char **argv, int rescan)
1427 {
1428         static const char must[] =
1429                 "you must specify \"all\", a bus, or a bus:target:lun to %s";
1430         int rv, error = 0;
1431         int bus = -1, target = -1, lun = -1;
1432         char *tstr;
1433
1434         if (argc < 3) {
1435                 warnx(must, rescan? "rescan" : "reset");
1436                 return(1);
1437         }
1438
1439         tstr = argv[optind];
1440         while (isspace(*tstr) && (*tstr != '\0'))
1441                 tstr++;
1442         if (strncasecmp(tstr, "all", strlen("all")) == 0)
1443                 arglist |= CAM_ARG_BUS;
1444         else {
1445                 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1446                 if (rv != 1 && rv != 3) {
1447                         warnx(must, rescan? "rescan" : "reset");
1448                         return(1);
1449                 }
1450         }
1451
1452         if ((arglist & CAM_ARG_BUS)
1453             && (arglist & CAM_ARG_TARGET)
1454             && (arglist & CAM_ARG_LUN))
1455                 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1456         else
1457                 error = rescan_or_reset_bus(bus, rescan);
1458
1459         return(error);
1460 }
1461
1462 static int
1463 rescan_or_reset_bus(int bus, int rescan)
1464 {
1465         union ccb ccb, matchccb;
1466         int fd, retval;
1467         int bufsize;
1468
1469         retval = 0;
1470
1471         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1472                 warnx("error opening transport layer device %s", XPT_DEVICE);
1473                 warn("%s", XPT_DEVICE);
1474                 return(1);
1475         }
1476
1477         if (bus != -1) {
1478                 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1479                 ccb.ccb_h.path_id = bus;
1480                 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1481                 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1482                 ccb.crcn.flags = CAM_FLAG_NONE;
1483
1484                 /* run this at a low priority */
1485                 ccb.ccb_h.pinfo.priority = 5;
1486
1487                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1488                         warn("CAMIOCOMMAND ioctl failed");
1489                         close(fd);
1490                         return(1);
1491                 }
1492
1493                 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1494                         fprintf(stdout, "%s of bus %d was successful\n",
1495                             rescan ? "Re-scan" : "Reset", bus);
1496                 } else {
1497                         fprintf(stdout, "%s of bus %d returned error %#x\n",
1498                                 rescan ? "Re-scan" : "Reset", bus,
1499                                 ccb.ccb_h.status & CAM_STATUS_MASK);
1500                         retval = 1;
1501                 }
1502
1503                 close(fd);
1504                 return(retval);
1505
1506         }
1507
1508
1509         /*
1510          * The right way to handle this is to modify the xpt so that it can
1511          * handle a wildcarded bus in a rescan or reset CCB.  At the moment
1512          * that isn't implemented, so instead we enumerate the busses and
1513          * send the rescan or reset to those busses in the case where the
1514          * given bus is -1 (wildcard).  We don't send a rescan or reset
1515          * to the xpt bus; sending a rescan to the xpt bus is effectively a
1516          * no-op, sending a rescan to the xpt bus would result in a status of
1517          * CAM_REQ_INVALID.
1518          */
1519         bzero(&(&matchccb.ccb_h)[1],
1520               sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1521         matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1522         bufsize = sizeof(struct dev_match_result) * 20;
1523         matchccb.cdm.match_buf_len = bufsize;
1524         matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1525         if (matchccb.cdm.matches == NULL) {
1526                 warnx("can't malloc memory for matches");
1527                 retval = 1;
1528                 goto bailout;
1529         }
1530         matchccb.cdm.num_matches = 0;
1531
1532         matchccb.cdm.num_patterns = 1;
1533         matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1534
1535         matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1536                 matchccb.cdm.pattern_buf_len);
1537         if (matchccb.cdm.patterns == NULL) {
1538                 warnx("can't malloc memory for patterns");
1539                 retval = 1;
1540                 goto bailout;
1541         }
1542         matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1543         matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1544
1545         do {
1546                 unsigned int i;
1547
1548                 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1549                         warn("CAMIOCOMMAND ioctl failed");
1550                         retval = 1;
1551                         goto bailout;
1552                 }
1553
1554                 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1555                  || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1556                    && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1557                         warnx("got CAM error %#x, CDM error %d\n",
1558                               matchccb.ccb_h.status, matchccb.cdm.status);
1559                         retval = 1;
1560                         goto bailout;
1561                 }
1562
1563                 for (i = 0; i < matchccb.cdm.num_matches; i++) {
1564                         struct bus_match_result *bus_result;
1565
1566                         /* This shouldn't happen. */
1567                         if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1568                                 continue;
1569
1570                         bus_result = &matchccb.cdm.matches[i].result.bus_result;
1571
1572                         /*
1573                          * We don't want to rescan or reset the xpt bus.
1574                          * See above.
1575                          */
1576                         if ((int)bus_result->path_id == -1)
1577                                 continue;
1578
1579                         ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1580                                                        XPT_RESET_BUS;
1581                         ccb.ccb_h.path_id = bus_result->path_id;
1582                         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1583                         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1584                         ccb.crcn.flags = CAM_FLAG_NONE;
1585
1586                         /* run this at a low priority */
1587                         ccb.ccb_h.pinfo.priority = 5;
1588
1589                         if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1590                                 warn("CAMIOCOMMAND ioctl failed");
1591                                 retval = 1;
1592                                 goto bailout;
1593                         }
1594
1595                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1596                                 fprintf(stdout, "%s of bus %d was successful\n",
1597                                         rescan? "Re-scan" : "Reset",
1598                                         bus_result->path_id);
1599                         } else {
1600                                 /*
1601                                  * Don't bail out just yet, maybe the other
1602                                  * rescan or reset commands will complete
1603                                  * successfully.
1604                                  */
1605                                 fprintf(stderr, "%s of bus %d returned error "
1606                                         "%#x\n", rescan? "Re-scan" : "Reset",
1607                                         bus_result->path_id,
1608                                         ccb.ccb_h.status & CAM_STATUS_MASK);
1609                                 retval = 1;
1610                         }
1611                 }
1612         } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1613                  && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1614
1615 bailout:
1616
1617         if (fd != -1)
1618                 close(fd);
1619
1620         if (matchccb.cdm.patterns != NULL)
1621                 free(matchccb.cdm.patterns);
1622         if (matchccb.cdm.matches != NULL)
1623                 free(matchccb.cdm.matches);
1624
1625         return(retval);
1626 }
1627
1628 static int
1629 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1630 {
1631         union ccb ccb;
1632         struct cam_device *device;
1633         int fd;
1634
1635         device = NULL;
1636
1637         if (bus < 0) {
1638                 warnx("invalid bus number %d", bus);
1639                 return(1);
1640         }
1641
1642         if (target < 0) {
1643                 warnx("invalid target number %d", target);
1644                 return(1);
1645         }
1646
1647         if (lun < 0) {
1648                 warnx("invalid lun number %d", lun);
1649                 return(1);
1650         }
1651
1652         fd = -1;
1653
1654         bzero(&ccb, sizeof(union ccb));
1655
1656         if (scan) {
1657                 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1658                         warnx("error opening transport layer device %s\n",
1659                             XPT_DEVICE);
1660                         warn("%s", XPT_DEVICE);
1661                         return(1);
1662                 }
1663         } else {
1664                 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1665                 if (device == NULL) {
1666                         warnx("%s", cam_errbuf);
1667                         return(1);
1668                 }
1669         }
1670
1671         ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1672         ccb.ccb_h.path_id = bus;
1673         ccb.ccb_h.target_id = target;
1674         ccb.ccb_h.target_lun = lun;
1675         ccb.ccb_h.timeout = 5000;
1676         ccb.crcn.flags = CAM_FLAG_NONE;
1677
1678         /* run this at a low priority */
1679         ccb.ccb_h.pinfo.priority = 5;
1680
1681         if (scan) {
1682                 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1683                         warn("CAMIOCOMMAND ioctl failed");
1684                         close(fd);
1685                         return(1);
1686                 }
1687         } else {
1688                 if (cam_send_ccb(device, &ccb) < 0) {
1689                         warn("error sending XPT_RESET_DEV CCB");
1690                         cam_close_device(device);
1691                         return(1);
1692                 }
1693         }
1694
1695         if (scan)
1696                 close(fd);
1697         else
1698                 cam_close_device(device);
1699
1700         /*
1701          * An error code of CAM_BDR_SENT is normal for a BDR request.
1702          */
1703         if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1704          || ((!scan)
1705           && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1706                 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1707                     scan? "Re-scan" : "Reset", bus, target, lun);
1708                 return(0);
1709         } else {
1710                 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1711                     scan? "Re-scan" : "Reset", bus, target, lun,
1712                     ccb.ccb_h.status & CAM_STATUS_MASK);
1713                 return(1);
1714         }
1715 }
1716
1717 #ifndef MINIMALISTIC
1718 static int
1719 readdefects(struct cam_device *device, int argc, char **argv,
1720             char *combinedopt, int retry_count, int timeout)
1721 {
1722         union ccb *ccb = NULL;
1723         struct scsi_read_defect_data_10 *rdd_cdb;
1724         u_int8_t *defect_list = NULL;
1725         u_int32_t dlist_length = 65000;
1726         u_int32_t returned_length = 0;
1727         u_int32_t num_returned = 0;
1728         u_int8_t returned_format;
1729         unsigned int i;
1730         int c, error = 0;
1731         int lists_specified = 0;
1732
1733         while ((c = getopt(argc, argv, combinedopt)) != -1) {
1734                 switch(c){
1735                 case 'f':
1736                 {
1737                         char *tstr;
1738                         tstr = optarg;
1739                         while (isspace(*tstr) && (*tstr != '\0'))
1740                                 tstr++;
1741                         if (strcmp(tstr, "block") == 0)
1742                                 arglist |= CAM_ARG_FORMAT_BLOCK;
1743                         else if (strcmp(tstr, "bfi") == 0)
1744                                 arglist |= CAM_ARG_FORMAT_BFI;
1745                         else if (strcmp(tstr, "phys") == 0)
1746                                 arglist |= CAM_ARG_FORMAT_PHYS;
1747                         else {
1748                                 error = 1;
1749                                 warnx("invalid defect format %s", tstr);
1750                                 goto defect_bailout;
1751                         }
1752                         break;
1753                 }
1754                 case 'G':
1755                         arglist |= CAM_ARG_GLIST;
1756                         break;
1757                 case 'P':
1758                         arglist |= CAM_ARG_PLIST;
1759                         break;
1760                 default:
1761                         break;
1762                 }
1763         }
1764
1765         ccb = cam_getccb(device);
1766
1767         /*
1768          * Hopefully 65000 bytes is enough to hold the defect list.  If it
1769          * isn't, the disk is probably dead already.  We'd have to go with
1770          * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1771          * to hold them all.
1772          */
1773         defect_list = malloc(dlist_length);
1774         if (defect_list == NULL) {
1775                 warnx("can't malloc memory for defect list");
1776                 error = 1;
1777                 goto defect_bailout;
1778         }
1779
1780         rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1781
1782         /*
1783          * cam_getccb() zeros the CCB header only.  So we need to zero the
1784          * payload portion of the ccb.
1785          */
1786         bzero(&(&ccb->ccb_h)[1],
1787               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1788
1789         cam_fill_csio(&ccb->csio,
1790                       /*retries*/ retry_count,
1791                       /*cbfcnp*/ NULL,
1792                       /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1793                                               CAM_PASS_ERR_RECOVER : 0),
1794                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
1795                       /*data_ptr*/ defect_list,
1796                       /*dxfer_len*/ dlist_length,
1797                       /*sense_len*/ SSD_FULL_SIZE,
1798                       /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1799                       /*timeout*/ timeout ? timeout : 5000);
1800
1801         rdd_cdb->opcode = READ_DEFECT_DATA_10;
1802         if (arglist & CAM_ARG_FORMAT_BLOCK)
1803                 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1804         else if (arglist & CAM_ARG_FORMAT_BFI)
1805                 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1806         else if (arglist & CAM_ARG_FORMAT_PHYS)
1807                 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1808         else {
1809                 error = 1;
1810                 warnx("no defect list format specified");
1811                 goto defect_bailout;
1812         }
1813         if (arglist & CAM_ARG_PLIST) {
1814                 rdd_cdb->format |= SRDD10_PLIST;
1815                 lists_specified++;
1816         }
1817
1818         if (arglist & CAM_ARG_GLIST) {
1819                 rdd_cdb->format |= SRDD10_GLIST;
1820                 lists_specified++;
1821         }
1822
1823         scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1824
1825         /* Disable freezing the device queue */
1826         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1827
1828         if (cam_send_ccb(device, ccb) < 0) {
1829                 perror("error reading defect list");
1830
1831                 if (arglist & CAM_ARG_VERBOSE) {
1832                         cam_error_print(device, ccb, CAM_ESF_ALL,
1833                                         CAM_EPF_ALL, stderr);
1834                 }
1835
1836                 error = 1;
1837                 goto defect_bailout;
1838         }
1839
1840         returned_length = scsi_2btoul(((struct
1841                 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1842
1843         returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1844                         defect_list)->format;
1845
1846         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1847          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1848          && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1849                 struct scsi_sense_data *sense;
1850                 int error_code, sense_key, asc, ascq;
1851
1852                 sense = &ccb->csio.sense_data;
1853                 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1854
1855                 /*
1856                  * According to the SCSI spec, if the disk doesn't support
1857                  * the requested format, it will generally return a sense
1858                  * key of RECOVERED ERROR, and an additional sense code
1859                  * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1860                  * also check to make sure that the returned length is
1861                  * greater than 0, and then print out whatever format the
1862                  * disk gave us.
1863                  */
1864                 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1865                  && (asc == 0x1c) && (ascq == 0x00)
1866                  && (returned_length > 0)) {
1867                         warnx("requested defect format not available");
1868                         switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1869                         case SRDD10_BLOCK_FORMAT:
1870                                 warnx("Device returned block format");
1871                                 break;
1872                         case SRDD10_BYTES_FROM_INDEX_FORMAT:
1873                                 warnx("Device returned bytes from index"
1874                                       " format");
1875                                 break;
1876                         case SRDD10_PHYSICAL_SECTOR_FORMAT:
1877                                 warnx("Device returned physical sector format");
1878                                 break;
1879                         default:
1880                                 error = 1;
1881                                 warnx("Device returned unknown defect"
1882                                      " data format %#x", returned_format);
1883                                 goto defect_bailout;
1884                                 break; /* NOTREACHED */
1885                         }
1886                 } else {
1887                         error = 1;
1888                         warnx("Error returned from read defect data command");
1889                         if (arglist & CAM_ARG_VERBOSE)
1890                                 cam_error_print(device, ccb, CAM_ESF_ALL,
1891                                                 CAM_EPF_ALL, stderr);
1892                         goto defect_bailout;
1893                 }
1894         } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1895                 error = 1;
1896                 warnx("Error returned from read defect data command");
1897                 if (arglist & CAM_ARG_VERBOSE)
1898                         cam_error_print(device, ccb, CAM_ESF_ALL,
1899                                         CAM_EPF_ALL, stderr);
1900                 goto defect_bailout;
1901         }
1902
1903         /*
1904          * XXX KDM  I should probably clean up the printout format for the
1905          * disk defects. 
1906          */
1907         switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1908                 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1909                 {
1910                         struct scsi_defect_desc_phys_sector *dlist;
1911
1912                         dlist = (struct scsi_defect_desc_phys_sector *)
1913                                 (defect_list +
1914                                 sizeof(struct scsi_read_defect_data_hdr_10));
1915
1916                         num_returned = returned_length /
1917                                 sizeof(struct scsi_defect_desc_phys_sector);
1918
1919                         fprintf(stderr, "Got %d defect", num_returned);
1920
1921                         if ((lists_specified == 0) || (num_returned == 0)) {
1922                                 fprintf(stderr, "s.\n");
1923                                 break;
1924                         } else if (num_returned == 1)
1925                                 fprintf(stderr, ":\n");
1926                         else
1927                                 fprintf(stderr, "s:\n");
1928
1929                         for (i = 0; i < num_returned; i++) {
1930                                 fprintf(stdout, "%d:%d:%d\n",
1931                                         scsi_3btoul(dlist[i].cylinder),
1932                                         dlist[i].head,
1933                                         scsi_4btoul(dlist[i].sector));
1934                         }
1935                         break;
1936                 }
1937                 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1938                 {
1939                         struct scsi_defect_desc_bytes_from_index *dlist;
1940
1941                         dlist = (struct scsi_defect_desc_bytes_from_index *)
1942                                 (defect_list +
1943                                 sizeof(struct scsi_read_defect_data_hdr_10));
1944
1945                         num_returned = returned_length /
1946                               sizeof(struct scsi_defect_desc_bytes_from_index);
1947
1948                         fprintf(stderr, "Got %d defect", num_returned);
1949
1950                         if ((lists_specified == 0) || (num_returned == 0)) {
1951                                 fprintf(stderr, "s.\n");
1952                                 break;
1953                         } else if (num_returned == 1)
1954                                 fprintf(stderr, ":\n");
1955                         else
1956                                 fprintf(stderr, "s:\n");
1957
1958                         for (i = 0; i < num_returned; i++) {
1959                                 fprintf(stdout, "%d:%d:%d\n",
1960                                         scsi_3btoul(dlist[i].cylinder),
1961                                         dlist[i].head,
1962                                         scsi_4btoul(dlist[i].bytes_from_index));
1963                         }
1964                         break;
1965                 }
1966                 case SRDDH10_BLOCK_FORMAT:
1967                 {
1968                         struct scsi_defect_desc_block *dlist;
1969
1970                         dlist = (struct scsi_defect_desc_block *)(defect_list +
1971                                 sizeof(struct scsi_read_defect_data_hdr_10));
1972
1973                         num_returned = returned_length /
1974                               sizeof(struct scsi_defect_desc_block);
1975
1976                         fprintf(stderr, "Got %d defect", num_returned);
1977
1978                         if ((lists_specified == 0) || (num_returned == 0)) {
1979                                 fprintf(stderr, "s.\n");
1980                                 break;
1981                         } else if (num_returned == 1)
1982                                 fprintf(stderr, ":\n");
1983                         else
1984                                 fprintf(stderr, "s:\n");
1985
1986                         for (i = 0; i < num_returned; i++)
1987                                 fprintf(stdout, "%u\n",
1988                                         scsi_4btoul(dlist[i].address));
1989                         break;
1990                 }
1991                 default:
1992                         fprintf(stderr, "Unknown defect format %d\n",
1993                                 returned_format & SRDDH10_DLIST_FORMAT_MASK);
1994                         error = 1;
1995                         break;
1996         }
1997 defect_bailout:
1998
1999         if (defect_list != NULL)
2000                 free(defect_list);
2001
2002         if (ccb != NULL)
2003                 cam_freeccb(ccb);
2004
2005         return(error);
2006 }
2007 #endif /* MINIMALISTIC */
2008
2009 #if 0
2010 void
2011 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2012 {
2013         union ccb *ccb;
2014         
2015         ccb = cam_getccb(device);
2016
2017         cam_freeccb(ccb);
2018 }
2019 #endif
2020
2021 #ifndef MINIMALISTIC
2022 void
2023 mode_sense(struct cam_device *device, int mode_page, int page_control,
2024            int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2025 {
2026         union ccb *ccb;
2027         int retval;
2028
2029         ccb = cam_getccb(device);
2030
2031         if (ccb == NULL)
2032                 errx(1, "mode_sense: couldn't allocate CCB");
2033
2034         bzero(&(&ccb->ccb_h)[1],
2035               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2036
2037         scsi_mode_sense(&ccb->csio,
2038                         /* retries */ retry_count,
2039                         /* cbfcnp */ NULL,
2040                         /* tag_action */ MSG_SIMPLE_Q_TAG,
2041                         /* dbd */ dbd,
2042                         /* page_code */ page_control << 6,
2043                         /* page */ mode_page,
2044                         /* param_buf */ data,
2045                         /* param_len */ datalen,
2046                         /* sense_len */ SSD_FULL_SIZE,
2047                         /* timeout */ timeout ? timeout : 5000);
2048
2049         if (arglist & CAM_ARG_ERR_RECOVER)
2050                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2051
2052         /* Disable freezing the device queue */
2053         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2054
2055         if (((retval = cam_send_ccb(device, ccb)) < 0)
2056          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2057                 if (arglist & CAM_ARG_VERBOSE) {
2058                         cam_error_print(device, ccb, CAM_ESF_ALL,
2059                                         CAM_EPF_ALL, stderr);
2060                 }
2061                 cam_freeccb(ccb);
2062                 cam_close_device(device);
2063                 if (retval < 0)
2064                         err(1, "error sending mode sense command");
2065                 else
2066                         errx(1, "error sending mode sense command");
2067         }
2068
2069         cam_freeccb(ccb);
2070 }
2071
2072 void
2073 mode_select(struct cam_device *device, int save_pages, int retry_count,
2074            int timeout, u_int8_t *data, int datalen)
2075 {
2076         union ccb *ccb;
2077         int retval;
2078
2079         ccb = cam_getccb(device);
2080
2081         if (ccb == NULL)
2082                 errx(1, "mode_select: couldn't allocate CCB");
2083
2084         bzero(&(&ccb->ccb_h)[1],
2085               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2086
2087         scsi_mode_select(&ccb->csio,
2088                          /* retries */ retry_count,
2089                          /* cbfcnp */ NULL,
2090                          /* tag_action */ MSG_SIMPLE_Q_TAG,
2091                          /* scsi_page_fmt */ 1,
2092                          /* save_pages */ save_pages,
2093                          /* param_buf */ data,
2094                          /* param_len */ datalen,
2095                          /* sense_len */ SSD_FULL_SIZE,
2096                          /* timeout */ timeout ? timeout : 5000);
2097
2098         if (arglist & CAM_ARG_ERR_RECOVER)
2099                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2100
2101         /* Disable freezing the device queue */
2102         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2103
2104         if (((retval = cam_send_ccb(device, ccb)) < 0)
2105          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2106                 if (arglist & CAM_ARG_VERBOSE) {
2107                         cam_error_print(device, ccb, CAM_ESF_ALL,
2108                                         CAM_EPF_ALL, stderr);
2109                 }
2110                 cam_freeccb(ccb);
2111                 cam_close_device(device);
2112
2113                 if (retval < 0)
2114                         err(1, "error sending mode select command");
2115                 else
2116                         errx(1, "error sending mode select command");
2117                 
2118         }
2119
2120         cam_freeccb(ccb);
2121 }
2122
2123 void
2124 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2125          int retry_count, int timeout)
2126 {
2127         int c, mode_page = -1, page_control = 0;
2128         int binary = 0, list = 0;
2129
2130         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2131                 switch(c) {
2132                 case 'b':
2133                         binary = 1;
2134                         break;
2135                 case 'd':
2136                         arglist |= CAM_ARG_DBD;
2137                         break;
2138                 case 'e':
2139                         arglist |= CAM_ARG_MODE_EDIT;
2140                         break;
2141                 case 'l':
2142                         list = 1;
2143                         break;
2144                 case 'm':
2145                         mode_page = strtol(optarg, NULL, 0);
2146                         if (mode_page < 0)
2147                                 errx(1, "invalid mode page %d", mode_page);
2148                         break;
2149                 case 'P':
2150                         page_control = strtol(optarg, NULL, 0);
2151                         if ((page_control < 0) || (page_control > 3))
2152                                 errx(1, "invalid page control field %d",
2153                                      page_control);
2154                         arglist |= CAM_ARG_PAGE_CNTL;
2155                         break;
2156                 default:
2157                         break;
2158                 }
2159         }
2160
2161         if (mode_page == -1 && list == 0)
2162                 errx(1, "you must specify a mode page!");
2163
2164         if (list) {
2165                 mode_list(device, page_control, arglist & CAM_ARG_DBD,
2166                     retry_count, timeout);
2167         } else {
2168                 mode_edit(device, mode_page, page_control,
2169                     arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2170                     retry_count, timeout);
2171         }
2172 }
2173
2174 static int
2175 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2176         int retry_count, int timeout)
2177 {
2178         union ccb *ccb;
2179         u_int32_t flags = CAM_DIR_NONE;
2180         u_int8_t *data_ptr = NULL;
2181         u_int8_t cdb[20];
2182         u_int8_t atacmd[12];
2183         struct get_hook hook;
2184         int c, data_bytes = 0;
2185         int cdb_len = 0;
2186         int atacmd_len = 0;
2187         int need_res = 0;
2188         char *datastr = NULL, *tstr, *resstr = NULL;
2189         int error = 0;
2190         int fd_data = 0, fd_res = 0;
2191         int retval;
2192
2193         ccb = cam_getccb(device);
2194
2195         if (ccb == NULL) {
2196                 warnx("scsicmd: error allocating ccb");
2197                 return(1);
2198         }
2199
2200         bzero(&(&ccb->ccb_h)[1],
2201               sizeof(union ccb) - sizeof(struct ccb_hdr));
2202
2203         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2204                 switch(c) {
2205                 case 'a':
2206                         tstr = optarg;
2207                         while (isspace(*tstr) && (*tstr != '\0'))
2208                                 tstr++;
2209                         hook.argc = argc - optind;
2210                         hook.argv = argv + optind;
2211                         hook.got = 0;
2212                         atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2213                                                     iget, &hook);
2214                         /*
2215                          * Increment optind by the number of arguments the
2216                          * encoding routine processed.  After each call to
2217                          * getopt(3), optind points to the argument that
2218                          * getopt should process _next_.  In this case,
2219                          * that means it points to the first command string
2220                          * argument, if there is one.  Once we increment
2221                          * this, it should point to either the next command
2222                          * line argument, or it should be past the end of
2223                          * the list.
2224                          */
2225                         optind += hook.got;
2226                         break;
2227                 case 'c':
2228                         tstr = optarg;
2229                         while (isspace(*tstr) && (*tstr != '\0'))
2230                                 tstr++;
2231                         hook.argc = argc - optind;
2232                         hook.argv = argv + optind;
2233                         hook.got = 0;
2234                         cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2235                                                     iget, &hook);
2236                         /*
2237                          * Increment optind by the number of arguments the
2238                          * encoding routine processed.  After each call to
2239                          * getopt(3), optind points to the argument that
2240                          * getopt should process _next_.  In this case,
2241                          * that means it points to the first command string
2242                          * argument, if there is one.  Once we increment
2243                          * this, it should point to either the next command
2244                          * line argument, or it should be past the end of
2245                          * the list.
2246                          */
2247                         optind += hook.got;
2248                         break;
2249                 case 'i':
2250                         if (arglist & CAM_ARG_CMD_OUT) {
2251                                 warnx("command must either be "
2252                                       "read or write, not both");
2253                                 error = 1;
2254                                 goto scsicmd_bailout;
2255                         }
2256                         arglist |= CAM_ARG_CMD_IN;
2257                         flags = CAM_DIR_IN;
2258                         data_bytes = strtol(optarg, NULL, 0);
2259                         if (data_bytes <= 0) {
2260                                 warnx("invalid number of input bytes %d",
2261                                       data_bytes);
2262                                 error = 1;
2263                                 goto scsicmd_bailout;
2264                         }
2265                         hook.argc = argc - optind;
2266                         hook.argv = argv + optind;
2267                         hook.got = 0;
2268                         optind++;
2269                         datastr = cget(&hook, NULL);
2270                         /*
2271                          * If the user supplied "-" instead of a format, he
2272                          * wants the data to be written to stdout.
2273                          */
2274                         if ((datastr != NULL)
2275                          && (datastr[0] == '-'))
2276                                 fd_data = 1;
2277
2278                         data_ptr = (u_int8_t *)malloc(data_bytes);
2279                         if (data_ptr == NULL) {
2280                                 warnx("can't malloc memory for data_ptr");
2281                                 error = 1;
2282                                 goto scsicmd_bailout;
2283                         }
2284                         break;
2285                 case 'o':
2286                         if (arglist & CAM_ARG_CMD_IN) {
2287                                 warnx("command must either be "
2288                                       "read or write, not both");
2289                                 error = 1;      
2290                                 goto scsicmd_bailout;
2291                         }
2292                         arglist |= CAM_ARG_CMD_OUT;
2293                         flags = CAM_DIR_OUT;
2294                         data_bytes = strtol(optarg, NULL, 0);
2295                         if (data_bytes <= 0) {
2296                                 warnx("invalid number of output bytes %d",
2297                                       data_bytes);
2298                                 error = 1;
2299                                 goto scsicmd_bailout;
2300                         }
2301                         hook.argc = argc - optind;
2302                         hook.argv = argv + optind;
2303                         hook.got = 0;
2304                         datastr = cget(&hook, NULL);
2305                         data_ptr = (u_int8_t *)malloc(data_bytes);
2306                         if (data_ptr == NULL) {
2307                                 warnx("can't malloc memory for data_ptr");
2308                                 error = 1;
2309                                 goto scsicmd_bailout;
2310                         }
2311                         bzero(data_ptr, data_bytes);
2312                         /*
2313                          * If the user supplied "-" instead of a format, he
2314                          * wants the data to be read from stdin.
2315                          */
2316                         if ((datastr != NULL)
2317                          && (datastr[0] == '-'))
2318                                 fd_data = 1;
2319                         else
2320                                 buff_encode_visit(data_ptr, data_bytes, datastr,
2321                                                   iget, &hook);
2322                         optind += hook.got;
2323                         break;
2324                 case 'r':
2325                         need_res = 1;
2326                         hook.argc = argc - optind;
2327                         hook.argv = argv + optind;
2328                         hook.got = 0;
2329                         resstr = cget(&hook, NULL);
2330                         if ((resstr != NULL) && (resstr[0] == '-'))
2331                                 fd_res = 1;
2332                         optind += hook.got;
2333                         break;
2334                 default:
2335                         break;
2336                 }
2337         }
2338
2339         /*
2340          * If fd_data is set, and we're writing to the device, we need to
2341          * read the data the user wants written from stdin.
2342          */
2343         if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2344                 ssize_t amt_read;
2345                 int amt_to_read = data_bytes;
2346                 u_int8_t *buf_ptr = data_ptr;
2347
2348                 for (amt_read = 0; amt_to_read > 0;
2349                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2350                         if (amt_read == -1) {
2351                                 warn("error reading data from stdin");
2352                                 error = 1;
2353                                 goto scsicmd_bailout;
2354                         }
2355                         amt_to_read -= amt_read;
2356                         buf_ptr += amt_read;
2357                 }
2358         }
2359
2360         if (arglist & CAM_ARG_ERR_RECOVER)
2361                 flags |= CAM_PASS_ERR_RECOVER;
2362
2363         /* Disable freezing the device queue */
2364         flags |= CAM_DEV_QFRZDIS;
2365
2366         if (cdb_len) {
2367                 /*
2368                  * This is taken from the SCSI-3 draft spec.
2369                  * (T10/1157D revision 0.3)
2370                  * The top 3 bits of an opcode are the group code.
2371                  * The next 5 bits are the command code.
2372                  * Group 0:  six byte commands
2373                  * Group 1:  ten byte commands
2374                  * Group 2:  ten byte commands
2375                  * Group 3:  reserved
2376                  * Group 4:  sixteen byte commands
2377                  * Group 5:  twelve byte commands
2378                  * Group 6:  vendor specific
2379                  * Group 7:  vendor specific
2380                  */
2381                 switch((cdb[0] >> 5) & 0x7) {
2382                         case 0:
2383                                 cdb_len = 6;
2384                                 break;
2385                         case 1:
2386                         case 2:
2387                                 cdb_len = 10;
2388                                 break;
2389                         case 3:
2390                         case 6:
2391                         case 7:
2392                                 /* computed by buff_encode_visit */
2393                                 break;
2394                         case 4:
2395                                 cdb_len = 16;
2396                                 break;
2397                         case 5:
2398                                 cdb_len = 12;
2399                                 break;
2400                 }
2401
2402                 /*
2403                  * We should probably use csio_build_visit or something like that
2404                  * here, but it's easier to encode arguments as you go.  The
2405                  * alternative would be skipping the CDB argument and then encoding
2406                  * it here, since we've got the data buffer argument by now.
2407                  */
2408                 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2409
2410                 cam_fill_csio(&ccb->csio,
2411                       /*retries*/ retry_count,
2412                       /*cbfcnp*/ NULL,
2413                       /*flags*/ flags,
2414                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
2415                       /*data_ptr*/ data_ptr,
2416                       /*dxfer_len*/ data_bytes,
2417                       /*sense_len*/ SSD_FULL_SIZE,
2418                       /*cdb_len*/ cdb_len,
2419                       /*timeout*/ timeout ? timeout : 5000);
2420         } else {
2421                 atacmd_len = 12;
2422                 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2423                 if (need_res)
2424                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2425
2426                 cam_fill_ataio(&ccb->ataio,
2427                       /*retries*/ retry_count,
2428                       /*cbfcnp*/ NULL,
2429                       /*flags*/ flags,
2430                       /*tag_action*/ 0,
2431                       /*data_ptr*/ data_ptr,
2432                       /*dxfer_len*/ data_bytes,
2433                       /*timeout*/ timeout ? timeout : 5000);
2434         }
2435
2436         if (((retval = cam_send_ccb(device, ccb)) < 0)
2437          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2438                 if (retval < 0)
2439                         warn("error sending command");
2440                 else
2441                         warnx("error sending command");
2442
2443                 if (arglist & CAM_ARG_VERBOSE) {
2444                         cam_error_print(device, ccb, CAM_ESF_ALL,
2445                                         CAM_EPF_ALL, stderr);
2446                 }
2447
2448                 error = 1;
2449                 goto scsicmd_bailout;
2450         }
2451
2452         if (atacmd_len && need_res) {
2453                 if (fd_res == 0) {
2454                         buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2455                                           arg_put, NULL);
2456                         fprintf(stdout, "\n");
2457                 } else {
2458                         fprintf(stdout,
2459                             "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2460                             ccb->ataio.res.status,
2461                             ccb->ataio.res.error,
2462                             ccb->ataio.res.lba_low,
2463                             ccb->ataio.res.lba_mid,
2464                             ccb->ataio.res.lba_high,
2465                             ccb->ataio.res.device,
2466                             ccb->ataio.res.lba_low_exp,
2467                             ccb->ataio.res.lba_mid_exp,
2468                             ccb->ataio.res.lba_high_exp,
2469                             ccb->ataio.res.sector_count,
2470                             ccb->ataio.res.sector_count_exp);
2471                         fflush(stdout);
2472                 }
2473         }
2474
2475         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2476          && (arglist & CAM_ARG_CMD_IN)
2477          && (data_bytes > 0)) {
2478                 if (fd_data == 0) {
2479                         buff_decode_visit(data_ptr, data_bytes, datastr,
2480                                           arg_put, NULL);
2481                         fprintf(stdout, "\n");
2482                 } else {
2483                         ssize_t amt_written;
2484                         int amt_to_write = data_bytes;
2485                         u_int8_t *buf_ptr = data_ptr;
2486
2487                         for (amt_written = 0; (amt_to_write > 0) &&
2488                              (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2489                                 amt_to_write -= amt_written;
2490                                 buf_ptr += amt_written;
2491                         }
2492                         if (amt_written == -1) {
2493                                 warn("error writing data to stdout");
2494                                 error = 1;
2495                                 goto scsicmd_bailout;
2496                         } else if ((amt_written == 0)
2497                                 && (amt_to_write > 0)) {
2498                                 warnx("only wrote %u bytes out of %u",
2499                                       data_bytes - amt_to_write, data_bytes);
2500                         }
2501                 }
2502         }
2503
2504 scsicmd_bailout:
2505
2506         if ((data_bytes > 0) && (data_ptr != NULL))
2507                 free(data_ptr);
2508
2509         cam_freeccb(ccb);
2510
2511         return(error);
2512 }
2513
2514 static int
2515 camdebug(int argc, char **argv, char *combinedopt)
2516 {
2517         int c, fd;
2518         int bus = -1, target = -1, lun = -1;
2519         char *tstr, *tmpstr = NULL;
2520         union ccb ccb;
2521         int error = 0;
2522
2523         bzero(&ccb, sizeof(union ccb));
2524
2525         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2526                 switch(c) {
2527                 case 'I':
2528                         arglist |= CAM_ARG_DEBUG_INFO;
2529                         ccb.cdbg.flags |= CAM_DEBUG_INFO;
2530                         break;
2531                 case 'P':
2532                         arglist |= CAM_ARG_DEBUG_PERIPH;
2533                         ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2534                         break;
2535                 case 'S':
2536                         arglist |= CAM_ARG_DEBUG_SUBTRACE;
2537                         ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2538                         break;
2539                 case 'T':
2540                         arglist |= CAM_ARG_DEBUG_TRACE;
2541                         ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2542                         break;
2543                 case 'X':
2544                         arglist |= CAM_ARG_DEBUG_XPT;
2545                         ccb.cdbg.flags |= CAM_DEBUG_XPT;
2546                         break;
2547                 case 'c':
2548                         arglist |= CAM_ARG_DEBUG_CDB;
2549                         ccb.cdbg.flags |= CAM_DEBUG_CDB;
2550                         break;
2551                 default:
2552                         break;
2553                 }
2554         }
2555
2556         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2557                 warnx("error opening transport layer device %s", XPT_DEVICE);
2558                 warn("%s", XPT_DEVICE);
2559                 return(1);
2560         }
2561         argc -= optind;
2562         argv += optind;
2563
2564         if (argc <= 0) {
2565                 warnx("you must specify \"off\", \"all\" or a bus,");
2566                 warnx("bus:target, or bus:target:lun");
2567                 close(fd);
2568                 return(1);
2569         }
2570
2571         tstr = *argv;
2572
2573         while (isspace(*tstr) && (*tstr != '\0'))
2574                 tstr++;
2575
2576         if (strncmp(tstr, "off", 3) == 0) {
2577                 ccb.cdbg.flags = CAM_DEBUG_NONE;
2578                 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2579                              CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2580                              CAM_ARG_DEBUG_XPT);
2581         } else if (strncmp(tstr, "all", 3) != 0) {
2582                 tmpstr = (char *)strtok(tstr, ":");
2583                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2584                         bus = strtol(tmpstr, NULL, 0);
2585                         arglist |= CAM_ARG_BUS;
2586                         tmpstr = (char *)strtok(NULL, ":");
2587                         if ((tmpstr != NULL) && (*tmpstr != '\0')){
2588                                 target = strtol(tmpstr, NULL, 0);
2589                                 arglist |= CAM_ARG_TARGET;
2590                                 tmpstr = (char *)strtok(NULL, ":");
2591                                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2592                                         lun = strtol(tmpstr, NULL, 0);
2593                                         arglist |= CAM_ARG_LUN;
2594                                 }
2595                         }
2596                 } else {
2597                         error = 1;
2598                         warnx("you must specify \"all\", \"off\", or a bus,");
2599                         warnx("bus:target, or bus:target:lun to debug");
2600                 }
2601         }
2602         
2603         if (error == 0) {
2604
2605                 ccb.ccb_h.func_code = XPT_DEBUG;
2606                 ccb.ccb_h.path_id = bus;
2607                 ccb.ccb_h.target_id = target;
2608                 ccb.ccb_h.target_lun = lun;
2609
2610                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2611                         warn("CAMIOCOMMAND ioctl failed");
2612                         error = 1;
2613                 }
2614
2615                 if (error == 0) {
2616                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2617                              CAM_FUNC_NOTAVAIL) {
2618                                 warnx("CAM debugging not available");
2619                                 warnx("you need to put options CAMDEBUG in"
2620                                       " your kernel config file!");
2621                                 error = 1;
2622                         } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2623                                     CAM_REQ_CMP) {
2624                                 warnx("XPT_DEBUG CCB failed with status %#x",
2625                                       ccb.ccb_h.status);
2626                                 error = 1;
2627                         } else {
2628                                 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2629                                         fprintf(stderr,
2630                                                 "Debugging turned off\n");
2631                                 } else {
2632                                         fprintf(stderr,
2633                                                 "Debugging enabled for "
2634                                                 "%d:%d:%d\n",
2635                                                 bus, target, lun);
2636                                 }
2637                         }
2638                 }
2639                 close(fd);
2640         }
2641
2642         return(error);
2643 }
2644
2645 static int
2646 tagcontrol(struct cam_device *device, int argc, char **argv,
2647            char *combinedopt)
2648 {
2649         int c;
2650         union ccb *ccb;
2651         int numtags = -1;
2652         int retval = 0;
2653         int quiet = 0;
2654         char pathstr[1024];
2655
2656         ccb = cam_getccb(device);
2657
2658         if (ccb == NULL) {
2659                 warnx("tagcontrol: error allocating ccb");
2660                 return(1);
2661         }
2662
2663         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2664                 switch(c) {
2665                 case 'N':
2666                         numtags = strtol(optarg, NULL, 0);
2667                         if (numtags < 0) {
2668                                 warnx("tag count %d is < 0", numtags);
2669                                 retval = 1;
2670                                 goto tagcontrol_bailout;
2671                         }
2672                         break;
2673                 case 'q':
2674                         quiet++;
2675                         break;
2676                 default:
2677                         break;
2678                 }
2679         }
2680
2681         cam_path_string(device, pathstr, sizeof(pathstr));
2682
2683         if (numtags >= 0) {
2684                 bzero(&(&ccb->ccb_h)[1],
2685                       sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2686                 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2687                 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2688                 ccb->crs.openings = numtags;
2689
2690
2691                 if (cam_send_ccb(device, ccb) < 0) {
2692                         perror("error sending XPT_REL_SIMQ CCB");
2693                         retval = 1;
2694                         goto tagcontrol_bailout;
2695                 }
2696
2697                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2698                         warnx("XPT_REL_SIMQ CCB failed");
2699                         cam_error_print(device, ccb, CAM_ESF_ALL,
2700                                         CAM_EPF_ALL, stderr);
2701                         retval = 1;
2702                         goto tagcontrol_bailout;
2703                 }
2704
2705
2706                 if (quiet == 0)
2707                         fprintf(stdout, "%stagged openings now %d\n",
2708                                 pathstr, ccb->crs.openings);
2709         }
2710
2711         bzero(&(&ccb->ccb_h)[1],
2712               sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2713
2714         ccb->ccb_h.func_code = XPT_GDEV_STATS;
2715
2716         if (cam_send_ccb(device, ccb) < 0) {
2717                 perror("error sending XPT_GDEV_STATS CCB");
2718                 retval = 1;
2719                 goto tagcontrol_bailout;
2720         }
2721
2722         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2723                 warnx("XPT_GDEV_STATS CCB failed");
2724                 cam_error_print(device, ccb, CAM_ESF_ALL,
2725                                 CAM_EPF_ALL, stderr);
2726                 retval = 1;
2727                 goto tagcontrol_bailout;
2728         }
2729
2730         if (arglist & CAM_ARG_VERBOSE) {
2731                 fprintf(stdout, "%s", pathstr);
2732                 fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2733                 fprintf(stdout, "%s", pathstr);
2734                 fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2735                 fprintf(stdout, "%s", pathstr);
2736                 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2737                 fprintf(stdout, "%s", pathstr);
2738                 fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2739                 fprintf(stdout, "%s", pathstr);
2740                 fprintf(stdout, "held          %d\n", ccb->cgds.held);
2741                 fprintf(stdout, "%s", pathstr);
2742                 fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2743                 fprintf(stdout, "%s", pathstr);
2744                 fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2745         } else {
2746                 if (quiet == 0) {
2747                         fprintf(stdout, "%s", pathstr);
2748                         fprintf(stdout, "device openings: ");
2749                 }
2750                 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2751                         ccb->cgds.dev_active);
2752         }
2753
2754 tagcontrol_bailout:
2755
2756         cam_freeccb(ccb);
2757         return(retval);
2758 }
2759
2760 static void
2761 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2762 {
2763         char pathstr[1024];
2764
2765         cam_path_string(device, pathstr, sizeof(pathstr));
2766
2767         if (cts->transport == XPORT_SPI) {
2768                 struct ccb_trans_settings_spi *spi =
2769                     &cts->xport_specific.spi;
2770
2771                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2772
2773                         fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2774                                 spi->sync_period);
2775
2776                         if (spi->sync_offset != 0) {
2777                                 u_int freq;
2778
2779                                 freq = scsi_calc_syncsrate(spi->sync_period);
2780                                 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2781                                         pathstr, freq / 1000, freq % 1000);
2782                         }
2783                 }
2784
2785                 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2786                         fprintf(stdout, "%soffset: %d\n", pathstr,
2787                             spi->sync_offset);
2788                 }
2789
2790                 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2791                         fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2792                                 (0x01 << spi->bus_width) * 8);
2793                 }
2794
2795                 if (spi->valid & CTS_SPI_VALID_DISC) {
2796                         fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2797                                 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2798                                 "enabled" : "disabled");
2799                 }
2800         }
2801         if (cts->transport == XPORT_ATA) {
2802                 struct ccb_trans_settings_ata *ata =
2803                     &cts->xport_specific.ata;
2804
2805                 if ((ata->valid & CTS_ATA_VALID_MODE) != 0) {
2806                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
2807                                 ata_mode2string(ata->mode));
2808                 }
2809                 if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2810                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2811                                 ata->atapi);
2812                 }
2813                 if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2814                         fprintf(stdout, "%sPIO transaction length: %d\n",
2815                                 pathstr, ata->bytecount);
2816                 }
2817         }
2818         if (cts->transport == XPORT_SATA) {
2819                 struct ccb_trans_settings_sata *sata =
2820                     &cts->xport_specific.sata;
2821
2822                 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2823                         fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2824                                 sata->revision);
2825                 }
2826                 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2827                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
2828                                 ata_mode2string(sata->mode));
2829                 }
2830                 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2831                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2832                                 sata->atapi);
2833                 }
2834                 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2835                         fprintf(stdout, "%sPIO transaction length: %d\n",
2836                                 pathstr, sata->bytecount);
2837                 }
2838                 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2839                         fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2840                                 sata->pm_present);
2841                 }
2842                 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2843                         fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2844                                 sata->tags);
2845                 }
2846         }
2847         if (cts->protocol == PROTO_SCSI) {
2848                 struct ccb_trans_settings_scsi *scsi=
2849                     &cts->proto_specific.scsi;
2850
2851                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2852                         fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2853                                 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2854                                 "enabled" : "disabled");
2855                 }
2856         }
2857
2858 }
2859
2860 /*
2861  * Get a path inquiry CCB for the specified device.  
2862  */
2863 static int
2864 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2865 {
2866         union ccb *ccb;
2867         int retval = 0;
2868
2869         ccb = cam_getccb(device);
2870         if (ccb == NULL) {
2871                 warnx("get_cpi: couldn't allocate CCB");
2872                 return(1);
2873         }
2874         bzero(&(&ccb->ccb_h)[1],
2875               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2876         ccb->ccb_h.func_code = XPT_PATH_INQ;
2877         if (cam_send_ccb(device, ccb) < 0) {
2878                 warn("get_cpi: error sending Path Inquiry CCB");
2879                 if (arglist & CAM_ARG_VERBOSE)
2880                         cam_error_print(device, ccb, CAM_ESF_ALL,
2881                                         CAM_EPF_ALL, stderr);
2882                 retval = 1;
2883                 goto get_cpi_bailout;
2884         }
2885         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2886                 if (arglist & CAM_ARG_VERBOSE)
2887                         cam_error_print(device, ccb, CAM_ESF_ALL,
2888                                         CAM_EPF_ALL, stderr);
2889                 retval = 1;
2890                 goto get_cpi_bailout;
2891         }
2892         bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2893
2894 get_cpi_bailout:
2895         cam_freeccb(ccb);
2896         return(retval);
2897 }
2898
2899 /*
2900  * Get a get device CCB for the specified device.  
2901  */
2902 static int
2903 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
2904 {
2905         union ccb *ccb;
2906         int retval = 0;
2907
2908         ccb = cam_getccb(device);
2909         if (ccb == NULL) {
2910                 warnx("get_cgd: couldn't allocate CCB");
2911                 return(1);
2912         }
2913         bzero(&(&ccb->ccb_h)[1],
2914               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2915         ccb->ccb_h.func_code = XPT_GDEV_TYPE;
2916         if (cam_send_ccb(device, ccb) < 0) {
2917                 warn("get_cgd: error sending Path Inquiry CCB");
2918                 if (arglist & CAM_ARG_VERBOSE)
2919                         cam_error_print(device, ccb, CAM_ESF_ALL,
2920                                         CAM_EPF_ALL, stderr);
2921                 retval = 1;
2922                 goto get_cgd_bailout;
2923         }
2924         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2925                 if (arglist & CAM_ARG_VERBOSE)
2926                         cam_error_print(device, ccb, CAM_ESF_ALL,
2927                                         CAM_EPF_ALL, stderr);
2928                 retval = 1;
2929                 goto get_cgd_bailout;
2930         }
2931         bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
2932
2933 get_cgd_bailout:
2934         cam_freeccb(ccb);
2935         return(retval);
2936 }
2937
2938 static void
2939 cpi_print(struct ccb_pathinq *cpi)
2940 {
2941         char adapter_str[1024];
2942         int i;
2943
2944         snprintf(adapter_str, sizeof(adapter_str),
2945                  "%s%d:", cpi->dev_name, cpi->unit_number);
2946
2947         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2948                 cpi->version_num);
2949
2950         for (i = 1; i < 0xff; i = i << 1) {
2951                 const char *str;
2952
2953                 if ((i & cpi->hba_inquiry) == 0)
2954                         continue;
2955
2956                 fprintf(stdout, "%s supports ", adapter_str);
2957
2958                 switch(i) {
2959                 case PI_MDP_ABLE:
2960                         str = "MDP message";
2961                         break;
2962                 case PI_WIDE_32:
2963                         str = "32 bit wide SCSI";
2964                         break;
2965                 case PI_WIDE_16:
2966                         str = "16 bit wide SCSI";
2967                         break;
2968                 case PI_SDTR_ABLE:
2969                         str = "SDTR message";
2970                         break;
2971                 case PI_LINKED_CDB:
2972                         str = "linked CDBs";
2973                         break;
2974                 case PI_TAG_ABLE:
2975                         str = "tag queue messages";
2976                         break;
2977                 case PI_SOFT_RST:
2978                         str = "soft reset alternative";
2979                         break;
2980                 case PI_SATAPM:
2981                         str = "SATA Port Multiplier";
2982                         break;
2983                 default:
2984                         str = "unknown PI bit set";
2985                         break;
2986                 }
2987                 fprintf(stdout, "%s\n", str);
2988         }
2989
2990         for (i = 1; i < 0xff; i = i << 1) {
2991                 const char *str;
2992
2993                 if ((i & cpi->hba_misc) == 0)
2994                         continue;
2995
2996                 fprintf(stdout, "%s ", adapter_str);
2997
2998                 switch(i) {
2999                 case PIM_SCANHILO:
3000                         str = "bus scans from high ID to low ID";
3001                         break;
3002                 case PIM_NOREMOVE:
3003                         str = "removable devices not included in scan";
3004                         break;
3005                 case PIM_NOINITIATOR:
3006                         str = "initiator role not supported";
3007                         break;
3008                 case PIM_NOBUSRESET:
3009                         str = "user has disabled initial BUS RESET or"
3010                               " controller is in target/mixed mode";
3011                         break;
3012                 case PIM_NO_6_BYTE:
3013                         str = "do not send 6-byte commands";
3014                         break;
3015                 case PIM_SEQSCAN:
3016                         str = "scan bus sequentially";
3017                         break;
3018                 default:
3019                         str = "unknown PIM bit set";
3020                         break;
3021                 }
3022                 fprintf(stdout, "%s\n", str);
3023         }
3024
3025         for (i = 1; i < 0xff; i = i << 1) {
3026                 const char *str;
3027
3028                 if ((i & cpi->target_sprt) == 0)
3029                         continue;
3030
3031                 fprintf(stdout, "%s supports ", adapter_str);
3032                 switch(i) {
3033                 case PIT_PROCESSOR:
3034                         str = "target mode processor mode";
3035                         break;
3036                 case PIT_PHASE:
3037                         str = "target mode phase cog. mode";
3038                         break;
3039                 case PIT_DISCONNECT:
3040                         str = "disconnects in target mode";
3041                         break;
3042                 case PIT_TERM_IO:
3043                         str = "terminate I/O message in target mode";
3044                         break;
3045                 case PIT_GRP_6:
3046                         str = "group 6 commands in target mode";
3047                         break;
3048                 case PIT_GRP_7:
3049                         str = "group 7 commands in target mode";
3050                         break;
3051                 default:
3052                         str = "unknown PIT bit set";
3053                         break;
3054                 }
3055
3056                 fprintf(stdout, "%s\n", str);
3057         }
3058         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3059                 cpi->hba_eng_cnt);
3060         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3061                 cpi->max_target);
3062         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3063                 cpi->max_lun);
3064         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3065                 adapter_str, cpi->hpath_id);
3066         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3067                 cpi->initiator_id);
3068         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3069         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3070         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3071         fprintf(stdout, "%s base transfer speed: ", adapter_str);
3072         if (cpi->base_transfer_speed > 1000)
3073                 fprintf(stdout, "%d.%03dMB/sec\n",
3074                         cpi->base_transfer_speed / 1000,
3075                         cpi->base_transfer_speed % 1000);
3076         else
3077                 fprintf(stdout, "%dKB/sec\n",
3078                         (cpi->base_transfer_speed % 1000) * 1000);
3079 }
3080
3081 static int
3082 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3083               struct ccb_trans_settings *cts)
3084 {
3085         int retval;
3086         union ccb *ccb;
3087
3088         retval = 0;
3089         ccb = cam_getccb(device);
3090
3091         if (ccb == NULL) {
3092                 warnx("get_print_cts: error allocating ccb");
3093                 return(1);
3094         }
3095
3096         bzero(&(&ccb->ccb_h)[1],
3097               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3098
3099         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3100
3101         if (user_settings == 0)
3102                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3103         else
3104                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3105
3106         if (cam_send_ccb(device, ccb) < 0) {
3107                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3108                 if (arglist & CAM_ARG_VERBOSE)
3109                         cam_error_print(device, ccb, CAM_ESF_ALL,
3110                                         CAM_EPF_ALL, stderr);
3111                 retval = 1;
3112                 goto get_print_cts_bailout;
3113         }
3114
3115         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3116                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3117                 if (arglist & CAM_ARG_VERBOSE)
3118                         cam_error_print(device, ccb, CAM_ESF_ALL,
3119                                         CAM_EPF_ALL, stderr);
3120                 retval = 1;
3121                 goto get_print_cts_bailout;
3122         }
3123
3124         if (quiet == 0)
3125                 cts_print(device, &ccb->cts);
3126
3127         if (cts != NULL)
3128                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3129
3130 get_print_cts_bailout:
3131
3132         cam_freeccb(ccb);
3133
3134         return(retval);
3135 }
3136
3137 static int
3138 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3139             int argc, char **argv, char *combinedopt)
3140 {
3141         int c;
3142         union ccb *ccb;
3143         int user_settings = 0;
3144         int retval = 0;
3145         int disc_enable = -1, tag_enable = -1;
3146         int mode = -1;
3147         int offset = -1;
3148         double syncrate = -1;
3149         int bus_width = -1;
3150         int quiet = 0;
3151         int change_settings = 0, send_tur = 0;
3152         struct ccb_pathinq cpi;
3153
3154         ccb = cam_getccb(device);
3155         if (ccb == NULL) {
3156                 warnx("ratecontrol: error allocating ccb");
3157                 return(1);
3158         }
3159         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3160                 switch(c){
3161                 case 'a':
3162                         send_tur = 1;
3163                         break;
3164                 case 'c':
3165                         user_settings = 0;
3166                         break;
3167                 case 'D':
3168                         if (strncasecmp(optarg, "enable", 6) == 0)
3169                                 disc_enable = 1;
3170                         else if (strncasecmp(optarg, "disable", 7) == 0)
3171                                 disc_enable = 0;
3172                         else {
3173                                 warnx("-D argument \"%s\" is unknown", optarg);
3174                                 retval = 1;
3175                                 goto ratecontrol_bailout;
3176                         }
3177                         change_settings = 1;
3178                         break;
3179                 case 'M':
3180                         mode = ata_string2mode(optarg);
3181                         if (mode < 0) {
3182                                 warnx("unknown mode '%s'", optarg);
3183                                 retval = 1;
3184                                 goto ratecontrol_bailout;
3185                         }
3186                         change_settings = 1;
3187                         break;
3188                 case 'O':
3189                         offset = strtol(optarg, NULL, 0);
3190                         if (offset < 0) {
3191                                 warnx("offset value %d is < 0", offset);
3192                                 retval = 1;
3193                                 goto ratecontrol_bailout;
3194                         }
3195                         change_settings = 1;
3196                         break;
3197                 case 'q':
3198                         quiet++;
3199                         break;
3200                 case 'R':
3201                         syncrate = atof(optarg);
3202                         if (syncrate < 0) {
3203                                 warnx("sync rate %f is < 0", syncrate);
3204                                 retval = 1;
3205                                 goto ratecontrol_bailout;
3206                         }
3207                         change_settings = 1;
3208                         break;
3209                 case 'T':
3210                         if (strncasecmp(optarg, "enable", 6) == 0)
3211                                 tag_enable = 1;
3212                         else if (strncasecmp(optarg, "disable", 7) == 0)
3213                                 tag_enable = 0;
3214                         else {
3215                                 warnx("-T argument \"%s\" is unknown", optarg);
3216                                 retval = 1;
3217                                 goto ratecontrol_bailout;
3218                         }
3219                         change_settings = 1;
3220                         break;
3221                 case 'U':
3222                         user_settings = 1;
3223                         break;
3224                 case 'W':
3225                         bus_width = strtol(optarg, NULL, 0);
3226                         if (bus_width < 0) {
3227                                 warnx("bus width %d is < 0", bus_width);
3228                                 retval = 1;
3229                                 goto ratecontrol_bailout;
3230                         }
3231                         change_settings = 1;
3232                         break;
3233                 default:
3234                         break;
3235                 }
3236         }
3237         bzero(&(&ccb->ccb_h)[1],
3238               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3239         /*
3240          * Grab path inquiry information, so we can determine whether
3241          * or not the initiator is capable of the things that the user
3242          * requests.
3243          */
3244         ccb->ccb_h.func_code = XPT_PATH_INQ;
3245         if (cam_send_ccb(device, ccb) < 0) {
3246                 perror("error sending XPT_PATH_INQ CCB");
3247                 if (arglist & CAM_ARG_VERBOSE) {
3248                         cam_error_print(device, ccb, CAM_ESF_ALL,
3249                                         CAM_EPF_ALL, stderr);
3250                 }
3251                 retval = 1;
3252                 goto ratecontrol_bailout;
3253         }
3254         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3255                 warnx("XPT_PATH_INQ CCB failed");
3256                 if (arglist & CAM_ARG_VERBOSE) {
3257                         cam_error_print(device, ccb, CAM_ESF_ALL,
3258                                         CAM_EPF_ALL, stderr);
3259                 }
3260                 retval = 1;
3261                 goto ratecontrol_bailout;
3262         }
3263         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3264         bzero(&(&ccb->ccb_h)[1],
3265               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3266         if (quiet == 0) {
3267                 fprintf(stdout, "%s parameters:\n",
3268                     user_settings ? "User" : "Current");
3269         }
3270         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3271         if (retval != 0)
3272                 goto ratecontrol_bailout;
3273
3274         if (arglist & CAM_ARG_VERBOSE)
3275                 cpi_print(&cpi);
3276
3277         if (change_settings) {
3278                 int didsettings = 0;
3279                 struct ccb_trans_settings_spi *spi = NULL;
3280                 struct ccb_trans_settings_ata *ata = NULL;
3281                 struct ccb_trans_settings_sata *sata = NULL;
3282                 struct ccb_trans_settings_scsi *scsi = NULL;
3283
3284                 if (ccb->cts.transport == XPORT_SPI)
3285                         spi = &ccb->cts.xport_specific.spi;
3286                 if (ccb->cts.transport == XPORT_ATA)
3287                         ata = &ccb->cts.xport_specific.ata;
3288                 if (ccb->cts.transport == XPORT_SATA)
3289                         sata = &ccb->cts.xport_specific.sata;
3290                 if (ccb->cts.protocol == PROTO_SCSI)
3291                         scsi = &ccb->cts.proto_specific.scsi;
3292                 ccb->cts.xport_specific.valid = 0;
3293                 ccb->cts.proto_specific.valid = 0;
3294                 if (spi && disc_enable != -1) {
3295                         spi->valid |= CTS_SPI_VALID_DISC;
3296                         if (disc_enable == 0)
3297                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3298                         else
3299                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3300                 }
3301                 if (scsi && tag_enable != -1) {
3302                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3303                                 warnx("HBA does not support tagged queueing, "
3304                                       "so you cannot modify tag settings");
3305                                 retval = 1;
3306                                 goto ratecontrol_bailout;
3307                         }
3308                         scsi->valid |= CTS_SCSI_VALID_TQ;
3309                         if (tag_enable == 0)
3310                                 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3311                         else
3312                                 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3313                         didsettings++;
3314                 }
3315                 if (spi && offset != -1) {
3316                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3317                                 warnx("HBA is not capable of changing offset");
3318                                 retval = 1;
3319                                 goto ratecontrol_bailout;
3320                         }
3321                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3322                         spi->sync_offset = offset;
3323                         didsettings++;
3324                 }
3325                 if (spi && syncrate != -1) {
3326                         int prelim_sync_period;
3327                         u_int freq;
3328
3329                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3330                                 warnx("HBA is not capable of changing "
3331                                       "transfer rates");
3332                                 retval = 1;
3333                                 goto ratecontrol_bailout;
3334                         }
3335                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3336                         /*
3337                          * The sync rate the user gives us is in MHz.
3338                          * We need to translate it into KHz for this
3339                          * calculation.
3340                          */
3341                         syncrate *= 1000;
3342                         /*
3343                          * Next, we calculate a "preliminary" sync period
3344                          * in tenths of a nanosecond.
3345                          */
3346                         if (syncrate == 0)
3347                                 prelim_sync_period = 0;
3348                         else
3349                                 prelim_sync_period = 10000000 / syncrate;
3350                         spi->sync_period =
3351                                 scsi_calc_syncparam(prelim_sync_period);
3352                         freq = scsi_calc_syncsrate(spi->sync_period);
3353                         didsettings++;
3354                 }
3355                 if (sata && syncrate != -1) {
3356                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3357                                 warnx("HBA is not capable of changing "
3358                                       "transfer rates");
3359                                 retval = 1;
3360                                 goto ratecontrol_bailout;
3361                         }
3362                         sata->revision = ata_speed2revision(syncrate * 100);
3363                         if (sata->revision < 0) {
3364                                 warnx("Invalid rate %f", syncrate);
3365                                 retval = 1;
3366                                 goto ratecontrol_bailout;
3367                         }
3368                         sata->valid |= CTS_SATA_VALID_REVISION;
3369                         didsettings++;
3370                 }
3371                 if ((ata || sata) && mode != -1) {
3372                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3373                                 warnx("HBA is not capable of changing "
3374                                       "transfer rates");
3375                                 retval = 1;
3376                                 goto ratecontrol_bailout;
3377                         }
3378                         if (ata) {
3379                                 ata->mode = mode;
3380                                 ata->valid |= CTS_ATA_VALID_MODE;
3381                         } else {
3382                                 sata->mode = mode;
3383                                 sata->valid |= CTS_SATA_VALID_MODE;
3384                         }
3385                         didsettings++;
3386                 }
3387                 /*
3388                  * The bus_width argument goes like this:
3389                  * 0 == 8 bit
3390                  * 1 == 16 bit
3391                  * 2 == 32 bit
3392                  * Therefore, if you shift the number of bits given on the
3393                  * command line right by 4, you should get the correct
3394                  * number.
3395                  */
3396                 if (spi && bus_width != -1) {
3397                         /*
3398                          * We might as well validate things here with a
3399                          * decipherable error message, rather than what
3400                          * will probably be an indecipherable error message
3401                          * by the time it gets back to us.
3402                          */
3403                         if ((bus_width == 16)
3404                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3405                                 warnx("HBA does not support 16 bit bus width");
3406                                 retval = 1;
3407                                 goto ratecontrol_bailout;
3408                         } else if ((bus_width == 32)
3409                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3410                                 warnx("HBA does not support 32 bit bus width");
3411                                 retval = 1;
3412                                 goto ratecontrol_bailout;
3413                         } else if ((bus_width != 8)
3414                                 && (bus_width != 16)
3415                                 && (bus_width != 32)) {
3416                                 warnx("Invalid bus width %d", bus_width);
3417                                 retval = 1;
3418                                 goto ratecontrol_bailout;
3419                         }
3420                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3421                         spi->bus_width = bus_width >> 4;
3422                         didsettings++;
3423                 }
3424                 if  (didsettings == 0) {
3425                         goto ratecontrol_bailout;
3426                 }
3427                 if  (!user_settings && (ata || sata)) {
3428                         warnx("You can modify only user settings for ATA/SATA");
3429                         retval = 1;
3430                         goto ratecontrol_bailout;
3431                 }
3432                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3433                 if (cam_send_ccb(device, ccb) < 0) {
3434                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3435                         if (arglist & CAM_ARG_VERBOSE) {
3436                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3437                                                 CAM_EPF_ALL, stderr);
3438                         }
3439                         retval = 1;
3440                         goto ratecontrol_bailout;
3441                 }
3442                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3443                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3444                         if (arglist & CAM_ARG_VERBOSE) {
3445                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3446                                                 CAM_EPF_ALL, stderr);
3447                         }
3448                         retval = 1;
3449                         goto ratecontrol_bailout;
3450                 }
3451         }
3452         if (send_tur) {
3453                 retval = testunitready(device, retry_count, timeout,
3454                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3455                 /*
3456                  * If the TUR didn't succeed, just bail.
3457                  */
3458                 if (retval != 0) {
3459                         if (quiet == 0)
3460                                 fprintf(stderr, "Test Unit Ready failed\n");
3461                         goto ratecontrol_bailout;
3462                 }
3463                 /*
3464                  * If the user wants things quiet, there's no sense in
3465                  * getting the transfer settings, if we're not going
3466                  * to print them.
3467                  */
3468                 if (quiet != 0)
3469                         goto ratecontrol_bailout;
3470                 fprintf(stdout, "New parameters:\n");
3471                 retval = get_print_cts(device, user_settings, 0, NULL);
3472         }
3473
3474 ratecontrol_bailout:
3475         cam_freeccb(ccb);
3476         return(retval);
3477 }
3478
3479 static int
3480 scsiformat(struct cam_device *device, int argc, char **argv,
3481            char *combinedopt, int retry_count, int timeout)
3482 {
3483         union ccb *ccb;
3484         int c;
3485         int ycount = 0, quiet = 0;
3486         int error = 0, response = 0, retval = 0;
3487         int use_timeout = 10800 * 1000;
3488         int immediate = 1;
3489         struct format_defect_list_header fh;
3490         u_int8_t *data_ptr = NULL;
3491         u_int32_t dxfer_len = 0;
3492         u_int8_t byte2 = 0;
3493         int num_warnings = 0;
3494         int reportonly = 0;
3495
3496         ccb = cam_getccb(device);
3497
3498         if (ccb == NULL) {
3499                 warnx("scsiformat: error allocating ccb");
3500                 return(1);
3501         }
3502
3503         bzero(&(&ccb->ccb_h)[1],
3504               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3505
3506         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3507                 switch(c) {
3508                 case 'q':
3509                         quiet++;
3510                         break;
3511                 case 'r':
3512                         reportonly = 1;
3513                         break;
3514                 case 'w':
3515                         immediate = 0;
3516                         break;
3517                 case 'y':
3518                         ycount++;
3519                         break;
3520                 }
3521         }
3522
3523         if (reportonly)
3524                 goto doreport;
3525
3526         if (quiet == 0) {
3527                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3528                         "following device:\n");
3529
3530                 error = scsidoinquiry(device, argc, argv, combinedopt,
3531                                       retry_count, timeout);
3532
3533                 if (error != 0) {
3534                         warnx("scsiformat: error sending inquiry");
3535                         goto scsiformat_bailout;
3536                 }
3537         }
3538
3539         if (ycount == 0) {
3540
3541                 do {
3542                         char str[1024];
3543
3544                         fprintf(stdout, "Are you SURE you want to do "
3545                                 "this? (yes/no) ");
3546
3547                         if (fgets(str, sizeof(str), stdin) != NULL) {
3548
3549                                 if (strncasecmp(str, "yes", 3) == 0)
3550                                         response = 1;
3551                                 else if (strncasecmp(str, "no", 2) == 0)
3552                                         response = -1;
3553                                 else {
3554                                         fprintf(stdout, "Please answer"
3555                                                 " \"yes\" or \"no\"\n");
3556                                 }
3557                         }
3558                 } while (response == 0);
3559
3560                 if (response == -1) {
3561                         error = 1;
3562                         goto scsiformat_bailout;
3563                 }
3564         }
3565
3566         if (timeout != 0)
3567                 use_timeout = timeout;
3568
3569         if (quiet == 0) {
3570                 fprintf(stdout, "Current format timeout is %d seconds\n",
3571                         use_timeout / 1000);
3572         }
3573
3574         /*
3575          * If the user hasn't disabled questions and didn't specify a
3576          * timeout on the command line, ask them if they want the current
3577          * timeout.
3578          */
3579         if ((ycount == 0)
3580          && (timeout == 0)) {
3581                 char str[1024];
3582                 int new_timeout = 0;
3583
3584                 fprintf(stdout, "Enter new timeout in seconds or press\n"
3585                         "return to keep the current timeout [%d] ",
3586                         use_timeout / 1000);
3587
3588                 if (fgets(str, sizeof(str), stdin) != NULL) {
3589                         if (str[0] != '\0')
3590                                 new_timeout = atoi(str);
3591                 }
3592
3593                 if (new_timeout != 0) {
3594                         use_timeout = new_timeout * 1000;
3595                         fprintf(stdout, "Using new timeout value %d\n",
3596                                 use_timeout / 1000);
3597                 }
3598         }
3599
3600         /*
3601          * Keep this outside the if block below to silence any unused
3602          * variable warnings.
3603          */
3604         bzero(&fh, sizeof(fh));
3605
3606         /*
3607          * If we're in immediate mode, we've got to include the format
3608          * header
3609          */
3610         if (immediate != 0) {
3611                 fh.byte2 = FU_DLH_IMMED;
3612                 data_ptr = (u_int8_t *)&fh;
3613                 dxfer_len = sizeof(fh);
3614                 byte2 = FU_FMT_DATA;
3615         } else if (quiet == 0) {
3616                 fprintf(stdout, "Formatting...");
3617                 fflush(stdout);
3618         }
3619
3620         scsi_format_unit(&ccb->csio,
3621                          /* retries */ retry_count,
3622                          /* cbfcnp */ NULL,
3623                          /* tag_action */ MSG_SIMPLE_Q_TAG,
3624                          /* byte2 */ byte2,
3625                          /* ileave */ 0,
3626                          /* data_ptr */ data_ptr,
3627                          /* dxfer_len */ dxfer_len,
3628                          /* sense_len */ SSD_FULL_SIZE,
3629                          /* timeout */ use_timeout);
3630
3631         /* Disable freezing the device queue */
3632         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3633
3634         if (arglist & CAM_ARG_ERR_RECOVER)
3635                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3636
3637         if (((retval = cam_send_ccb(device, ccb)) < 0)
3638          || ((immediate == 0)
3639            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3640                 const char errstr[] = "error sending format command";
3641
3642                 if (retval < 0)
3643                         warn(errstr);
3644                 else
3645                         warnx(errstr);
3646
3647                 if (arglist & CAM_ARG_VERBOSE) {
3648                         cam_error_print(device, ccb, CAM_ESF_ALL,
3649                                         CAM_EPF_ALL, stderr);
3650                 }
3651                 error = 1;
3652                 goto scsiformat_bailout;
3653         }
3654
3655         /*
3656          * If we ran in non-immediate mode, we already checked for errors
3657          * above and printed out any necessary information.  If we're in
3658          * immediate mode, we need to loop through and get status
3659          * information periodically.
3660          */
3661         if (immediate == 0) {
3662                 if (quiet == 0) {
3663                         fprintf(stdout, "Format Complete\n");
3664                 }
3665                 goto scsiformat_bailout;
3666         }
3667
3668 doreport:
3669         do {
3670                 cam_status status;
3671
3672                 bzero(&(&ccb->ccb_h)[1],
3673                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3674
3675                 /*
3676                  * There's really no need to do error recovery or
3677                  * retries here, since we're just going to sit in a
3678                  * loop and wait for the device to finish formatting.
3679                  */
3680                 scsi_test_unit_ready(&ccb->csio,
3681                                      /* retries */ 0,
3682                                      /* cbfcnp */ NULL,
3683                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
3684                                      /* sense_len */ SSD_FULL_SIZE,
3685                                      /* timeout */ 5000);
3686
3687                 /* Disable freezing the device queue */
3688                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3689
3690                 retval = cam_send_ccb(device, ccb);
3691
3692                 /*
3693                  * If we get an error from the ioctl, bail out.  SCSI
3694                  * errors are expected.
3695                  */
3696                 if (retval < 0) {
3697                         warn("error sending CAMIOCOMMAND ioctl");
3698                         if (arglist & CAM_ARG_VERBOSE) {
3699                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3700                                                 CAM_EPF_ALL, stderr);
3701                         }
3702                         error = 1;
3703                         goto scsiformat_bailout;
3704                 }
3705
3706                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3707
3708                 if ((status != CAM_REQ_CMP)
3709                  && (status == CAM_SCSI_STATUS_ERROR)
3710                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3711                         struct scsi_sense_data *sense;
3712                         int error_code, sense_key, asc, ascq;
3713
3714                         sense = &ccb->csio.sense_data;
3715                         scsi_extract_sense(sense, &error_code, &sense_key,
3716                                            &asc, &ascq);
3717
3718                         /*
3719                          * According to the SCSI-2 and SCSI-3 specs, a
3720                          * drive that is in the middle of a format should
3721                          * return NOT READY with an ASC of "logical unit
3722                          * not ready, format in progress".  The sense key
3723                          * specific bytes will then be a progress indicator.
3724                          */
3725                         if ((sense_key == SSD_KEY_NOT_READY)
3726                          && (asc == 0x04) && (ascq == 0x04)) {
3727                                 if ((sense->extra_len >= 10)
3728                                  && ((sense->sense_key_spec[0] &
3729                                       SSD_SCS_VALID) != 0)
3730                                  && (quiet == 0)) {
3731                                         int val;
3732                                         u_int64_t percentage;
3733
3734                                         val = scsi_2btoul(
3735                                                 &sense->sense_key_spec[1]);
3736                                         percentage = 10000 * val;
3737
3738                                         fprintf(stdout,
3739                                                 "\rFormatting:  %ju.%02u %% "
3740                                                 "(%d/%d) done",
3741                                                 (uintmax_t)(percentage / 
3742                                                 (0x10000 * 100)),
3743                                                 (unsigned)((percentage / 
3744                                                 0x10000) % 100),
3745                                                 val, 0x10000);
3746                                         fflush(stdout);
3747                                 } else if ((quiet == 0)
3748                                         && (++num_warnings <= 1)) {
3749                                         warnx("Unexpected SCSI Sense Key "
3750                                               "Specific value returned "
3751                                               "during format:");
3752                                         scsi_sense_print(device, &ccb->csio,
3753                                                          stderr);
3754                                         warnx("Unable to print status "
3755                                               "information, but format will "
3756                                               "proceed.");
3757                                         warnx("will exit when format is "
3758                                               "complete");
3759                                 }
3760                                 sleep(1);
3761                         } else {
3762                                 warnx("Unexpected SCSI error during format");
3763                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3764                                                 CAM_EPF_ALL, stderr);
3765                                 error = 1;
3766                                 goto scsiformat_bailout;
3767                         }
3768
3769                 } else if (status != CAM_REQ_CMP) {
3770                         warnx("Unexpected CAM status %#x", status);
3771                         if (arglist & CAM_ARG_VERBOSE)
3772                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3773                                                 CAM_EPF_ALL, stderr);
3774                         error = 1;
3775                         goto scsiformat_bailout;
3776                 }
3777
3778         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3779
3780         if (quiet == 0)
3781                 fprintf(stdout, "\nFormat Complete\n");
3782
3783 scsiformat_bailout:
3784
3785         cam_freeccb(ccb);
3786
3787         return(error);
3788 }
3789
3790 static int
3791 scsireportluns(struct cam_device *device, int argc, char **argv,
3792                char *combinedopt, int retry_count, int timeout)
3793 {
3794         union ccb *ccb;
3795         int c, countonly, lunsonly;
3796         struct scsi_report_luns_data *lundata;
3797         int alloc_len;
3798         uint8_t report_type;
3799         uint32_t list_len, i, j;
3800         int retval;
3801
3802         retval = 0;
3803         lundata = NULL;
3804         report_type = RPL_REPORT_DEFAULT;
3805         ccb = cam_getccb(device);
3806
3807         if (ccb == NULL) {
3808                 warnx("%s: error allocating ccb", __func__);
3809                 return (1);
3810         }
3811
3812         bzero(&(&ccb->ccb_h)[1],
3813               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3814
3815         countonly = 0;
3816         lunsonly = 0;
3817
3818         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3819                 switch (c) {
3820                 case 'c':
3821                         countonly++;
3822                         break;
3823                 case 'l':
3824                         lunsonly++;
3825                         break;
3826                 case 'r':
3827                         if (strcasecmp(optarg, "default") == 0)
3828                                 report_type = RPL_REPORT_DEFAULT;
3829                         else if (strcasecmp(optarg, "wellknown") == 0)
3830                                 report_type = RPL_REPORT_WELLKNOWN;
3831                         else if (strcasecmp(optarg, "all") == 0)
3832                                 report_type = RPL_REPORT_ALL;
3833                         else {
3834                                 warnx("%s: invalid report type \"%s\"",
3835                                       __func__, optarg);
3836                                 retval = 1;
3837                                 goto bailout;
3838                         }
3839                         break;
3840                 default:
3841                         break;
3842                 }
3843         }
3844
3845         if ((countonly != 0)
3846          && (lunsonly != 0)) {
3847                 warnx("%s: you can only specify one of -c or -l", __func__);
3848                 retval = 1;
3849                 goto bailout;
3850         }
3851         /*
3852          * According to SPC-4, the allocation length must be at least 16
3853          * bytes -- enough for the header and one LUN.
3854          */
3855         alloc_len = sizeof(*lundata) + 8;
3856
3857 retry:
3858
3859         lundata = malloc(alloc_len);
3860
3861         if (lundata == NULL) {
3862                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
3863                 retval = 1;
3864                 goto bailout;
3865         }
3866
3867         scsi_report_luns(&ccb->csio,
3868                          /*retries*/ retry_count,
3869                          /*cbfcnp*/ NULL,
3870                          /*tag_action*/ MSG_SIMPLE_Q_TAG,
3871                          /*select_report*/ report_type,
3872                          /*rpl_buf*/ lundata,
3873                          /*alloc_len*/ alloc_len,
3874                          /*sense_len*/ SSD_FULL_SIZE,
3875                          /*timeout*/ timeout ? timeout : 5000);
3876
3877         /* Disable freezing the device queue */
3878         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3879
3880         if (arglist & CAM_ARG_ERR_RECOVER)
3881                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3882
3883         if (cam_send_ccb(device, ccb) < 0) {
3884                 warn("error sending REPORT LUNS command");
3885
3886                 if (arglist & CAM_ARG_VERBOSE)
3887                         cam_error_print(device, ccb, CAM_ESF_ALL,
3888                                         CAM_EPF_ALL, stderr);
3889
3890                 retval = 1;
3891                 goto bailout;
3892         }
3893
3894         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3895                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3896                 retval = 1;
3897                 goto bailout;
3898         }
3899
3900
3901         list_len = scsi_4btoul(lundata->length);
3902
3903         /*
3904          * If we need to list the LUNs, and our allocation
3905          * length was too short, reallocate and retry.
3906          */
3907         if ((countonly == 0)
3908          && (list_len > (alloc_len - sizeof(*lundata)))) {
3909                 alloc_len = list_len + sizeof(*lundata);
3910                 free(lundata);
3911                 goto retry;
3912         }
3913
3914         if (lunsonly == 0)
3915                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
3916                         ((list_len / 8) > 1) ? "s" : "");
3917
3918         if (countonly != 0)
3919                 goto bailout;
3920
3921         for (i = 0; i < (list_len / 8); i++) {
3922                 int no_more;
3923
3924                 no_more = 0;
3925                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
3926                         if (j != 0)
3927                                 fprintf(stdout, ",");
3928                         switch (lundata->luns[i].lundata[j] &
3929                                 RPL_LUNDATA_ATYP_MASK) {
3930                         case RPL_LUNDATA_ATYP_PERIPH:
3931                                 if ((lundata->luns[i].lundata[j] &
3932                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
3933                                         fprintf(stdout, "%d:", 
3934                                                 lundata->luns[i].lundata[j] &
3935                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
3936                                 else if ((j == 0)
3937                                       && ((lundata->luns[i].lundata[j+2] &
3938                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
3939                                         no_more = 1;
3940
3941                                 fprintf(stdout, "%d",
3942                                         lundata->luns[i].lundata[j+1]);
3943                                 break;
3944                         case RPL_LUNDATA_ATYP_FLAT: {
3945                                 uint8_t tmplun[2];
3946                                 tmplun[0] = lundata->luns[i].lundata[j] &
3947                                         RPL_LUNDATA_FLAT_LUN_MASK;
3948                                 tmplun[1] = lundata->luns[i].lundata[j+1];
3949
3950                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
3951                                 no_more = 1;
3952                                 break;
3953                         }
3954                         case RPL_LUNDATA_ATYP_LUN:
3955                                 fprintf(stdout, "%d:%d:%d",
3956                                         (lundata->luns[i].lundata[j+1] &
3957                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
3958                                         lundata->luns[i].lundata[j] &
3959                                         RPL_LUNDATA_LUN_TARG_MASK,
3960                                         lundata->luns[i].lundata[j+1] &
3961                                         RPL_LUNDATA_LUN_LUN_MASK);
3962                                 break;
3963                         case RPL_LUNDATA_ATYP_EXTLUN: {
3964                                 int field_len, field_len_code, eam_code;
3965
3966                                 eam_code = lundata->luns[i].lundata[j] &
3967                                         RPL_LUNDATA_EXT_EAM_MASK;
3968                                 field_len_code = (lundata->luns[i].lundata[j] &
3969                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
3970                                 field_len = field_len_code * 2;
3971                 
3972                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
3973                                  && (field_len_code == 0x00)) {
3974                                         fprintf(stdout, "%d",
3975                                                 lundata->luns[i].lundata[j+1]);
3976                                 } else if ((eam_code ==
3977                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
3978                                         && (field_len_code == 0x03)) {
3979                                         uint8_t tmp_lun[8];
3980
3981                                         /*
3982                                          * This format takes up all 8 bytes.
3983                                          * If we aren't starting at offset 0,
3984                                          * that's a bug.
3985                                          */
3986                                         if (j != 0) {
3987                                                 fprintf(stdout, "Invalid "
3988                                                         "offset %d for "
3989                                                         "Extended LUN not "
3990                                                         "specified format", j);
3991                                                 no_more = 1;
3992                                                 break;
3993                                         }
3994                                         bzero(tmp_lun, sizeof(tmp_lun));
3995                                         bcopy(&lundata->luns[i].lundata[j+1],
3996                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
3997                                         fprintf(stdout, "%#jx",
3998                                                (intmax_t)scsi_8btou64(tmp_lun));
3999                                         no_more = 1;
4000                                 } else {
4001                                         fprintf(stderr, "Unknown Extended LUN"
4002                                                 "Address method %#x, length "
4003                                                 "code %#x", eam_code,
4004                                                 field_len_code);
4005                                         no_more = 1;
4006                                 }
4007                                 break;
4008                         }
4009                         default:
4010                                 fprintf(stderr, "Unknown LUN address method "
4011                                         "%#x\n", lundata->luns[i].lundata[0] &
4012                                         RPL_LUNDATA_ATYP_MASK);
4013                                 break;
4014                         }
4015                         /*
4016                          * For the flat addressing method, there are no
4017                          * other levels after it.
4018                          */
4019                         if (no_more != 0)
4020                                 break;
4021                 }
4022                 fprintf(stdout, "\n");
4023         }
4024
4025 bailout:
4026
4027         cam_freeccb(ccb);
4028
4029         free(lundata);
4030
4031         return (retval);
4032 }
4033
4034 static int
4035 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4036                  char *combinedopt, int retry_count, int timeout)
4037 {
4038         union ccb *ccb;
4039         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4040         struct scsi_read_capacity_data rcap;
4041         struct scsi_read_capacity_data_long rcaplong;
4042         uint64_t maxsector;
4043         uint32_t block_len;
4044         int retval;
4045         int c;
4046
4047         blocksizeonly = 0;
4048         humanize = 0;
4049         numblocks = 0;
4050         quiet = 0;
4051         sizeonly = 0;
4052         baseten = 0;
4053         retval = 0;
4054
4055         ccb = cam_getccb(device);
4056
4057         if (ccb == NULL) {
4058                 warnx("%s: error allocating ccb", __func__);
4059                 return (1);
4060         }
4061
4062         bzero(&(&ccb->ccb_h)[1],
4063               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4064
4065         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4066                 switch (c) {
4067                 case 'b':
4068                         blocksizeonly++;
4069                         break;
4070                 case 'h':
4071                         humanize++;
4072                         baseten = 0;
4073                         break;
4074                 case 'H':
4075                         humanize++;
4076                         baseten++;
4077                         break;
4078                 case 'N':
4079                         numblocks++;
4080                         break;
4081                 case 'q':
4082                         quiet++;
4083                         break;
4084                 case 's':
4085                         sizeonly++;
4086                         break;
4087                 default:
4088                         break;
4089                 }
4090         }
4091
4092         if ((blocksizeonly != 0)
4093          && (numblocks != 0)) {
4094                 warnx("%s: you can only specify one of -b or -N", __func__);
4095                 retval = 1;
4096                 goto bailout;
4097         }
4098
4099         if ((blocksizeonly != 0)
4100          && (sizeonly != 0)) {
4101                 warnx("%s: you can only specify one of -b or -s", __func__);
4102                 retval = 1;
4103                 goto bailout;
4104         }
4105
4106         if ((humanize != 0)
4107          && (quiet != 0)) {
4108                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
4109                 retval = 1;
4110                 goto bailout;
4111         }
4112
4113         if ((humanize != 0)
4114          && (blocksizeonly != 0)) {
4115                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
4116                 retval = 1;
4117                 goto bailout;
4118         }
4119
4120         scsi_read_capacity(&ccb->csio,
4121                            /*retries*/ retry_count,
4122                            /*cbfcnp*/ NULL,
4123                            /*tag_action*/ MSG_SIMPLE_Q_TAG,
4124                            &rcap,
4125                            SSD_FULL_SIZE,
4126                            /*timeout*/ timeout ? timeout : 5000);
4127
4128         /* Disable freezing the device queue */
4129         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4130
4131         if (arglist & CAM_ARG_ERR_RECOVER)
4132                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4133
4134         if (cam_send_ccb(device, ccb) < 0) {
4135                 warn("error sending READ CAPACITY command");
4136
4137                 if (arglist & CAM_ARG_VERBOSE)
4138                         cam_error_print(device, ccb, CAM_ESF_ALL,
4139                                         CAM_EPF_ALL, stderr);
4140
4141                 retval = 1;
4142                 goto bailout;
4143         }
4144
4145         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4146                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4147                 retval = 1;
4148                 goto bailout;
4149         }
4150
4151         maxsector = scsi_4btoul(rcap.addr);
4152         block_len = scsi_4btoul(rcap.length);
4153
4154         /*
4155          * A last block of 2^32-1 means that the true capacity is over 2TB,
4156          * and we need to issue the long READ CAPACITY to get the real
4157          * capacity.  Otherwise, we're all set.
4158          */
4159         if (maxsector != 0xffffffff)
4160                 goto do_print;
4161
4162         scsi_read_capacity_16(&ccb->csio,
4163                               /*retries*/ retry_count,
4164                               /*cbfcnp*/ NULL,
4165                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
4166                               /*lba*/ 0,
4167                               /*reladdr*/ 0,
4168                               /*pmi*/ 0,
4169                               &rcaplong,
4170                               /*sense_len*/ SSD_FULL_SIZE,
4171                               /*timeout*/ timeout ? timeout : 5000);
4172
4173         /* Disable freezing the device queue */
4174         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4175
4176         if (arglist & CAM_ARG_ERR_RECOVER)
4177                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4178
4179         if (cam_send_ccb(device, ccb) < 0) {
4180                 warn("error sending READ CAPACITY (16) command");
4181
4182                 if (arglist & CAM_ARG_VERBOSE)
4183                         cam_error_print(device, ccb, CAM_ESF_ALL,
4184                                         CAM_EPF_ALL, stderr);
4185
4186                 retval = 1;
4187                 goto bailout;
4188         }
4189
4190         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4191                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4192                 retval = 1;
4193                 goto bailout;
4194         }
4195
4196         maxsector = scsi_8btou64(rcaplong.addr);
4197         block_len = scsi_4btoul(rcaplong.length);
4198
4199 do_print:
4200         if (blocksizeonly == 0) {
4201                 /*
4202                  * Humanize implies !quiet, and also implies numblocks.
4203                  */
4204                 if (humanize != 0) {
4205                         char tmpstr[6];
4206                         int64_t tmpbytes;
4207                         int ret;
4208
4209                         tmpbytes = (maxsector + 1) * block_len;
4210                         ret = humanize_number(tmpstr, sizeof(tmpstr),
4211                                               tmpbytes, "", HN_AUTOSCALE,
4212                                               HN_B | HN_DECIMAL |
4213                                               ((baseten != 0) ?
4214                                               HN_DIVISOR_1000 : 0));
4215                         if (ret == -1) {
4216                                 warnx("%s: humanize_number failed!", __func__);
4217                                 retval = 1;
4218                                 goto bailout;
4219                         }
4220                         fprintf(stdout, "Device Size: %s%s", tmpstr,
4221                                 (sizeonly == 0) ?  ", " : "\n");
4222                 } else if (numblocks != 0) {
4223                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4224                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
4225                                 (sizeonly == 0) ? ", " : "\n");
4226                 } else {
4227                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4228                                 "Last Block: " : "", (uintmax_t)maxsector,
4229                                 (sizeonly == 0) ? ", " : "\n");
4230                 }
4231         }
4232         if (sizeonly == 0)
4233                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4234                         "Block Length: " : "", block_len, (quiet == 0) ?
4235                         " bytes" : "");
4236 bailout:
4237         cam_freeccb(ccb);
4238
4239         return (retval);
4240 }
4241
4242 static int
4243 atapm(struct cam_device *device, int argc, char **argv,
4244                  char *combinedopt, int retry_count, int timeout)
4245 {
4246         union ccb *ccb;
4247         int retval = 0;
4248         int t = -1;
4249         int c;
4250         u_char cmd, sc;
4251
4252         ccb = cam_getccb(device);
4253
4254         if (ccb == NULL) {
4255                 warnx("%s: error allocating ccb", __func__);
4256                 return (1);
4257         }
4258
4259         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4260                 switch (c) {
4261                 case 't':
4262                         t = atoi(optarg);
4263                         break;
4264                 default:
4265                         break;
4266                 }
4267         }
4268         if (strcmp(argv[1], "idle") == 0) {
4269                 if (t == -1)
4270                         cmd = ATA_IDLE_IMMEDIATE;
4271                 else
4272                         cmd = ATA_IDLE_CMD;
4273         } else if (strcmp(argv[1], "standby") == 0) {
4274                 if (t == -1)
4275                         cmd = ATA_STANDBY_IMMEDIATE;
4276                 else
4277                         cmd = ATA_STANDBY_CMD;
4278         } else {
4279                 cmd = ATA_SLEEP;
4280                 t = -1;
4281         }
4282         if (t < 0)
4283                 sc = 0;
4284         else if (t <= (240 * 5))
4285                 sc = t / 5;
4286         else if (t <= (11 * 30 * 60))
4287                 sc = t / (30 * 60) + 241;
4288         else
4289                 sc = 253;
4290         cam_fill_ataio(&ccb->ataio,
4291                       retry_count,
4292                       NULL,
4293                       /*flags*/CAM_DIR_NONE,
4294                       MSG_SIMPLE_Q_TAG,
4295                       /*data_ptr*/NULL,
4296                       /*dxfer_len*/0,
4297                       timeout ? timeout : 30 * 1000);
4298         ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
4299
4300         /* Disable freezing the device queue */
4301         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4302
4303         if (arglist & CAM_ARG_ERR_RECOVER)
4304                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4305
4306         if (cam_send_ccb(device, ccb) < 0) {
4307                 warn("error sending command");
4308
4309                 if (arglist & CAM_ARG_VERBOSE)
4310                         cam_error_print(device, ccb, CAM_ESF_ALL,
4311                                         CAM_EPF_ALL, stderr);
4312
4313                 retval = 1;
4314                 goto bailout;
4315         }
4316
4317         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4318                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4319                 retval = 1;
4320                 goto bailout;
4321         }
4322 bailout:
4323         cam_freeccb(ccb);
4324         return (retval);
4325 }
4326
4327 #endif /* MINIMALISTIC */
4328
4329 void 
4330 usage(int verbose)
4331 {
4332         fprintf(verbose ? stdout : stderr,
4333 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
4334 "        camcontrol devlist    [-v]\n"
4335 #ifndef MINIMALISTIC
4336 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
4337 "        camcontrol tur        [dev_id][generic args]\n"
4338 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
4339 "        camcontrol identify   [dev_id][generic args] [-v]\n"
4340 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
4341 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
4342 "                              [-q] [-s]\n"
4343 "        camcontrol start      [dev_id][generic args]\n"
4344 "        camcontrol stop       [dev_id][generic args]\n"
4345 "        camcontrol load       [dev_id][generic args]\n"
4346 "        camcontrol eject      [dev_id][generic args]\n"
4347 #endif /* MINIMALISTIC */
4348 "        camcontrol rescan     <all | bus[:target:lun]>\n"
4349 "        camcontrol reset      <all | bus[:target:lun]>\n"
4350 #ifndef MINIMALISTIC
4351 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
4352 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
4353 "                              [-P pagectl][-e | -b][-d]\n"
4354 "        camcontrol cmd        [dev_id][generic args]\n"
4355 "                              <-a cmd [args] | -c cmd [args]>\n"
4356 "                              [-i len fmt|-o len fmt [args]] [-r fmt]\n"
4357 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
4358 "                              <all|bus[:target[:lun]]|off>\n"
4359 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
4360 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
4361 "                              [-D <enable|disable>][-M mode][-O offset]\n"
4362 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
4363 "                              [-U][-W bus_width]\n"
4364 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
4365 "        camcontrol idle       [dev_id][generic args][-t time]\n"
4366 "        camcontrol standby    [dev_id][generic args][-t time]\n"
4367 "        camcontrol sleep      [dev_id][generic args]\n"
4368 #endif /* MINIMALISTIC */
4369 "        camcontrol help\n");
4370         if (!verbose)
4371                 return;
4372 #ifndef MINIMALISTIC
4373         fprintf(stdout,
4374 "Specify one of the following options:\n"
4375 "devlist     list all CAM devices\n"
4376 "periphlist  list all CAM peripheral drivers attached to a device\n"
4377 "tur         send a test unit ready to the named device\n"
4378 "inquiry     send a SCSI inquiry command to the named device\n"
4379 "identify    send a ATA identify command to the named device\n"
4380 "reportluns  send a SCSI report luns command to the device\n"
4381 "readcap     send a SCSI read capacity command to the device\n"
4382 "start       send a Start Unit command to the device\n"
4383 "stop        send a Stop Unit command to the device\n"
4384 "load        send a Start Unit command to the device with the load bit set\n"
4385 "eject       send a Stop Unit command to the device with the eject bit set\n"
4386 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
4387 "reset       reset all busses, the given bus, or bus:target:lun\n"
4388 "defects     read the defect list of the specified device\n"
4389 "modepage    display or edit (-e) the given mode page\n"
4390 "cmd         send the given scsi command, may need -i or -o as well\n"
4391 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
4392 "tags        report or set the number of transaction slots for a device\n"
4393 "negotiate   report or set device negotiation parameters\n"
4394 "format      send the SCSI FORMAT UNIT command to the named device\n"
4395 "idle        send the ATA IDLE command to the named device\n"
4396 "standby     send the ATA STANDBY command to the named device\n"
4397 "sleep       send the ATA SLEEP command to the named device\n"
4398 "help        this message\n"
4399 "Device Identifiers:\n"
4400 "bus:target        specify the bus and target, lun defaults to 0\n"
4401 "bus:target:lun    specify the bus, target and lun\n"
4402 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
4403 "Generic arguments:\n"
4404 "-v                be verbose, print out sense information\n"
4405 "-t timeout        command timeout in seconds, overrides default timeout\n"
4406 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
4407 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
4408 "-E                have the kernel attempt to perform SCSI error recovery\n"
4409 "-C count          specify the SCSI command retry count (needs -E to work)\n"
4410 "modepage arguments:\n"
4411 "-l                list all available mode pages\n"
4412 "-m page           specify the mode page to view or edit\n"
4413 "-e                edit the specified mode page\n"
4414 "-b                force view to binary mode\n"
4415 "-d                disable block descriptors for mode sense\n"
4416 "-P pgctl          page control field 0-3\n"
4417 "defects arguments:\n"
4418 "-f format         specify defect list format (block, bfi or phys)\n"
4419 "-G                get the grown defect list\n"
4420 "-P                get the permanant defect list\n"
4421 "inquiry arguments:\n"
4422 "-D                get the standard inquiry data\n"
4423 "-S                get the serial number\n"
4424 "-R                get the transfer rate, etc.\n"
4425 "reportluns arguments:\n"
4426 "-c                only report a count of available LUNs\n"
4427 "-l                only print out luns, and not a count\n"
4428 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
4429 "readcap arguments\n"
4430 "-b                only report the blocksize\n"
4431 "-h                human readable device size, base 2\n"
4432 "-H                human readable device size, base 10\n"
4433 "-N                print the number of blocks instead of last block\n"
4434 "-q                quiet, print numbers only\n"
4435 "-s                only report the last block/device size\n"
4436 "cmd arguments:\n"
4437 "-c cdb [args]     specify the SCSI CDB\n"
4438 "-i len fmt        specify input data and input data format\n"
4439 "-o len fmt [args] specify output data and output data fmt\n"
4440 "debug arguments:\n"
4441 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
4442 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
4443 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
4444 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
4445 "tags arguments:\n"
4446 "-N tags           specify the number of tags to use for this device\n"
4447 "-q                be quiet, don't report the number of tags\n"
4448 "-v                report a number of tag-related parameters\n"
4449 "negotiate arguments:\n"
4450 "-a                send a test unit ready after negotiation\n"
4451 "-c                report/set current negotiation settings\n"
4452 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
4453 "-M mode           set ATA mode\n"
4454 "-O offset         set command delay offset\n"
4455 "-q                be quiet, don't report anything\n"
4456 "-R syncrate       synchronization rate in MHz\n"
4457 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
4458 "-U                report/set user negotiation settings\n"
4459 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
4460 "-v                also print a Path Inquiry CCB for the controller\n"
4461 "format arguments:\n"
4462 "-q                be quiet, don't print status messages\n"
4463 "-r                run in report only mode\n"
4464 "-w                don't send immediate format command\n"
4465 "-y                don't ask any questions\n"
4466 "idle/standby arguments:\n"
4467 "-t <arg>          number of seconds before respective state.\n");
4468 #endif /* MINIMALISTIC */
4469 }
4470
4471 int 
4472 main(int argc, char **argv)
4473 {
4474         int c;
4475         char *device = NULL;
4476         int unit = 0;
4477         struct cam_device *cam_dev = NULL;
4478         int timeout = 0, retry_count = 1;
4479         camcontrol_optret optreturn;
4480         char *tstr;
4481         const char *mainopt = "C:En:t:u:v";
4482         const char *subopt = NULL;
4483         char combinedopt[256];
4484         int error = 0, optstart = 2;
4485         int devopen = 1;
4486 #ifndef MINIMALISTIC
4487         int bus, target, lun;
4488 #endif /* MINIMALISTIC */
4489
4490         cmdlist = CAM_CMD_NONE;
4491         arglist = CAM_ARG_NONE;
4492
4493         if (argc < 2) {
4494                 usage(0);
4495                 exit(1);
4496         }
4497
4498         /*
4499          * Get the base option.
4500          */
4501         optreturn = getoption(argv[1], &cmdlist, &arglist, &subopt);
4502
4503         if (optreturn == CC_OR_AMBIGUOUS) {
4504                 warnx("ambiguous option %s", argv[1]);
4505                 usage(0);
4506                 exit(1);
4507         } else if (optreturn == CC_OR_NOT_FOUND) {
4508                 warnx("option %s not found", argv[1]);
4509                 usage(0);
4510                 exit(1);
4511         }
4512
4513         /*
4514          * Ahh, getopt(3) is a pain.
4515          *
4516          * This is a gross hack.  There really aren't many other good
4517          * options (excuse the pun) for parsing options in a situation like
4518          * this.  getopt is kinda braindead, so you end up having to run
4519          * through the options twice, and give each invocation of getopt
4520          * the option string for the other invocation.
4521          * 
4522          * You would think that you could just have two groups of options.
4523          * The first group would get parsed by the first invocation of
4524          * getopt, and the second group would get parsed by the second
4525          * invocation of getopt.  It doesn't quite work out that way.  When
4526          * the first invocation of getopt finishes, it leaves optind pointing
4527          * to the argument _after_ the first argument in the second group.
4528          * So when the second invocation of getopt comes around, it doesn't
4529          * recognize the first argument it gets and then bails out.
4530          * 
4531          * A nice alternative would be to have a flag for getopt that says
4532          * "just keep parsing arguments even when you encounter an unknown
4533          * argument", but there isn't one.  So there's no real clean way to
4534          * easily parse two sets of arguments without having one invocation
4535          * of getopt know about the other.
4536          * 
4537          * Without this hack, the first invocation of getopt would work as
4538          * long as the generic arguments are first, but the second invocation
4539          * (in the subfunction) would fail in one of two ways.  In the case
4540          * where you don't set optreset, it would fail because optind may be
4541          * pointing to the argument after the one it should be pointing at.
4542          * In the case where you do set optreset, and reset optind, it would
4543          * fail because getopt would run into the first set of options, which
4544          * it doesn't understand.
4545          *
4546          * All of this would "sort of" work if you could somehow figure out
4547          * whether optind had been incremented one option too far.  The
4548          * mechanics of that, however, are more daunting than just giving
4549          * both invocations all of the expect options for either invocation.
4550          * 
4551          * Needless to say, I wouldn't mind if someone invented a better
4552          * (non-GPL!) command line parsing interface than getopt.  I
4553          * wouldn't mind if someone added more knobs to getopt to make it
4554          * work better.  Who knows, I may talk myself into doing it someday,
4555          * if the standards weenies let me.  As it is, it just leads to
4556          * hackery like this and causes people to avoid it in some cases.
4557          * 
4558          * KDM, September 8th, 1998
4559          */
4560         if (subopt != NULL)
4561                 sprintf(combinedopt, "%s%s", mainopt, subopt);
4562         else
4563                 sprintf(combinedopt, "%s", mainopt);
4564
4565         /*
4566          * For these options we do not parse optional device arguments and
4567          * we do not open a passthrough device.
4568          */
4569         if ((cmdlist == CAM_CMD_RESCAN)
4570          || (cmdlist == CAM_CMD_RESET)
4571          || (cmdlist == CAM_CMD_DEVTREE)
4572          || (cmdlist == CAM_CMD_USAGE)
4573          || (cmdlist == CAM_CMD_DEBUG))
4574                 devopen = 0;
4575
4576 #ifndef MINIMALISTIC
4577         if ((devopen == 1)
4578          && (argc > 2 && argv[2][0] != '-')) {
4579                 char name[30];
4580                 int rv;
4581
4582                 /*
4583                  * First catch people who try to do things like:
4584                  * camcontrol tur /dev/da0 
4585                  * camcontrol doesn't take device nodes as arguments.
4586                  */
4587                 if (argv[2][0] == '/') {
4588                         warnx("%s is not a valid device identifier", argv[2]);
4589                         errx(1, "please read the camcontrol(8) man page");
4590                 } else if (isdigit(argv[2][0])) {
4591                         /* device specified as bus:target[:lun] */
4592                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
4593                         if (rv < 2)
4594                                 errx(1, "numeric device specification must "
4595                                      "be either bus:target, or "
4596                                      "bus:target:lun");
4597                         /* default to 0 if lun was not specified */
4598                         if ((arglist & CAM_ARG_LUN) == 0) {
4599                                 lun = 0;
4600                                 arglist |= CAM_ARG_LUN;
4601                         }
4602                         optstart++;
4603                 } else {
4604                         if (cam_get_device(argv[2], name, sizeof name, &unit)
4605                             == -1)
4606                                 errx(1, "%s", cam_errbuf);
4607                         device = strdup(name);
4608                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
4609                         optstart++;
4610                 }
4611         }
4612 #endif /* MINIMALISTIC */
4613         /*
4614          * Start getopt processing at argv[2/3], since we've already
4615          * accepted argv[1..2] as the command name, and as a possible
4616          * device name.
4617          */
4618         optind = optstart;
4619
4620         /*
4621          * Now we run through the argument list looking for generic
4622          * options, and ignoring options that possibly belong to
4623          * subfunctions.
4624          */
4625         while ((c = getopt(argc, argv, combinedopt))!= -1){
4626                 switch(c) {
4627                         case 'C':
4628                                 retry_count = strtol(optarg, NULL, 0);
4629                                 if (retry_count < 0)
4630                                         errx(1, "retry count %d is < 0",
4631                                              retry_count);
4632                                 arglist |= CAM_ARG_RETRIES;
4633                                 break;
4634                         case 'E':
4635                                 arglist |= CAM_ARG_ERR_RECOVER;
4636                                 break;
4637                         case 'n':
4638                                 arglist |= CAM_ARG_DEVICE;
4639                                 tstr = optarg;
4640                                 while (isspace(*tstr) && (*tstr != '\0'))
4641                                         tstr++;
4642                                 device = (char *)strdup(tstr);
4643                                 break;
4644                         case 't':
4645                                 timeout = strtol(optarg, NULL, 0);
4646                                 if (timeout < 0)
4647                                         errx(1, "invalid timeout %d", timeout);
4648                                 /* Convert the timeout from seconds to ms */
4649                                 timeout *= 1000;
4650                                 arglist |= CAM_ARG_TIMEOUT;
4651                                 break;
4652                         case 'u':
4653                                 arglist |= CAM_ARG_UNIT;
4654                                 unit = strtol(optarg, NULL, 0);
4655                                 break;
4656                         case 'v':
4657                                 arglist |= CAM_ARG_VERBOSE;
4658                                 break;
4659                         default:
4660                                 break;
4661                 }
4662         }
4663
4664 #ifndef MINIMALISTIC
4665         /*
4666          * For most commands we'll want to open the passthrough device
4667          * associated with the specified device.  In the case of the rescan
4668          * commands, we don't use a passthrough device at all, just the
4669          * transport layer device.
4670          */
4671         if (devopen == 1) {
4672                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
4673                  && (((arglist & CAM_ARG_DEVICE) == 0)
4674                   || ((arglist & CAM_ARG_UNIT) == 0))) {
4675                         errx(1, "subcommand \"%s\" requires a valid device "
4676                              "identifier", argv[1]);
4677                 }
4678
4679                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
4680                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
4681                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
4682                      == NULL)
4683                         errx(1,"%s", cam_errbuf);
4684         }
4685 #endif /* MINIMALISTIC */
4686
4687         /*
4688          * Reset optind to 2, and reset getopt, so these routines can parse
4689          * the arguments again.
4690          */
4691         optind = optstart;
4692         optreset = 1;
4693
4694         switch(cmdlist) {
4695 #ifndef MINIMALISTIC
4696                 case CAM_CMD_DEVLIST:
4697                         error = getdevlist(cam_dev);
4698                         break;
4699 #endif /* MINIMALISTIC */
4700                 case CAM_CMD_DEVTREE:
4701                         error = getdevtree();
4702                         break;
4703 #ifndef MINIMALISTIC
4704                 case CAM_CMD_TUR:
4705                         error = testunitready(cam_dev, retry_count, timeout, 0);
4706                         break;
4707                 case CAM_CMD_INQUIRY:
4708                         error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
4709                                               retry_count, timeout);
4710                         break;
4711                 case CAM_CMD_IDENTIFY:
4712                         error = ataidentify(cam_dev, retry_count, timeout);
4713                         break;
4714                 case CAM_CMD_STARTSTOP:
4715                         error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
4716                                           arglist & CAM_ARG_EJECT, retry_count,
4717                                           timeout);
4718                         break;
4719 #endif /* MINIMALISTIC */
4720                 case CAM_CMD_RESCAN:
4721                         error = dorescan_or_reset(argc, argv, 1);
4722                         break;
4723                 case CAM_CMD_RESET:
4724                         error = dorescan_or_reset(argc, argv, 0);
4725                         break;
4726 #ifndef MINIMALISTIC
4727                 case CAM_CMD_READ_DEFECTS:
4728                         error = readdefects(cam_dev, argc, argv, combinedopt,
4729                                             retry_count, timeout);
4730                         break;
4731                 case CAM_CMD_MODE_PAGE:
4732                         modepage(cam_dev, argc, argv, combinedopt,
4733                                  retry_count, timeout);
4734                         break;
4735                 case CAM_CMD_SCSI_CMD:
4736                         error = scsicmd(cam_dev, argc, argv, combinedopt,
4737                                         retry_count, timeout);
4738                         break;
4739                 case CAM_CMD_DEBUG:
4740                         error = camdebug(argc, argv, combinedopt);
4741                         break;
4742                 case CAM_CMD_TAG:
4743                         error = tagcontrol(cam_dev, argc, argv, combinedopt);
4744                         break;
4745                 case CAM_CMD_RATE:
4746                         error = ratecontrol(cam_dev, retry_count, timeout,
4747                                             argc, argv, combinedopt);
4748                         break;
4749                 case CAM_CMD_FORMAT:
4750                         error = scsiformat(cam_dev, argc, argv,
4751                                            combinedopt, retry_count, timeout);
4752                         break;
4753                 case CAM_CMD_REPORTLUNS:
4754                         error = scsireportluns(cam_dev, argc, argv,
4755                                                combinedopt, retry_count,
4756                                                timeout);
4757                         break;
4758                 case CAM_CMD_READCAP:
4759                         error = scsireadcapacity(cam_dev, argc, argv,
4760                                                  combinedopt, retry_count,
4761                                                  timeout);
4762                         break;
4763                 case CAM_CMD_IDLE:
4764                 case CAM_CMD_STANDBY:
4765                 case CAM_CMD_SLEEP:
4766                         error = atapm(cam_dev, argc, argv,
4767                                                  combinedopt, retry_count,
4768                                                  timeout);
4769                         break;
4770 #endif /* MINIMALISTIC */
4771                 case CAM_CMD_USAGE:
4772                         usage(1);
4773                         break;
4774                 default:
4775                         usage(0);
4776                         error = 1;
4777                         break;
4778         }
4779
4780         if (cam_dev != NULL)
4781                 cam_close_device(cam_dev);
4782
4783         exit(error);
4784 }