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