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