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