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