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