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