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