]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/camcontrol/camcontrol.c
MFV r299425:
[FreeBSD/FreeBSD.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/stat.h>
36 #include <sys/endian.h>
37 #include <sys/sbuf.h>
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <inttypes.h>
44 #include <limits.h>
45 #include <fcntl.h>
46 #include <ctype.h>
47 #include <err.h>
48 #include <libutil.h>
49 #ifndef MINIMALISTIC
50 #include <limits.h>
51 #include <inttypes.h>
52 #endif
53
54 #include <cam/cam.h>
55 #include <cam/cam_debug.h>
56 #include <cam/cam_ccb.h>
57 #include <cam/scsi/scsi_all.h>
58 #include <cam/scsi/scsi_da.h>
59 #include <cam/scsi/scsi_pass.h>
60 #include <cam/scsi/scsi_message.h>
61 #include <cam/scsi/smp_all.h>
62 #include <cam/ata/ata_all.h>
63 #include <camlib.h>
64 #include "camcontrol.h"
65
66 typedef enum {
67         CAM_CMD_NONE            = 0x00000000,
68         CAM_CMD_DEVLIST         = 0x00000001,
69         CAM_CMD_TUR             = 0x00000002,
70         CAM_CMD_INQUIRY         = 0x00000003,
71         CAM_CMD_STARTSTOP       = 0x00000004,
72         CAM_CMD_RESCAN          = 0x00000005,
73         CAM_CMD_READ_DEFECTS    = 0x00000006,
74         CAM_CMD_MODE_PAGE       = 0x00000007,
75         CAM_CMD_SCSI_CMD        = 0x00000008,
76         CAM_CMD_DEVTREE         = 0x00000009,
77         CAM_CMD_USAGE           = 0x0000000a,
78         CAM_CMD_DEBUG           = 0x0000000b,
79         CAM_CMD_RESET           = 0x0000000c,
80         CAM_CMD_FORMAT          = 0x0000000d,
81         CAM_CMD_TAG             = 0x0000000e,
82         CAM_CMD_RATE            = 0x0000000f,
83         CAM_CMD_DETACH          = 0x00000010,
84         CAM_CMD_REPORTLUNS      = 0x00000011,
85         CAM_CMD_READCAP         = 0x00000012,
86         CAM_CMD_IDENTIFY        = 0x00000013,
87         CAM_CMD_IDLE            = 0x00000014,
88         CAM_CMD_STANDBY         = 0x00000015,
89         CAM_CMD_SLEEP           = 0x00000016,
90         CAM_CMD_SMP_CMD         = 0x00000017,
91         CAM_CMD_SMP_RG          = 0x00000018,
92         CAM_CMD_SMP_PC          = 0x00000019,
93         CAM_CMD_SMP_PHYLIST     = 0x0000001a,
94         CAM_CMD_SMP_MANINFO     = 0x0000001b,
95         CAM_CMD_DOWNLOAD_FW     = 0x0000001c,
96         CAM_CMD_SECURITY        = 0x0000001d,
97         CAM_CMD_HPA             = 0x0000001e,
98         CAM_CMD_SANITIZE        = 0x0000001f,
99         CAM_CMD_PERSIST         = 0x00000020,
100         CAM_CMD_APM             = 0x00000021,
101         CAM_CMD_AAM             = 0x00000022,
102         CAM_CMD_ATTRIB          = 0x00000023,
103         CAM_CMD_OPCODES         = 0x00000024,
104         CAM_CMD_REPROBE         = 0x00000025
105 } cam_cmdmask;
106
107 typedef enum {
108         CAM_ARG_NONE            = 0x00000000,
109         CAM_ARG_VERBOSE         = 0x00000001,
110         CAM_ARG_DEVICE          = 0x00000002,
111         CAM_ARG_BUS             = 0x00000004,
112         CAM_ARG_TARGET          = 0x00000008,
113         CAM_ARG_LUN             = 0x00000010,
114         CAM_ARG_EJECT           = 0x00000020,
115         CAM_ARG_UNIT            = 0x00000040,
116         CAM_ARG_FORMAT_BLOCK    = 0x00000080,
117         CAM_ARG_FORMAT_BFI      = 0x00000100,
118         CAM_ARG_FORMAT_PHYS     = 0x00000200,
119         CAM_ARG_PLIST           = 0x00000400,
120         CAM_ARG_GLIST           = 0x00000800,
121         CAM_ARG_GET_SERIAL      = 0x00001000,
122         CAM_ARG_GET_STDINQ      = 0x00002000,
123         CAM_ARG_GET_XFERRATE    = 0x00004000,
124         CAM_ARG_INQ_MASK        = 0x00007000,
125         CAM_ARG_MODE_EDIT       = 0x00008000,
126         CAM_ARG_PAGE_CNTL       = 0x00010000,
127         CAM_ARG_TIMEOUT         = 0x00020000,
128         CAM_ARG_CMD_IN          = 0x00040000,
129         CAM_ARG_CMD_OUT         = 0x00080000,
130         CAM_ARG_DBD             = 0x00100000,
131         CAM_ARG_ERR_RECOVER     = 0x00200000,
132         CAM_ARG_RETRIES         = 0x00400000,
133         CAM_ARG_START_UNIT      = 0x00800000,
134         CAM_ARG_DEBUG_INFO      = 0x01000000,
135         CAM_ARG_DEBUG_TRACE     = 0x02000000,
136         CAM_ARG_DEBUG_SUBTRACE  = 0x04000000,
137         CAM_ARG_DEBUG_CDB       = 0x08000000,
138         CAM_ARG_DEBUG_XPT       = 0x10000000,
139         CAM_ARG_DEBUG_PERIPH    = 0x20000000,
140         CAM_ARG_DEBUG_PROBE     = 0x40000000,
141 } cam_argmask;
142
143 struct camcontrol_opts {
144         const char      *optname;
145         uint32_t        cmdnum;
146         cam_argmask     argnum;
147         const char      *subopt;
148 };
149
150 #ifndef MINIMALISTIC
151 struct ata_res_pass16 {
152         u_int16_t reserved[5];
153         u_int8_t flags;
154         u_int8_t error;
155         u_int8_t sector_count_exp;
156         u_int8_t sector_count;
157         u_int8_t lba_low_exp;
158         u_int8_t lba_low;
159         u_int8_t lba_mid_exp;
160         u_int8_t lba_mid;
161         u_int8_t lba_high_exp;
162         u_int8_t lba_high;
163         u_int8_t device;
164         u_int8_t status;
165 };
166
167 struct ata_set_max_pwd
168 {
169         u_int16_t reserved1;
170         u_int8_t password[32];
171         u_int16_t reserved2[239];
172 };
173
174 static const char scsicmd_opts[] = "a:c:dfi:o:r";
175 static const char readdefect_opts[] = "f:GPqsS:X";
176 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
177 static const char smprg_opts[] = "l";
178 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
179 static const char smpphylist_opts[] = "lq";
180 static char pwd_opt;
181 #endif
182
183 static struct camcontrol_opts option_table[] = {
184 #ifndef MINIMALISTIC
185         {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
186         {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
187         {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
188         {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
189         {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
190         {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
191         {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
192         {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
193         {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
194         {"reprobe", CAM_CMD_REPROBE, CAM_ARG_NONE, NULL},
195 #endif /* MINIMALISTIC */
196         {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
197         {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
198 #ifndef MINIMALISTIC
199         {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
200         {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
201         {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
202         {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
203         {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
204         {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
205         {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
206         {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
207         {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
208         {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
209         {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
210         {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
211 #endif /* MINIMALISTIC */
212         {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, "-b"},
213 #ifndef MINIMALISTIC
214         {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
215         {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
216         {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
217         {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
218         {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
219         {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
220         {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
221         {"sanitize", CAM_CMD_SANITIZE, CAM_ARG_NONE, "a:c:IP:qrUwy"},
222         {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
223         {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
224         {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
225         {"apm", CAM_CMD_APM, CAM_ARG_NONE, "l:"},
226         {"aam", CAM_CMD_AAM, CAM_ARG_NONE, "l:"},
227         {"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:qsy"},
228         {"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"},
229         {"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"},
230         {"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"},
231         {"attrib", CAM_CMD_ATTRIB, CAM_ARG_NONE, "a:ce:F:p:r:s:T:w:V:"},
232         {"opcodes", CAM_CMD_OPCODES, CAM_ARG_NONE, "No:s:T"},
233 #endif /* MINIMALISTIC */
234         {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
235         {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
236         {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
237         {NULL, 0, 0, NULL}
238 };
239
240 struct cam_devitem {
241         struct device_match_result dev_match;
242         int num_periphs;
243         struct periph_match_result *periph_matches;
244         struct scsi_vpd_device_id *device_id;
245         int device_id_len;
246         STAILQ_ENTRY(cam_devitem) links;
247 };
248
249 struct cam_devlist {
250         STAILQ_HEAD(, cam_devitem) dev_queue;
251         path_id_t path_id;
252 };
253
254 static cam_cmdmask cmdlist;
255 static cam_argmask arglist;
256
257 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
258                             uint32_t *cmdnum, cam_argmask *argnum,
259                             const char **subopt);
260 #ifndef MINIMALISTIC
261 static int getdevlist(struct cam_device *device);
262 #endif /* MINIMALISTIC */
263 static int getdevtree(int argc, char **argv, char *combinedopt);
264 #ifndef MINIMALISTIC
265 static int testunitready(struct cam_device *device, int retry_count,
266                          int timeout, int quiet);
267 static int scsistart(struct cam_device *device, int startstop, int loadeject,
268                      int retry_count, int timeout);
269 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
270 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
271 #endif /* MINIMALISTIC */
272 static int parse_btl(char *tstr, path_id_t *bus, target_id_t *target,
273                      lun_id_t *lun, cam_argmask *arglst);
274 static int dorescan_or_reset(int argc, char **argv, int rescan);
275 static int rescan_or_reset_bus(path_id_t bus, int rescan);
276 static int scanlun_or_reset_dev(path_id_t bus, target_id_t target,
277     lun_id_t lun, int scan);
278 #ifndef MINIMALISTIC
279 static int readdefects(struct cam_device *device, int argc, char **argv,
280                        char *combinedopt, int retry_count, int timeout);
281 static void modepage(struct cam_device *device, int argc, char **argv,
282                      char *combinedopt, int retry_count, int timeout);
283 static int scsicmd(struct cam_device *device, int argc, char **argv,
284                    char *combinedopt, int retry_count, int timeout);
285 static int smpcmd(struct cam_device *device, int argc, char **argv,
286                   char *combinedopt, int retry_count, int timeout);
287 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
288                             char *combinedopt, int retry_count, int timeout);
289 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
290                          char *combinedopt, int retry_count, int timeout);
291 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
292                       char *combinedopt, int retry_count, int timeout);
293 static int getdevid(struct cam_devitem *item);
294 static int buildbusdevlist(struct cam_devlist *devlist);
295 static void freebusdevlist(struct cam_devlist *devlist);
296 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
297                                          uint64_t sasaddr);
298 static int smpphylist(struct cam_device *device, int argc, char **argv,
299                       char *combinedopt, int retry_count, int timeout);
300 static int tagcontrol(struct cam_device *device, int argc, char **argv,
301                       char *combinedopt);
302 static void cts_print(struct cam_device *device,
303                       struct ccb_trans_settings *cts);
304 static void cpi_print(struct ccb_pathinq *cpi);
305 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
306 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
307 static int get_print_cts(struct cam_device *device, int user_settings,
308                          int quiet, struct ccb_trans_settings *cts);
309 static int ratecontrol(struct cam_device *device, int retry_count,
310                        int timeout, int argc, char **argv, char *combinedopt);
311 static int scsiformat(struct cam_device *device, int argc, char **argv,
312                       char *combinedopt, int retry_count, int timeout);
313 static int scsisanitize(struct cam_device *device, int argc, char **argv,
314                         char *combinedopt, int retry_count, int timeout);
315 static int scsireportluns(struct cam_device *device, int argc, char **argv,
316                           char *combinedopt, int retry_count, int timeout);
317 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
318                             char *combinedopt, int retry_count, int timeout);
319 static int atapm(struct cam_device *device, int argc, char **argv,
320                  char *combinedopt, int retry_count, int timeout);
321 static int atasecurity(struct cam_device *device, int retry_count, int timeout,
322                        int argc, char **argv, char *combinedopt);
323 static int atahpa(struct cam_device *device, int retry_count, int timeout,
324                   int argc, char **argv, char *combinedopt);
325 static int scsiprintoneopcode(struct cam_device *device, int req_opcode,
326                               int sa_set, int req_sa, uint8_t *buf,
327                               uint32_t valid_len);
328 static int scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
329                             uint32_t valid_len);
330 static int scsiopcodes(struct cam_device *device, int argc, char **argv,
331                        char *combinedopt, int retry_count, int timeout,
332                        int verbose);
333 static int scsireprobe(struct cam_device *device);
334
335 #endif /* MINIMALISTIC */
336 #ifndef min
337 #define min(a,b) (((a)<(b))?(a):(b))
338 #endif
339 #ifndef max
340 #define max(a,b) (((a)>(b))?(a):(b))
341 #endif
342
343 camcontrol_optret
344 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
345           cam_argmask *argnum, const char **subopt)
346 {
347         struct camcontrol_opts *opts;
348         int num_matches = 0;
349
350         for (opts = table; (opts != NULL) && (opts->optname != NULL);
351              opts++) {
352                 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
353                         *cmdnum = opts->cmdnum;
354                         *argnum = opts->argnum;
355                         *subopt = opts->subopt;
356                         if (++num_matches > 1)
357                                 return(CC_OR_AMBIGUOUS);
358                 }
359         }
360
361         if (num_matches > 0)
362                 return(CC_OR_FOUND);
363         else
364                 return(CC_OR_NOT_FOUND);
365 }
366
367 #ifndef MINIMALISTIC
368 static int
369 getdevlist(struct cam_device *device)
370 {
371         union ccb *ccb;
372         char status[32];
373         int error = 0;
374
375         ccb = cam_getccb(device);
376
377         ccb->ccb_h.func_code = XPT_GDEVLIST;
378         ccb->ccb_h.flags = CAM_DIR_NONE;
379         ccb->ccb_h.retry_count = 1;
380         ccb->cgdl.index = 0;
381         ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
382         while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
383                 if (cam_send_ccb(device, ccb) < 0) {
384                         perror("error getting device list");
385                         cam_freeccb(ccb);
386                         return(1);
387                 }
388
389                 status[0] = '\0';
390
391                 switch (ccb->cgdl.status) {
392                         case CAM_GDEVLIST_MORE_DEVS:
393                                 strcpy(status, "MORE");
394                                 break;
395                         case CAM_GDEVLIST_LAST_DEVICE:
396                                 strcpy(status, "LAST");
397                                 break;
398                         case CAM_GDEVLIST_LIST_CHANGED:
399                                 strcpy(status, "CHANGED");
400                                 break;
401                         case CAM_GDEVLIST_ERROR:
402                                 strcpy(status, "ERROR");
403                                 error = 1;
404                                 break;
405                 }
406
407                 fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
408                         ccb->cgdl.periph_name,
409                         ccb->cgdl.unit_number,
410                         ccb->cgdl.generation,
411                         ccb->cgdl.index,
412                         status);
413
414                 /*
415                  * If the list has changed, we need to start over from the
416                  * beginning.
417                  */
418                 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
419                         ccb->cgdl.index = 0;
420         }
421
422         cam_freeccb(ccb);
423
424         return(error);
425 }
426 #endif /* MINIMALISTIC */
427
428 static int
429 getdevtree(int argc, char **argv, char *combinedopt)
430 {
431         union ccb ccb;
432         int bufsize, fd;
433         unsigned int i;
434         int need_close = 0;
435         int error = 0;
436         int skip_device = 0;
437         int busonly = 0;
438         int c;
439
440         while ((c = getopt(argc, argv, combinedopt)) != -1) {
441                 switch(c) {
442                 case 'b':
443                         if ((arglist & CAM_ARG_VERBOSE) == 0)
444                                 busonly = 1;
445                         break;
446                 default:
447                         break;
448                 }
449         }
450
451         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
452                 warn("couldn't open %s", XPT_DEVICE);
453                 return(1);
454         }
455
456         bzero(&ccb, sizeof(union ccb));
457
458         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
459         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
460         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
461
462         ccb.ccb_h.func_code = XPT_DEV_MATCH;
463         bufsize = sizeof(struct dev_match_result) * 100;
464         ccb.cdm.match_buf_len = bufsize;
465         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
466         if (ccb.cdm.matches == NULL) {
467                 warnx("can't malloc memory for matches");
468                 close(fd);
469                 return(1);
470         }
471         ccb.cdm.num_matches = 0;
472
473         /*
474          * We fetch all nodes, since we display most of them in the default
475          * case, and all in the verbose case.
476          */
477         ccb.cdm.num_patterns = 0;
478         ccb.cdm.pattern_buf_len = 0;
479
480         /*
481          * We do the ioctl multiple times if necessary, in case there are
482          * more than 100 nodes in the EDT.
483          */
484         do {
485                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
486                         warn("error sending CAMIOCOMMAND ioctl");
487                         error = 1;
488                         break;
489                 }
490
491                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
492                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
493                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
494                         warnx("got CAM error %#x, CDM error %d\n",
495                               ccb.ccb_h.status, ccb.cdm.status);
496                         error = 1;
497                         break;
498                 }
499
500                 for (i = 0; i < ccb.cdm.num_matches; i++) {
501                         switch (ccb.cdm.matches[i].type) {
502                         case DEV_MATCH_BUS: {
503                                 struct bus_match_result *bus_result;
504
505                                 /*
506                                  * Only print the bus information if the
507                                  * user turns on the verbose flag.
508                                  */
509                                 if ((busonly == 0) &&
510                                     (arglist & CAM_ARG_VERBOSE) == 0)
511                                         break;
512
513                                 bus_result =
514                                         &ccb.cdm.matches[i].result.bus_result;
515
516                                 if (need_close) {
517                                         fprintf(stdout, ")\n");
518                                         need_close = 0;
519                                 }
520
521                                 fprintf(stdout, "scbus%d on %s%d bus %d%s\n",
522                                         bus_result->path_id,
523                                         bus_result->dev_name,
524                                         bus_result->unit_number,
525                                         bus_result->bus_id,
526                                         (busonly ? "" : ":"));
527                                 break;
528                         }
529                         case DEV_MATCH_DEVICE: {
530                                 struct device_match_result *dev_result;
531                                 char vendor[16], product[48], revision[16];
532                                 char fw[5], tmpstr[256];
533
534                                 if (busonly == 1)
535                                         break;
536
537                                 dev_result =
538                                      &ccb.cdm.matches[i].result.device_result;
539
540                                 if ((dev_result->flags
541                                      & DEV_RESULT_UNCONFIGURED)
542                                  && ((arglist & CAM_ARG_VERBOSE) == 0)) {
543                                         skip_device = 1;
544                                         break;
545                                 } else
546                                         skip_device = 0;
547
548                                 if (dev_result->protocol == PROTO_SCSI) {
549                                     cam_strvis(vendor, dev_result->inq_data.vendor,
550                                            sizeof(dev_result->inq_data.vendor),
551                                            sizeof(vendor));
552                                     cam_strvis(product,
553                                            dev_result->inq_data.product,
554                                            sizeof(dev_result->inq_data.product),
555                                            sizeof(product));
556                                     cam_strvis(revision,
557                                            dev_result->inq_data.revision,
558                                           sizeof(dev_result->inq_data.revision),
559                                            sizeof(revision));
560                                     sprintf(tmpstr, "<%s %s %s>", vendor, product,
561                                         revision);
562                                 } else if (dev_result->protocol == PROTO_ATA ||
563                                     dev_result->protocol == PROTO_SATAPM) {
564                                     cam_strvis(product,
565                                            dev_result->ident_data.model,
566                                            sizeof(dev_result->ident_data.model),
567                                            sizeof(product));
568                                     cam_strvis(revision,
569                                            dev_result->ident_data.revision,
570                                           sizeof(dev_result->ident_data.revision),
571                                            sizeof(revision));
572                                     sprintf(tmpstr, "<%s %s>", product,
573                                         revision);
574                                 } else if (dev_result->protocol == PROTO_SEMB) {
575                                         struct sep_identify_data *sid;
576
577                                         sid = (struct sep_identify_data *)
578                                             &dev_result->ident_data;
579                                         cam_strvis(vendor, sid->vendor_id,
580                                             sizeof(sid->vendor_id),
581                                             sizeof(vendor));
582                                         cam_strvis(product, sid->product_id,
583                                             sizeof(sid->product_id),
584                                             sizeof(product));
585                                         cam_strvis(revision, sid->product_rev,
586                                             sizeof(sid->product_rev),
587                                             sizeof(revision));
588                                         cam_strvis(fw, sid->firmware_rev,
589                                             sizeof(sid->firmware_rev),
590                                             sizeof(fw));
591                                         sprintf(tmpstr, "<%s %s %s %s>",
592                                             vendor, product, revision, fw);
593                                 } else {
594                                     sprintf(tmpstr, "<>");
595                                 }
596                                 if (need_close) {
597                                         fprintf(stdout, ")\n");
598                                         need_close = 0;
599                                 }
600
601                                 fprintf(stdout, "%-33s  at scbus%d "
602                                         "target %d lun %jx (",
603                                         tmpstr,
604                                         dev_result->path_id,
605                                         dev_result->target_id,
606                                         (uintmax_t)dev_result->target_lun);
607
608                                 need_close = 1;
609
610                                 break;
611                         }
612                         case DEV_MATCH_PERIPH: {
613                                 struct periph_match_result *periph_result;
614
615                                 periph_result =
616                                       &ccb.cdm.matches[i].result.periph_result;
617
618                                 if (busonly || skip_device != 0)
619                                         break;
620
621                                 if (need_close > 1)
622                                         fprintf(stdout, ",");
623
624                                 fprintf(stdout, "%s%d",
625                                         periph_result->periph_name,
626                                         periph_result->unit_number);
627
628                                 need_close++;
629                                 break;
630                         }
631                         default:
632                                 fprintf(stdout, "unknown match type\n");
633                                 break;
634                         }
635                 }
636
637         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
638                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
639
640         if (need_close)
641                 fprintf(stdout, ")\n");
642
643         close(fd);
644
645         return(error);
646 }
647
648 #ifndef MINIMALISTIC
649 static int
650 testunitready(struct cam_device *device, int retry_count, int timeout,
651               int quiet)
652 {
653         int error = 0;
654         union ccb *ccb;
655
656         ccb = cam_getccb(device);
657
658         scsi_test_unit_ready(&ccb->csio,
659                              /* retries */ retry_count,
660                              /* cbfcnp */ NULL,
661                              /* tag_action */ MSG_SIMPLE_Q_TAG,
662                              /* sense_len */ SSD_FULL_SIZE,
663                              /* timeout */ timeout ? timeout : 5000);
664
665         /* Disable freezing the device queue */
666         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
667
668         if (arglist & CAM_ARG_ERR_RECOVER)
669                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
670
671         if (cam_send_ccb(device, ccb) < 0) {
672                 if (quiet == 0)
673                         perror("error sending test unit ready");
674
675                 if (arglist & CAM_ARG_VERBOSE) {
676                         cam_error_print(device, ccb, CAM_ESF_ALL,
677                                         CAM_EPF_ALL, stderr);
678                 }
679
680                 cam_freeccb(ccb);
681                 return(1);
682         }
683
684         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
685                 if (quiet == 0)
686                         fprintf(stdout, "Unit is ready\n");
687         } else {
688                 if (quiet == 0)
689                         fprintf(stdout, "Unit is not ready\n");
690                 error = 1;
691
692                 if (arglist & CAM_ARG_VERBOSE) {
693                         cam_error_print(device, ccb, CAM_ESF_ALL,
694                                         CAM_EPF_ALL, stderr);
695                 }
696         }
697
698         cam_freeccb(ccb);
699
700         return(error);
701 }
702
703 static int
704 scsistart(struct cam_device *device, int startstop, int loadeject,
705           int retry_count, int timeout)
706 {
707         union ccb *ccb;
708         int error = 0;
709
710         ccb = cam_getccb(device);
711
712         /*
713          * If we're stopping, send an ordered tag so the drive in question
714          * will finish any previously queued writes before stopping.  If
715          * the device isn't capable of tagged queueing, or if tagged
716          * queueing is turned off, the tag action is a no-op.
717          */
718         scsi_start_stop(&ccb->csio,
719                         /* retries */ retry_count,
720                         /* cbfcnp */ NULL,
721                         /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
722                                                      MSG_ORDERED_Q_TAG,
723                         /* start/stop */ startstop,
724                         /* load_eject */ loadeject,
725                         /* immediate */ 0,
726                         /* sense_len */ SSD_FULL_SIZE,
727                         /* timeout */ timeout ? timeout : 120000);
728
729         /* Disable freezing the device queue */
730         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
731
732         if (arglist & CAM_ARG_ERR_RECOVER)
733                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
734
735         if (cam_send_ccb(device, ccb) < 0) {
736                 perror("error sending start unit");
737
738                 if (arglist & CAM_ARG_VERBOSE) {
739                         cam_error_print(device, ccb, CAM_ESF_ALL,
740                                         CAM_EPF_ALL, stderr);
741                 }
742
743                 cam_freeccb(ccb);
744                 return(1);
745         }
746
747         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
748                 if (startstop) {
749                         fprintf(stdout, "Unit started successfully");
750                         if (loadeject)
751                                 fprintf(stdout,", Media loaded\n");
752                         else
753                                 fprintf(stdout,"\n");
754                 } else {
755                         fprintf(stdout, "Unit stopped successfully");
756                         if (loadeject)
757                                 fprintf(stdout, ", Media ejected\n");
758                         else
759                                 fprintf(stdout, "\n");
760                 }
761         else {
762                 error = 1;
763                 if (startstop)
764                         fprintf(stdout,
765                                 "Error received from start unit command\n");
766                 else
767                         fprintf(stdout,
768                                 "Error received from stop unit command\n");
769
770                 if (arglist & CAM_ARG_VERBOSE) {
771                         cam_error_print(device, ccb, CAM_ESF_ALL,
772                                         CAM_EPF_ALL, stderr);
773                 }
774         }
775
776         cam_freeccb(ccb);
777
778         return(error);
779 }
780
781 int
782 scsidoinquiry(struct cam_device *device, int argc, char **argv,
783               char *combinedopt, int retry_count, int timeout)
784 {
785         int c;
786         int error = 0;
787
788         while ((c = getopt(argc, argv, combinedopt)) != -1) {
789                 switch(c) {
790                 case 'D':
791                         arglist |= CAM_ARG_GET_STDINQ;
792                         break;
793                 case 'R':
794                         arglist |= CAM_ARG_GET_XFERRATE;
795                         break;
796                 case 'S':
797                         arglist |= CAM_ARG_GET_SERIAL;
798                         break;
799                 default:
800                         break;
801                 }
802         }
803
804         /*
805          * If the user didn't specify any inquiry options, he wants all of
806          * them.
807          */
808         if ((arglist & CAM_ARG_INQ_MASK) == 0)
809                 arglist |= CAM_ARG_INQ_MASK;
810
811         if (arglist & CAM_ARG_GET_STDINQ)
812                 error = scsiinquiry(device, retry_count, timeout);
813
814         if (error != 0)
815                 return(error);
816
817         if (arglist & CAM_ARG_GET_SERIAL)
818                 scsiserial(device, retry_count, timeout);
819
820         if (arglist & CAM_ARG_GET_XFERRATE)
821                 error = camxferrate(device);
822
823         return(error);
824 }
825
826 static int
827 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
828 {
829         union ccb *ccb;
830         struct scsi_inquiry_data *inq_buf;
831         int error = 0;
832
833         ccb = cam_getccb(device);
834
835         if (ccb == NULL) {
836                 warnx("couldn't allocate CCB");
837                 return(1);
838         }
839
840         /* cam_getccb cleans up the header, caller has to zero the payload */
841         bzero(&(&ccb->ccb_h)[1],
842               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
843
844         inq_buf = (struct scsi_inquiry_data *)malloc(
845                 sizeof(struct scsi_inquiry_data));
846
847         if (inq_buf == NULL) {
848                 cam_freeccb(ccb);
849                 warnx("can't malloc memory for inquiry\n");
850                 return(1);
851         }
852         bzero(inq_buf, sizeof(*inq_buf));
853
854         /*
855          * Note that although the size of the inquiry buffer is the full
856          * 256 bytes specified in the SCSI spec, we only tell the device
857          * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
858          * two reasons for this:
859          *
860          *  - The SCSI spec says that when a length field is only 1 byte,
861          *    a value of 0 will be interpreted as 256.  Therefore
862          *    scsi_inquiry() will convert an inq_len (which is passed in as
863          *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
864          *    to 0.  Evidently, very few devices meet the spec in that
865          *    regard.  Some devices, like many Seagate disks, take the 0 as
866          *    0, and don't return any data.  One Pioneer DVD-R drive
867          *    returns more data than the command asked for.
868          *
869          *    So, since there are numerous devices that just don't work
870          *    right with the full inquiry size, we don't send the full size.
871          *
872          *  - The second reason not to use the full inquiry data length is
873          *    that we don't need it here.  The only reason we issue a
874          *    standard inquiry is to get the vendor name, device name,
875          *    and revision so scsi_print_inquiry() can print them.
876          *
877          * If, at some point in the future, more inquiry data is needed for
878          * some reason, this code should use a procedure similar to the
879          * probe code.  i.e., issue a short inquiry, and determine from
880          * the additional length passed back from the device how much
881          * inquiry data the device supports.  Once the amount the device
882          * supports is determined, issue an inquiry for that amount and no
883          * more.
884          *
885          * KDM, 2/18/2000
886          */
887         scsi_inquiry(&ccb->csio,
888                      /* retries */ retry_count,
889                      /* cbfcnp */ NULL,
890                      /* tag_action */ MSG_SIMPLE_Q_TAG,
891                      /* inq_buf */ (u_int8_t *)inq_buf,
892                      /* inq_len */ SHORT_INQUIRY_LENGTH,
893                      /* evpd */ 0,
894                      /* page_code */ 0,
895                      /* sense_len */ SSD_FULL_SIZE,
896                      /* timeout */ timeout ? timeout : 5000);
897
898         /* Disable freezing the device queue */
899         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
900
901         if (arglist & CAM_ARG_ERR_RECOVER)
902                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
903
904         if (cam_send_ccb(device, ccb) < 0) {
905                 perror("error sending SCSI inquiry");
906
907                 if (arglist & CAM_ARG_VERBOSE) {
908                         cam_error_print(device, ccb, CAM_ESF_ALL,
909                                         CAM_EPF_ALL, stderr);
910                 }
911
912                 cam_freeccb(ccb);
913                 return(1);
914         }
915
916         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
917                 error = 1;
918
919                 if (arglist & CAM_ARG_VERBOSE) {
920                         cam_error_print(device, ccb, CAM_ESF_ALL,
921                                         CAM_EPF_ALL, stderr);
922                 }
923         }
924
925         cam_freeccb(ccb);
926
927         if (error != 0) {
928                 free(inq_buf);
929                 return(error);
930         }
931
932         fprintf(stdout, "%s%d: ", device->device_name,
933                 device->dev_unit_num);
934         scsi_print_inquiry(inq_buf);
935
936         free(inq_buf);
937
938         return(0);
939 }
940
941 static int
942 scsiserial(struct cam_device *device, int retry_count, int timeout)
943 {
944         union ccb *ccb;
945         struct scsi_vpd_unit_serial_number *serial_buf;
946         char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
947         int error = 0;
948
949         ccb = cam_getccb(device);
950
951         if (ccb == NULL) {
952                 warnx("couldn't allocate CCB");
953                 return(1);
954         }
955
956         /* cam_getccb cleans up the header, caller has to zero the payload */
957         bzero(&(&ccb->ccb_h)[1],
958               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
959
960         serial_buf = (struct scsi_vpd_unit_serial_number *)
961                 malloc(sizeof(*serial_buf));
962
963         if (serial_buf == NULL) {
964                 cam_freeccb(ccb);
965                 warnx("can't malloc memory for serial number");
966                 return(1);
967         }
968
969         scsi_inquiry(&ccb->csio,
970                      /*retries*/ retry_count,
971                      /*cbfcnp*/ NULL,
972                      /* tag_action */ MSG_SIMPLE_Q_TAG,
973                      /* inq_buf */ (u_int8_t *)serial_buf,
974                      /* inq_len */ sizeof(*serial_buf),
975                      /* evpd */ 1,
976                      /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
977                      /* sense_len */ SSD_FULL_SIZE,
978                      /* timeout */ timeout ? timeout : 5000);
979
980         /* Disable freezing the device queue */
981         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
982
983         if (arglist & CAM_ARG_ERR_RECOVER)
984                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
985
986         if (cam_send_ccb(device, ccb) < 0) {
987                 warn("error getting serial number");
988
989                 if (arglist & CAM_ARG_VERBOSE) {
990                         cam_error_print(device, ccb, CAM_ESF_ALL,
991                                         CAM_EPF_ALL, stderr);
992                 }
993
994                 cam_freeccb(ccb);
995                 free(serial_buf);
996                 return(1);
997         }
998
999         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1000                 error = 1;
1001
1002                 if (arglist & CAM_ARG_VERBOSE) {
1003                         cam_error_print(device, ccb, CAM_ESF_ALL,
1004                                         CAM_EPF_ALL, stderr);
1005                 }
1006         }
1007
1008         cam_freeccb(ccb);
1009
1010         if (error != 0) {
1011                 free(serial_buf);
1012                 return(error);
1013         }
1014
1015         bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
1016         serial_num[serial_buf->length] = '\0';
1017
1018         if ((arglist & CAM_ARG_GET_STDINQ)
1019          || (arglist & CAM_ARG_GET_XFERRATE))
1020                 fprintf(stdout, "%s%d: Serial Number ",
1021                         device->device_name, device->dev_unit_num);
1022
1023         fprintf(stdout, "%.60s\n", serial_num);
1024
1025         free(serial_buf);
1026
1027         return(0);
1028 }
1029
1030 int
1031 camxferrate(struct cam_device *device)
1032 {
1033         struct ccb_pathinq cpi;
1034         u_int32_t freq = 0;
1035         u_int32_t speed = 0;
1036         union ccb *ccb;
1037         u_int mb;
1038         int retval = 0;
1039
1040         if ((retval = get_cpi(device, &cpi)) != 0)
1041                 return (1);
1042
1043         ccb = cam_getccb(device);
1044
1045         if (ccb == NULL) {
1046                 warnx("couldn't allocate CCB");
1047                 return(1);
1048         }
1049
1050         bzero(&(&ccb->ccb_h)[1],
1051               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
1052
1053         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1054         ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
1055
1056         if (((retval = cam_send_ccb(device, ccb)) < 0)
1057          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1058                 const char error_string[] = "error getting transfer settings";
1059
1060                 if (retval < 0)
1061                         warn(error_string);
1062                 else
1063                         warnx(error_string);
1064
1065                 if (arglist & CAM_ARG_VERBOSE)
1066                         cam_error_print(device, ccb, CAM_ESF_ALL,
1067                                         CAM_EPF_ALL, stderr);
1068
1069                 retval = 1;
1070
1071                 goto xferrate_bailout;
1072
1073         }
1074
1075         speed = cpi.base_transfer_speed;
1076         freq = 0;
1077         if (ccb->cts.transport == XPORT_SPI) {
1078                 struct ccb_trans_settings_spi *spi =
1079                     &ccb->cts.xport_specific.spi;
1080
1081                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1082                         freq = scsi_calc_syncsrate(spi->sync_period);
1083                         speed = freq;
1084                 }
1085                 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1086                         speed *= (0x01 << spi->bus_width);
1087                 }
1088         } else if (ccb->cts.transport == XPORT_FC) {
1089                 struct ccb_trans_settings_fc *fc =
1090                     &ccb->cts.xport_specific.fc;
1091
1092                 if (fc->valid & CTS_FC_VALID_SPEED)
1093                         speed = fc->bitrate;
1094         } else if (ccb->cts.transport == XPORT_SAS) {
1095                 struct ccb_trans_settings_sas *sas =
1096                     &ccb->cts.xport_specific.sas;
1097
1098                 if (sas->valid & CTS_SAS_VALID_SPEED)
1099                         speed = sas->bitrate;
1100         } else if (ccb->cts.transport == XPORT_ATA) {
1101                 struct ccb_trans_settings_pata *pata =
1102                     &ccb->cts.xport_specific.ata;
1103
1104                 if (pata->valid & CTS_ATA_VALID_MODE)
1105                         speed = ata_mode2speed(pata->mode);
1106         } else if (ccb->cts.transport == XPORT_SATA) {
1107                 struct  ccb_trans_settings_sata *sata =
1108                     &ccb->cts.xport_specific.sata;
1109
1110                 if (sata->valid & CTS_SATA_VALID_REVISION)
1111                         speed = ata_revision2speed(sata->revision);
1112         }
1113
1114         mb = speed / 1000;
1115         if (mb > 0) {
1116                 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1117                         device->device_name, device->dev_unit_num,
1118                         mb, speed % 1000);
1119         } else {
1120                 fprintf(stdout, "%s%d: %dKB/s transfers",
1121                         device->device_name, device->dev_unit_num,
1122                         speed);
1123         }
1124
1125         if (ccb->cts.transport == XPORT_SPI) {
1126                 struct ccb_trans_settings_spi *spi =
1127                     &ccb->cts.xport_specific.spi;
1128
1129                 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1130                  && (spi->sync_offset != 0))
1131                         fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1132                                 freq % 1000, spi->sync_offset);
1133
1134                 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1135                  && (spi->bus_width > 0)) {
1136                         if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1137                          && (spi->sync_offset != 0)) {
1138                                 fprintf(stdout, ", ");
1139                         } else {
1140                                 fprintf(stdout, " (");
1141                         }
1142                         fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1143                 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1144                  && (spi->sync_offset != 0)) {
1145                         fprintf(stdout, ")");
1146                 }
1147         } else if (ccb->cts.transport == XPORT_ATA) {
1148                 struct ccb_trans_settings_pata *pata =
1149                     &ccb->cts.xport_specific.ata;
1150
1151                 printf(" (");
1152                 if (pata->valid & CTS_ATA_VALID_MODE)
1153                         printf("%s, ", ata_mode2string(pata->mode));
1154                 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1155                         printf("ATAPI %dbytes, ", pata->atapi);
1156                 if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1157                         printf("PIO %dbytes", pata->bytecount);
1158                 printf(")");
1159         } else if (ccb->cts.transport == XPORT_SATA) {
1160                 struct ccb_trans_settings_sata *sata =
1161                     &ccb->cts.xport_specific.sata;
1162
1163                 printf(" (");
1164                 if (sata->valid & CTS_SATA_VALID_REVISION)
1165                         printf("SATA %d.x, ", sata->revision);
1166                 else
1167                         printf("SATA, ");
1168                 if (sata->valid & CTS_SATA_VALID_MODE)
1169                         printf("%s, ", ata_mode2string(sata->mode));
1170                 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1171                         printf("ATAPI %dbytes, ", sata->atapi);
1172                 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1173                         printf("PIO %dbytes", sata->bytecount);
1174                 printf(")");
1175         }
1176
1177         if (ccb->cts.protocol == PROTO_SCSI) {
1178                 struct ccb_trans_settings_scsi *scsi =
1179                     &ccb->cts.proto_specific.scsi;
1180                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1181                         if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1182                                 fprintf(stdout, ", Command Queueing Enabled");
1183                         }
1184                 }
1185         }
1186
1187         fprintf(stdout, "\n");
1188
1189 xferrate_bailout:
1190
1191         cam_freeccb(ccb);
1192
1193         return(retval);
1194 }
1195
1196 static void
1197 atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
1198 {
1199         u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1200                                 ((u_int32_t)parm->lba_size_2 << 16);
1201
1202         u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1203                                 ((u_int64_t)parm->lba_size48_2 << 16) |
1204                                 ((u_int64_t)parm->lba_size48_3 << 32) |
1205                                 ((u_int64_t)parm->lba_size48_4 << 48);
1206
1207         if (header) {
1208                 printf("\nFeature                      "
1209                        "Support  Enabled   Value\n");
1210         }
1211
1212         printf("Host Protected Area (HPA)      ");
1213         if (parm->support.command1 & ATA_SUPPORT_PROTECTED) {
1214                 u_int64_t lba = lbasize48 ? lbasize48 : lbasize;
1215                 printf("yes      %s     %ju/%ju\n", (hpasize > lba) ? "yes" : "no ",
1216                         lba, hpasize);
1217
1218                 printf("HPA - Security                 ");
1219                 if (parm->support.command1 & ATA_SUPPORT_MAXSECURITY)
1220                         printf("yes\n");
1221                 else
1222                         printf("no\n");
1223         } else {
1224                 printf("no\n");
1225         }
1226 }
1227
1228 static int
1229 atasata(struct ata_params *parm)
1230 {
1231
1232
1233         if (parm->satacapabilities != 0xffff &&
1234             parm->satacapabilities != 0x0000)
1235                 return 1;
1236
1237         return 0;
1238 }
1239
1240 static void
1241 atacapprint(struct ata_params *parm)
1242 {
1243         u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1244                                 ((u_int32_t)parm->lba_size_2 << 16);
1245
1246         u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1247                                 ((u_int64_t)parm->lba_size48_2 << 16) |
1248                                 ((u_int64_t)parm->lba_size48_3 << 32) |
1249                                 ((u_int64_t)parm->lba_size48_4 << 48);
1250
1251         printf("\n");
1252         printf("protocol              ");
1253         printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1254         if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1255                 if (parm->satacapabilities & ATA_SATA_GEN3)
1256                         printf(" SATA 3.x\n");
1257                 else if (parm->satacapabilities & ATA_SATA_GEN2)
1258                         printf(" SATA 2.x\n");
1259                 else if (parm->satacapabilities & ATA_SATA_GEN1)
1260                         printf(" SATA 1.x\n");
1261                 else
1262                         printf(" SATA\n");
1263         }
1264         else
1265                 printf("\n");
1266         printf("device model          %.40s\n", parm->model);
1267         printf("firmware revision     %.8s\n", parm->revision);
1268         printf("serial number         %.20s\n", parm->serial);
1269         if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1270                 printf("WWN                   %04x%04x%04x%04x\n",
1271                     parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1272         }
1273         if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1274                 printf("media serial number   %.30s\n",
1275                     parm->media_serial);
1276         }
1277
1278         printf("cylinders             %d\n", parm->cylinders);
1279         printf("heads                 %d\n", parm->heads);
1280         printf("sectors/track         %d\n", parm->sectors);
1281         printf("sector size           logical %u, physical %lu, offset %lu\n",
1282             ata_logical_sector_size(parm),
1283             (unsigned long)ata_physical_sector_size(parm),
1284             (unsigned long)ata_logical_sector_offset(parm));
1285
1286         if (parm->config == ATA_PROTO_CFA ||
1287             (parm->support.command2 & ATA_SUPPORT_CFA))
1288                 printf("CFA supported\n");
1289
1290         printf("LBA%ssupported         ",
1291                 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1292         if (lbasize)
1293                 printf("%d sectors\n", lbasize);
1294         else
1295                 printf("\n");
1296
1297         printf("LBA48%ssupported       ",
1298                 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1299         if (lbasize48)
1300                 printf("%ju sectors\n", (uintmax_t)lbasize48);
1301         else
1302                 printf("\n");
1303
1304         printf("PIO supported         PIO");
1305         switch (ata_max_pmode(parm)) {
1306         case ATA_PIO4:
1307                 printf("4");
1308                 break;
1309         case ATA_PIO3:
1310                 printf("3");
1311                 break;
1312         case ATA_PIO2:
1313                 printf("2");
1314                 break;
1315         case ATA_PIO1:
1316                 printf("1");
1317                 break;
1318         default:
1319                 printf("0");
1320         }
1321         if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1322                 printf(" w/o IORDY");
1323         printf("\n");
1324
1325         printf("DMA%ssupported         ",
1326                 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1327         if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1328                 if (parm->mwdmamodes & 0xff) {
1329                         printf("WDMA");
1330                         if (parm->mwdmamodes & 0x04)
1331                                 printf("2");
1332                         else if (parm->mwdmamodes & 0x02)
1333                                 printf("1");
1334                         else if (parm->mwdmamodes & 0x01)
1335                                 printf("0");
1336                         printf(" ");
1337                 }
1338                 if ((parm->atavalid & ATA_FLAG_88) &&
1339                     (parm->udmamodes & 0xff)) {
1340                         printf("UDMA");
1341                         if (parm->udmamodes & 0x40)
1342                                 printf("6");
1343                         else if (parm->udmamodes & 0x20)
1344                                 printf("5");
1345                         else if (parm->udmamodes & 0x10)
1346                                 printf("4");
1347                         else if (parm->udmamodes & 0x08)
1348                                 printf("3");
1349                         else if (parm->udmamodes & 0x04)
1350                                 printf("2");
1351                         else if (parm->udmamodes & 0x02)
1352                                 printf("1");
1353                         else if (parm->udmamodes & 0x01)
1354                                 printf("0");
1355                         printf(" ");
1356                 }
1357         }
1358         printf("\n");
1359
1360         if (parm->media_rotation_rate == 1) {
1361                 printf("media RPM             non-rotating\n");
1362         } else if (parm->media_rotation_rate >= 0x0401 &&
1363             parm->media_rotation_rate <= 0xFFFE) {
1364                 printf("media RPM             %d\n",
1365                         parm->media_rotation_rate);
1366         }
1367
1368         printf("\nFeature                      "
1369                 "Support  Enabled   Value           Vendor\n");
1370         printf("read ahead                     %s       %s\n",
1371                 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1372                 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1373         printf("write cache                    %s       %s\n",
1374                 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1375                 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1376         printf("flush cache                    %s       %s\n",
1377                 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1378                 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1379         printf("overlap                        %s\n",
1380                 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1381         printf("Tagged Command Queuing (TCQ)   %s       %s",
1382                 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1383                 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1384                 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1385                         printf("        %d tags\n",
1386                             ATA_QUEUE_LEN(parm->queue) + 1);
1387                 } else
1388                         printf("\n");
1389         printf("Native Command Queuing (NCQ)   ");
1390         if (parm->satacapabilities != 0xffff &&
1391             (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1392                 printf("yes             %d tags\n",
1393                     ATA_QUEUE_LEN(parm->queue) + 1);
1394         } else
1395                 printf("no\n");
1396
1397         printf("NCQ Queue Management           %s\n", atasata(parm) &&
1398                 parm->satacapabilities2 & ATA_SUPPORT_NCQ_QMANAGEMENT ?
1399                 "yes" : "no");
1400         printf("NCQ Streaming                  %s\n", atasata(parm) &&
1401                 parm->satacapabilities2 & ATA_SUPPORT_NCQ_STREAM ?
1402                 "yes" : "no");
1403         printf("Receive & Send FPDMA Queued    %s\n", atasata(parm) &&
1404                 parm->satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED ?
1405                 "yes" : "no");
1406
1407         printf("SMART                          %s       %s\n",
1408                 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1409                 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1410         printf("microcode download             %s       %s\n",
1411                 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1412                 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1413         printf("security                       %s       %s\n",
1414                 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1415                 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1416         printf("power management               %s       %s\n",
1417                 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1418                 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1419         printf("advanced power management      %s       %s",
1420                 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1421                 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1422                 if (parm->support.command2 & ATA_SUPPORT_APM) {
1423                         printf("        %d/0x%02X\n",
1424                             parm->apm_value & 0xff, parm->apm_value & 0xff);
1425                 } else
1426                         printf("\n");
1427         printf("automatic acoustic management  %s       %s",
1428                 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1429                 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1430                 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1431                         printf("        %d/0x%02X       %d/0x%02X\n",
1432                             ATA_ACOUSTIC_CURRENT(parm->acoustic),
1433                             ATA_ACOUSTIC_CURRENT(parm->acoustic),
1434                             ATA_ACOUSTIC_VENDOR(parm->acoustic),
1435                             ATA_ACOUSTIC_VENDOR(parm->acoustic));
1436                 } else
1437                         printf("\n");
1438         printf("media status notification      %s       %s\n",
1439                 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1440                 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1441         printf("power-up in Standby            %s       %s\n",
1442                 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1443                 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1444         printf("write-read-verify              %s       %s",
1445                 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1446                 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1447                 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1448                         printf("        %d/0x%x\n",
1449                             parm->wrv_mode, parm->wrv_mode);
1450                 } else
1451                         printf("\n");
1452         printf("unload                         %s       %s\n",
1453                 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1454                 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1455         printf("general purpose logging        %s       %s\n",
1456                 parm->support.extension & ATA_SUPPORT_GENLOG ? "yes" : "no",
1457                 parm->enabled.extension & ATA_SUPPORT_GENLOG ? "yes" : "no");
1458         printf("free-fall                      %s       %s\n",
1459                 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1460                 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1461         printf("Data Set Management (DSM/TRIM) ");
1462         if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) {
1463                 printf("yes\n");
1464                 printf("DSM - max 512byte blocks       ");
1465                 if (parm->max_dsm_blocks == 0x00)
1466                         printf("yes              not specified\n");
1467                 else
1468                         printf("yes              %d\n",
1469                                 parm->max_dsm_blocks);
1470
1471                 printf("DSM - deterministic read       ");
1472                 if (parm->support3 & ATA_SUPPORT_DRAT) {
1473                         if (parm->support3 & ATA_SUPPORT_RZAT)
1474                                 printf("yes              zeroed\n");
1475                         else
1476                                 printf("yes              any value\n");
1477                 } else {
1478                         printf("no\n");
1479                 }
1480         } else {
1481                 printf("no\n");
1482         }
1483 }
1484
1485 static int
1486 scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
1487 {
1488         struct ata_pass_16 *ata_pass_16;
1489         struct ata_cmd ata_cmd;
1490
1491         ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
1492         ata_cmd.command = ata_pass_16->command;
1493         ata_cmd.control = ata_pass_16->control;
1494         ata_cmd.features = ata_pass_16->features;
1495
1496         if (arglist & CAM_ARG_VERBOSE) {
1497                 warnx("sending ATA %s via pass_16 with timeout of %u msecs",
1498                       ata_op_string(&ata_cmd),
1499                       ccb->csio.ccb_h.timeout);
1500         }
1501
1502         /* Disable freezing the device queue */
1503         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1504
1505         if (arglist & CAM_ARG_ERR_RECOVER)
1506                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1507
1508         if (cam_send_ccb(device, ccb) < 0) {
1509                 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1510                         warn("error sending ATA %s via pass_16",
1511                              ata_op_string(&ata_cmd));
1512                 }
1513
1514                 if (arglist & CAM_ARG_VERBOSE) {
1515                         cam_error_print(device, ccb, CAM_ESF_ALL,
1516                                         CAM_EPF_ALL, stderr);
1517                 }
1518
1519                 return (1);
1520         }
1521
1522         if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
1523             (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1524                 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1525                         warnx("ATA %s via pass_16 failed",
1526                               ata_op_string(&ata_cmd));
1527                 }
1528                 if (arglist & CAM_ARG_VERBOSE) {
1529                         cam_error_print(device, ccb, CAM_ESF_ALL,
1530                                         CAM_EPF_ALL, stderr);
1531                 }
1532
1533                 return (1);
1534         }
1535
1536         return (0);
1537 }
1538
1539
1540 static int
1541 ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
1542 {
1543         if (arglist & CAM_ARG_VERBOSE) {
1544                 warnx("sending ATA %s with timeout of %u msecs",
1545                       ata_op_string(&(ccb->ataio.cmd)),
1546                       ccb->ataio.ccb_h.timeout);
1547         }
1548
1549         /* Disable freezing the device queue */
1550         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1551
1552         if (arglist & CAM_ARG_ERR_RECOVER)
1553                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1554
1555         if (cam_send_ccb(device, ccb) < 0) {
1556                 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1557                         warn("error sending ATA %s",
1558                              ata_op_string(&(ccb->ataio.cmd)));
1559                 }
1560
1561                 if (arglist & CAM_ARG_VERBOSE) {
1562                         cam_error_print(device, ccb, CAM_ESF_ALL,
1563                                         CAM_EPF_ALL, stderr);
1564                 }
1565
1566                 return (1);
1567         }
1568
1569         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1570                 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1571                         warnx("ATA %s failed: %d",
1572                               ata_op_string(&(ccb->ataio.cmd)), quiet);
1573                 }
1574
1575                 if (arglist & CAM_ARG_VERBOSE) {
1576                         cam_error_print(device, ccb, CAM_ESF_ALL,
1577                                         CAM_EPF_ALL, stderr);
1578                 }
1579
1580                 return (1);
1581         }
1582
1583         return (0);
1584 }
1585
1586 static int
1587 ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
1588                u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1589                u_int8_t tag_action, u_int8_t command, u_int8_t features,
1590                u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1591                u_int16_t dxfer_len, int timeout, int quiet)
1592 {
1593         if (data_ptr != NULL) {
1594                 ata_flags |= AP_FLAG_BYT_BLOK_BYTES |
1595                             AP_FLAG_TLEN_SECT_CNT;
1596                 if (flags & CAM_DIR_OUT)
1597                         ata_flags |= AP_FLAG_TDIR_TO_DEV;
1598                 else
1599                         ata_flags |= AP_FLAG_TDIR_FROM_DEV;
1600         } else {
1601                 ata_flags |= AP_FLAG_TLEN_NO_DATA;
1602         }
1603
1604         bzero(&(&ccb->ccb_h)[1],
1605               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1606
1607         scsi_ata_pass_16(&ccb->csio,
1608                          retries,
1609                          NULL,
1610                          flags,
1611                          tag_action,
1612                          protocol,
1613                          ata_flags,
1614                          features,
1615                          sector_count,
1616                          lba,
1617                          command,
1618                          /*control*/0,
1619                          data_ptr,
1620                          dxfer_len,
1621                          /*sense_len*/SSD_FULL_SIZE,
1622                          timeout);
1623
1624         return scsi_cam_pass_16_send(device, ccb, quiet);
1625 }
1626
1627 static int
1628 ata_try_pass_16(struct cam_device *device)
1629 {
1630         struct ccb_pathinq cpi;
1631
1632         if (get_cpi(device, &cpi) != 0) {
1633                 warnx("couldn't get CPI");
1634                 return (-1);
1635         }
1636
1637         if (cpi.protocol == PROTO_SCSI) {
1638                 /* possibly compatible with pass_16 */
1639                 return (1);
1640         }
1641
1642         /* likely not compatible with pass_16 */
1643         return (0);
1644 }
1645
1646 static int
1647 ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries,
1648                  u_int32_t flags, u_int8_t protocol, u_int8_t tag_action,
1649                  u_int8_t command, u_int8_t features, u_int32_t lba,
1650                  u_int8_t sector_count, u_int8_t *data_ptr, u_int16_t dxfer_len,
1651                  int timeout, int quiet)
1652 {
1653
1654
1655         switch (ata_try_pass_16(device)) {
1656         case -1:
1657                 return (1);
1658         case 1:
1659                 /* Try using SCSI Passthrough */
1660                 return ata_do_pass_16(device, ccb, retries, flags, protocol,
1661                                       0, tag_action, command, features, lba,
1662                                       sector_count, data_ptr, dxfer_len,
1663                                       timeout, quiet);
1664         }
1665
1666         bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1667               sizeof(struct ccb_hdr));
1668         cam_fill_ataio(&ccb->ataio,
1669                        retries,
1670                        NULL,
1671                        flags,
1672                        tag_action,
1673                        data_ptr,
1674                        dxfer_len,
1675                        timeout);
1676
1677         ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1678         return ata_cam_send(device, ccb, quiet);
1679 }
1680
1681 static int
1682 ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
1683            u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1684            u_int8_t tag_action, u_int8_t command, u_int8_t features,
1685            u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1686            u_int16_t dxfer_len, int timeout, int force48bit)
1687 {
1688         int retval;
1689
1690         retval = ata_try_pass_16(device);
1691         if (retval == -1)
1692                 return (1);
1693
1694         if (retval == 1) {
1695                 int error;
1696
1697                 /* Try using SCSI Passthrough */
1698                 error = ata_do_pass_16(device, ccb, retries, flags, protocol,
1699                                       ata_flags, tag_action, command, features,
1700                                       lba, sector_count, data_ptr, dxfer_len,
1701                                       timeout, 0);
1702
1703                 if (ata_flags & AP_FLAG_CHK_COND) {
1704                         /* Decode ata_res from sense data */
1705                         struct ata_res_pass16 *res_pass16;
1706                         struct ata_res *res;
1707                         u_int i;
1708                         u_int16_t *ptr;
1709
1710                         /* sense_data is 4 byte aligned */
1711                         ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data;
1712                         for (i = 0; i < sizeof(*res_pass16) / 2; i++)
1713                                 ptr[i] = le16toh(ptr[i]);
1714
1715                         /* sense_data is 4 byte aligned */
1716                         res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
1717                             &ccb->csio.sense_data;
1718                         res = &ccb->ataio.res;
1719                         res->flags = res_pass16->flags;
1720                         res->status = res_pass16->status;
1721                         res->error = res_pass16->error;
1722                         res->lba_low = res_pass16->lba_low;
1723                         res->lba_mid = res_pass16->lba_mid;
1724                         res->lba_high = res_pass16->lba_high;
1725                         res->device = res_pass16->device;
1726                         res->lba_low_exp = res_pass16->lba_low_exp;
1727                         res->lba_mid_exp = res_pass16->lba_mid_exp;
1728                         res->lba_high_exp = res_pass16->lba_high_exp;
1729                         res->sector_count = res_pass16->sector_count;
1730                         res->sector_count_exp = res_pass16->sector_count_exp;
1731                 }
1732
1733                 return (error);
1734         }
1735
1736         bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1737               sizeof(struct ccb_hdr));
1738         cam_fill_ataio(&ccb->ataio,
1739                        retries,
1740                        NULL,
1741                        flags,
1742                        tag_action,
1743                        data_ptr,
1744                        dxfer_len,
1745                        timeout);
1746
1747         if (force48bit || lba > ATA_MAX_28BIT_LBA)
1748                 ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1749         else
1750                 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1751
1752         if (ata_flags & AP_FLAG_CHK_COND)
1753                 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
1754
1755         return ata_cam_send(device, ccb, 0);
1756 }
1757
1758 static void
1759 dump_data(uint16_t *ptr, uint32_t len)
1760 {
1761         u_int i;
1762
1763         for (i = 0; i < len / 2; i++) {
1764                 if ((i % 8) == 0)
1765                         printf(" %3d: ", i);
1766                 printf("%04hx ", ptr[i]);
1767                 if ((i % 8) == 7)
1768                         printf("\n");
1769         }
1770         if ((i % 8) != 7)
1771                 printf("\n");
1772 }
1773
1774 static int
1775 atahpa_proc_resp(struct cam_device *device, union ccb *ccb,
1776                  int is48bit, u_int64_t *hpasize)
1777 {
1778         struct ata_res *res;
1779
1780         res = &ccb->ataio.res;
1781         if (res->status & ATA_STATUS_ERROR) {
1782                 if (arglist & CAM_ARG_VERBOSE) {
1783                         cam_error_print(device, ccb, CAM_ESF_ALL,
1784                                         CAM_EPF_ALL, stderr);
1785                         printf("error = 0x%02x, sector_count = 0x%04x, "
1786                                "device = 0x%02x, status = 0x%02x\n",
1787                                res->error, res->sector_count,
1788                                res->device, res->status);
1789                 }
1790
1791                 if (res->error & ATA_ERROR_ID_NOT_FOUND) {
1792                         warnx("Max address has already been set since "
1793                               "last power-on or hardware reset");
1794                 }
1795
1796                 return (1);
1797         }
1798
1799         if (arglist & CAM_ARG_VERBOSE) {
1800                 fprintf(stdout, "%s%d: Raw native max data:\n",
1801                         device->device_name, device->dev_unit_num);
1802                 /* res is 4 byte aligned */
1803                 dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
1804
1805                 printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
1806                        "status = 0x%02x\n", res->error, res->sector_count,
1807                        res->device, res->status);
1808         }
1809
1810         if (hpasize != NULL) {
1811                 if (is48bit) {
1812                         *hpasize = (((u_int64_t)((res->lba_high_exp << 16) |
1813                             (res->lba_mid_exp << 8) | res->lba_low_exp) << 24) |
1814                             ((res->lba_high << 16) | (res->lba_mid << 8) |
1815                             res->lba_low)) + 1;
1816                 } else {
1817                         *hpasize = (((res->device & 0x0f) << 24) |
1818                             (res->lba_high << 16) | (res->lba_mid << 8) |
1819                             res->lba_low) + 1;
1820                 }
1821         }
1822
1823         return (0);
1824 }
1825
1826 static int
1827 ata_read_native_max(struct cam_device *device, int retry_count,
1828                       u_int32_t timeout, union ccb *ccb,
1829                       struct ata_params *parm, u_int64_t *hpasize)
1830 {
1831         int error;
1832         u_int cmd, is48bit;
1833         u_int8_t protocol;
1834
1835         is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48;
1836         protocol = AP_PROTO_NON_DATA;
1837
1838         if (is48bit) {
1839                 cmd = ATA_READ_NATIVE_MAX_ADDRESS48;
1840                 protocol |= AP_EXTEND;
1841         } else {
1842                 cmd = ATA_READ_NATIVE_MAX_ADDRESS;
1843         }
1844
1845         error = ata_do_cmd(device,
1846                            ccb,
1847                            retry_count,
1848                            /*flags*/CAM_DIR_NONE,
1849                            /*protocol*/protocol,
1850                            /*ata_flags*/AP_FLAG_CHK_COND,
1851                            /*tag_action*/MSG_SIMPLE_Q_TAG,
1852                            /*command*/cmd,
1853                            /*features*/0,
1854                            /*lba*/0,
1855                            /*sector_count*/0,
1856                            /*data_ptr*/NULL,
1857                            /*dxfer_len*/0,
1858                            timeout ? timeout : 1000,
1859                            is48bit);
1860
1861         if (error)
1862                 return (error);
1863
1864         return atahpa_proc_resp(device, ccb, is48bit, hpasize);
1865 }
1866
1867 static int
1868 atahpa_set_max(struct cam_device *device, int retry_count,
1869               u_int32_t timeout, union ccb *ccb,
1870               int is48bit, u_int64_t maxsize, int persist)
1871 {
1872         int error;
1873         u_int cmd;
1874         u_int8_t protocol;
1875
1876         protocol = AP_PROTO_NON_DATA;
1877
1878         if (is48bit) {
1879                 cmd = ATA_SET_MAX_ADDRESS48;
1880                 protocol |= AP_EXTEND;
1881         } else {
1882                 cmd = ATA_SET_MAX_ADDRESS;
1883         }
1884
1885         /* lba's are zero indexed so the max lba is requested max - 1 */
1886         if (maxsize)
1887                 maxsize--;
1888
1889         error = ata_do_cmd(device,
1890                            ccb,
1891                            retry_count,
1892                            /*flags*/CAM_DIR_NONE,
1893                            /*protocol*/protocol,
1894                            /*ata_flags*/AP_FLAG_CHK_COND,
1895                            /*tag_action*/MSG_SIMPLE_Q_TAG,
1896                            /*command*/cmd,
1897                            /*features*/ATA_HPA_FEAT_MAX_ADDR,
1898                            /*lba*/maxsize,
1899                            /*sector_count*/persist,
1900                            /*data_ptr*/NULL,
1901                            /*dxfer_len*/0,
1902                            timeout ? timeout : 1000,
1903                            is48bit);
1904
1905         if (error)
1906                 return (error);
1907
1908         return atahpa_proc_resp(device, ccb, is48bit, NULL);
1909 }
1910
1911 static int
1912 atahpa_password(struct cam_device *device, int retry_count,
1913                 u_int32_t timeout, union ccb *ccb,
1914                 int is48bit, struct ata_set_max_pwd *pwd)
1915 {
1916         int error;
1917         u_int cmd;
1918         u_int8_t protocol;
1919
1920         protocol = AP_PROTO_PIO_OUT;
1921         cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1922
1923         error = ata_do_cmd(device,
1924                            ccb,
1925                            retry_count,
1926                            /*flags*/CAM_DIR_OUT,
1927                            /*protocol*/protocol,
1928                            /*ata_flags*/AP_FLAG_CHK_COND,
1929                            /*tag_action*/MSG_SIMPLE_Q_TAG,
1930                            /*command*/cmd,
1931                            /*features*/ATA_HPA_FEAT_SET_PWD,
1932                            /*lba*/0,
1933                            /*sector_count*/0,
1934                            /*data_ptr*/(u_int8_t*)pwd,
1935                            /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1936                            timeout ? timeout : 1000,
1937                            is48bit);
1938
1939         if (error)
1940                 return (error);
1941
1942         return atahpa_proc_resp(device, ccb, is48bit, NULL);
1943 }
1944
1945 static int
1946 atahpa_lock(struct cam_device *device, int retry_count,
1947             u_int32_t timeout, union ccb *ccb, int is48bit)
1948 {
1949         int error;
1950         u_int cmd;
1951         u_int8_t protocol;
1952
1953         protocol = AP_PROTO_NON_DATA;
1954         cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1955
1956         error = ata_do_cmd(device,
1957                            ccb,
1958                            retry_count,
1959                            /*flags*/CAM_DIR_NONE,
1960                            /*protocol*/protocol,
1961                            /*ata_flags*/AP_FLAG_CHK_COND,
1962                            /*tag_action*/MSG_SIMPLE_Q_TAG,
1963                            /*command*/cmd,
1964                            /*features*/ATA_HPA_FEAT_LOCK,
1965                            /*lba*/0,
1966                            /*sector_count*/0,
1967                            /*data_ptr*/NULL,
1968                            /*dxfer_len*/0,
1969                            timeout ? timeout : 1000,
1970                            is48bit);
1971
1972         if (error)
1973                 return (error);
1974
1975         return atahpa_proc_resp(device, ccb, is48bit, NULL);
1976 }
1977
1978 static int
1979 atahpa_unlock(struct cam_device *device, int retry_count,
1980               u_int32_t timeout, union ccb *ccb,
1981               int is48bit, struct ata_set_max_pwd *pwd)
1982 {
1983         int error;
1984         u_int cmd;
1985         u_int8_t protocol;
1986
1987         protocol = AP_PROTO_PIO_OUT;
1988         cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1989
1990         error = ata_do_cmd(device,
1991                            ccb,
1992                            retry_count,
1993                            /*flags*/CAM_DIR_OUT,
1994                            /*protocol*/protocol,
1995                            /*ata_flags*/AP_FLAG_CHK_COND,
1996                            /*tag_action*/MSG_SIMPLE_Q_TAG,
1997                            /*command*/cmd,
1998                            /*features*/ATA_HPA_FEAT_UNLOCK,
1999                            /*lba*/0,
2000                            /*sector_count*/0,
2001                            /*data_ptr*/(u_int8_t*)pwd,
2002                            /*dxfer_len*/sizeof(struct ata_set_max_pwd),
2003                            timeout ? timeout : 1000,
2004                            is48bit);
2005
2006         if (error)
2007                 return (error);
2008
2009         return atahpa_proc_resp(device, ccb, is48bit, NULL);
2010 }
2011
2012 static int
2013 atahpa_freeze_lock(struct cam_device *device, int retry_count,
2014                    u_int32_t timeout, union ccb *ccb, int is48bit)
2015 {
2016         int error;
2017         u_int cmd;
2018         u_int8_t protocol;
2019
2020         protocol = AP_PROTO_NON_DATA;
2021         cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2022
2023         error = ata_do_cmd(device,
2024                            ccb,
2025                            retry_count,
2026                            /*flags*/CAM_DIR_NONE,
2027                            /*protocol*/protocol,
2028                            /*ata_flags*/AP_FLAG_CHK_COND,
2029                            /*tag_action*/MSG_SIMPLE_Q_TAG,
2030                            /*command*/cmd,
2031                            /*features*/ATA_HPA_FEAT_FREEZE,
2032                            /*lba*/0,
2033                            /*sector_count*/0,
2034                            /*data_ptr*/NULL,
2035                            /*dxfer_len*/0,
2036                            timeout ? timeout : 1000,
2037                            is48bit);
2038
2039         if (error)
2040                 return (error);
2041
2042         return atahpa_proc_resp(device, ccb, is48bit, NULL);
2043 }
2044
2045
2046 int
2047 ata_do_identify(struct cam_device *device, int retry_count, int timeout,
2048                 union ccb *ccb, struct ata_params** ident_bufp)
2049 {
2050         struct ata_params *ident_buf;
2051         struct ccb_pathinq cpi;
2052         struct ccb_getdev cgd;
2053         u_int i, error;
2054         int16_t *ptr;
2055         u_int8_t command, retry_command;
2056
2057         if (get_cpi(device, &cpi) != 0) {
2058                 warnx("couldn't get CPI");
2059                 return (-1);
2060         }
2061
2062         /* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */
2063         if (cpi.protocol == PROTO_ATA) {
2064                 if (get_cgd(device, &cgd) != 0) {
2065                         warnx("couldn't get CGD");
2066                         return (-1);
2067                 }
2068
2069                 command = (cgd.protocol == PROTO_ATA) ?
2070                     ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
2071                 retry_command = 0;
2072         } else {
2073                 /* We don't know which for sure so try both */
2074                 command = ATA_ATA_IDENTIFY;
2075                 retry_command = ATA_ATAPI_IDENTIFY;
2076         }
2077
2078         ptr = (uint16_t *)calloc(1, sizeof(struct ata_params));
2079         if (ptr == NULL) {
2080                 warnx("can't calloc memory for identify\n");
2081                 return (1);
2082         }
2083
2084         error = ata_do_28bit_cmd(device,
2085                                  ccb,
2086                                  /*retries*/retry_count,
2087                                  /*flags*/CAM_DIR_IN,
2088                                  /*protocol*/AP_PROTO_PIO_IN,
2089                                  /*tag_action*/MSG_SIMPLE_Q_TAG,
2090                                  /*command*/command,
2091                                  /*features*/0,
2092                                  /*lba*/0,
2093                                  /*sector_count*/(u_int8_t)sizeof(struct ata_params),
2094                                  /*data_ptr*/(u_int8_t *)ptr,
2095                                  /*dxfer_len*/sizeof(struct ata_params),
2096                                  /*timeout*/timeout ? timeout : 30 * 1000,
2097                                  /*quiet*/1);
2098
2099         if (error != 0) {
2100                 if (retry_command == 0) {
2101                         free(ptr);
2102                         return (1);
2103                 }
2104                 error = ata_do_28bit_cmd(device,
2105                                          ccb,
2106                                          /*retries*/retry_count,
2107                                          /*flags*/CAM_DIR_IN,
2108                                          /*protocol*/AP_PROTO_PIO_IN,
2109                                          /*tag_action*/MSG_SIMPLE_Q_TAG,
2110                                          /*command*/retry_command,
2111                                          /*features*/0,
2112                                          /*lba*/0,
2113                                          /*sector_count*/(u_int8_t)
2114                                              sizeof(struct ata_params),
2115                                          /*data_ptr*/(u_int8_t *)ptr,
2116                                          /*dxfer_len*/sizeof(struct ata_params),
2117                                          /*timeout*/timeout ? timeout : 30 * 1000,
2118                                          /*quiet*/0);
2119
2120                 if (error != 0) {
2121                         free(ptr);
2122                         return (1);
2123                 }
2124         }
2125
2126         error = 1;
2127         for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
2128                 ptr[i] = le16toh(ptr[i]);
2129                 if (ptr[i] != 0)
2130                         error = 0;
2131         }
2132
2133         if (arglist & CAM_ARG_VERBOSE) {
2134                 fprintf(stdout, "%s%d: Raw identify data:\n",
2135                     device->device_name, device->dev_unit_num);
2136                 dump_data(ptr, sizeof(struct ata_params));
2137         }
2138
2139         /* check for invalid (all zero) response */
2140         if (error != 0) {
2141                 warnx("Invalid identify response detected");
2142                 free(ptr);
2143                 return (error);
2144         }
2145
2146         ident_buf = (struct ata_params *)ptr;
2147         if (strncmp(ident_buf->model, "FX", 2) &&
2148             strncmp(ident_buf->model, "NEC", 3) &&
2149             strncmp(ident_buf->model, "Pioneer", 7) &&
2150             strncmp(ident_buf->model, "SHARP", 5)) {
2151                 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
2152                 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
2153                 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
2154                 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2155         }
2156         ata_btrim(ident_buf->model, sizeof(ident_buf->model));
2157         ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
2158         ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
2159         ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
2160         ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
2161         ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
2162         ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2163         ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
2164             sizeof(ident_buf->media_serial));
2165
2166         *ident_bufp = ident_buf;
2167
2168         return (0);
2169 }
2170
2171
2172 static int
2173 ataidentify(struct cam_device *device, int retry_count, int timeout)
2174 {
2175         union ccb *ccb;
2176         struct ata_params *ident_buf;
2177         u_int64_t hpasize;
2178
2179         if ((ccb = cam_getccb(device)) == NULL) {
2180                 warnx("couldn't allocate CCB");
2181                 return (1);
2182         }
2183
2184         if (ata_do_identify(device, retry_count, timeout, ccb, &ident_buf) != 0) {
2185                 cam_freeccb(ccb);
2186                 return (1);
2187         }
2188
2189         if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) {
2190                 if (ata_read_native_max(device, retry_count, timeout, ccb,
2191                                         ident_buf, &hpasize) != 0) {
2192                         cam_freeccb(ccb);
2193                         return (1);
2194                 }
2195         } else {
2196                 hpasize = 0;
2197         }
2198
2199         printf("%s%d: ", device->device_name, device->dev_unit_num);
2200         ata_print_ident(ident_buf);
2201         camxferrate(device);
2202         atacapprint(ident_buf);
2203         atahpa_print(ident_buf, hpasize, 0);
2204
2205         free(ident_buf);
2206         cam_freeccb(ccb);
2207
2208         return (0);
2209 }
2210 #endif /* MINIMALISTIC */
2211
2212
2213 #ifndef MINIMALISTIC
2214 enum {
2215         ATA_SECURITY_ACTION_PRINT,
2216         ATA_SECURITY_ACTION_FREEZE,
2217         ATA_SECURITY_ACTION_UNLOCK,
2218         ATA_SECURITY_ACTION_DISABLE,
2219         ATA_SECURITY_ACTION_ERASE,
2220         ATA_SECURITY_ACTION_ERASE_ENHANCED,
2221         ATA_SECURITY_ACTION_SET_PASSWORD
2222 };
2223
2224 static void
2225 atasecurity_print_time(u_int16_t tw)
2226 {
2227
2228         if (tw == 0)
2229                 printf("unspecified");
2230         else if (tw >= 255)
2231                 printf("> 508 min");
2232         else
2233                 printf("%i min", 2 * tw);
2234 }
2235
2236 static u_int32_t
2237 atasecurity_erase_timeout_msecs(u_int16_t timeout)
2238 {
2239
2240         if (timeout == 0)
2241                 return 2 * 3600 * 1000; /* default: two hours */
2242         else if (timeout > 255)
2243                 return (508 + 60) * 60 * 1000; /* spec says > 508 minutes */
2244
2245         return ((2 * timeout) + 5) * 60 * 1000; /* add a 5min margin */
2246 }
2247
2248
2249 static void
2250 atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
2251 {
2252         struct ata_cmd cmd;
2253
2254         bzero(&cmd, sizeof(cmd));
2255         cmd.command = command;
2256         printf("Issuing %s", ata_op_string(&cmd));
2257
2258         if (pwd != NULL) {
2259                 char pass[sizeof(pwd->password)+1];
2260
2261                 /* pwd->password may not be null terminated */
2262                 pass[sizeof(pwd->password)] = '\0';
2263                 strncpy(pass, pwd->password, sizeof(pwd->password));
2264                 printf(" password='%s', user='%s'",
2265                         pass,
2266                         (pwd->ctrl & ATA_SECURITY_PASSWORD_MASTER) ?
2267                         "master" : "user");
2268
2269                 if (command == ATA_SECURITY_SET_PASSWORD) {
2270                         printf(", mode='%s'",
2271                                (pwd->ctrl & ATA_SECURITY_LEVEL_MAXIMUM) ?
2272                                "maximum" : "high");
2273                 }
2274         }
2275
2276         printf("\n");
2277 }
2278
2279 static int
2280 atasecurity_freeze(struct cam_device *device, union ccb *ccb,
2281                    int retry_count, u_int32_t timeout, int quiet)
2282 {
2283
2284         if (quiet == 0)
2285                 atasecurity_notify(ATA_SECURITY_FREEZE_LOCK, NULL);
2286
2287         return ata_do_28bit_cmd(device,
2288                                 ccb,
2289                                 retry_count,
2290                                 /*flags*/CAM_DIR_NONE,
2291                                 /*protocol*/AP_PROTO_NON_DATA,
2292                                 /*tag_action*/MSG_SIMPLE_Q_TAG,
2293                                 /*command*/ATA_SECURITY_FREEZE_LOCK,
2294                                 /*features*/0,
2295                                 /*lba*/0,
2296                                 /*sector_count*/0,
2297                                 /*data_ptr*/NULL,
2298                                 /*dxfer_len*/0,
2299                                 /*timeout*/timeout,
2300                                 /*quiet*/0);
2301 }
2302
2303 static int
2304 atasecurity_unlock(struct cam_device *device, union ccb *ccb,
2305                    int retry_count, u_int32_t timeout,
2306                    struct ata_security_password *pwd, int quiet)
2307 {
2308
2309         if (quiet == 0)
2310                 atasecurity_notify(ATA_SECURITY_UNLOCK, pwd);
2311
2312         return ata_do_28bit_cmd(device,
2313                                 ccb,
2314                                 retry_count,
2315                                 /*flags*/CAM_DIR_OUT,
2316                                 /*protocol*/AP_PROTO_PIO_OUT,
2317                                 /*tag_action*/MSG_SIMPLE_Q_TAG,
2318                                 /*command*/ATA_SECURITY_UNLOCK,
2319                                 /*features*/0,
2320                                 /*lba*/0,
2321                                 /*sector_count*/0,
2322                                 /*data_ptr*/(u_int8_t *)pwd,
2323                                 /*dxfer_len*/sizeof(*pwd),
2324                                 /*timeout*/timeout,
2325                                 /*quiet*/0);
2326 }
2327
2328 static int
2329 atasecurity_disable(struct cam_device *device, union ccb *ccb,
2330                     int retry_count, u_int32_t timeout,
2331                     struct ata_security_password *pwd, int quiet)
2332 {
2333
2334         if (quiet == 0)
2335                 atasecurity_notify(ATA_SECURITY_DISABLE_PASSWORD, pwd);
2336         return ata_do_28bit_cmd(device,
2337                                 ccb,
2338                                 retry_count,
2339                                 /*flags*/CAM_DIR_OUT,
2340                                 /*protocol*/AP_PROTO_PIO_OUT,
2341                                 /*tag_action*/MSG_SIMPLE_Q_TAG,
2342                                 /*command*/ATA_SECURITY_DISABLE_PASSWORD,
2343                                 /*features*/0,
2344                                 /*lba*/0,
2345                                 /*sector_count*/0,
2346                                 /*data_ptr*/(u_int8_t *)pwd,
2347                                 /*dxfer_len*/sizeof(*pwd),
2348                                 /*timeout*/timeout,
2349                                 /*quiet*/0);
2350 }
2351
2352
2353 static int
2354 atasecurity_erase_confirm(struct cam_device *device,
2355                           struct ata_params* ident_buf)
2356 {
2357
2358         printf("\nYou are about to ERASE ALL DATA from the following"
2359                " device:\n%s%d,%s%d: ", device->device_name,
2360                device->dev_unit_num, device->given_dev_name,
2361                device->given_unit_number);
2362         ata_print_ident(ident_buf);
2363
2364         for(;;) {
2365                 char str[50];
2366                 printf("\nAre you SURE you want to ERASE ALL DATA? (yes/no) ");
2367
2368                 if (fgets(str, sizeof(str), stdin) != NULL) {
2369                         if (strncasecmp(str, "yes", 3) == 0) {
2370                                 return (1);
2371                         } else if (strncasecmp(str, "no", 2) == 0) {
2372                                 return (0);
2373                         } else {
2374                                 printf("Please answer \"yes\" or "
2375                                        "\"no\"\n");
2376                         }
2377                 }
2378         }
2379
2380         /* NOTREACHED */
2381         return (0);
2382 }
2383
2384 static int
2385 atasecurity_erase(struct cam_device *device, union ccb *ccb,
2386                   int retry_count, u_int32_t timeout,
2387                   u_int32_t erase_timeout,
2388                   struct ata_security_password *pwd, int quiet)
2389 {
2390         int error;
2391
2392         if (quiet == 0)
2393                 atasecurity_notify(ATA_SECURITY_ERASE_PREPARE, NULL);
2394
2395         error = ata_do_28bit_cmd(device,
2396                                  ccb,
2397                                  retry_count,
2398                                  /*flags*/CAM_DIR_NONE,
2399                                  /*protocol*/AP_PROTO_NON_DATA,
2400                                  /*tag_action*/MSG_SIMPLE_Q_TAG,
2401                                  /*command*/ATA_SECURITY_ERASE_PREPARE,
2402                                  /*features*/0,
2403                                  /*lba*/0,
2404                                  /*sector_count*/0,
2405                                  /*data_ptr*/NULL,
2406                                  /*dxfer_len*/0,
2407                                  /*timeout*/timeout,
2408                                  /*quiet*/0);
2409
2410         if (error != 0)
2411                 return error;
2412
2413         if (quiet == 0)
2414                 atasecurity_notify(ATA_SECURITY_ERASE_UNIT, pwd);
2415
2416         error = ata_do_28bit_cmd(device,
2417                                  ccb,
2418                                  retry_count,
2419                                  /*flags*/CAM_DIR_OUT,
2420                                  /*protocol*/AP_PROTO_PIO_OUT,
2421                                  /*tag_action*/MSG_SIMPLE_Q_TAG,
2422                                  /*command*/ATA_SECURITY_ERASE_UNIT,
2423                                  /*features*/0,
2424                                  /*lba*/0,
2425                                  /*sector_count*/0,
2426                                  /*data_ptr*/(u_int8_t *)pwd,
2427                                  /*dxfer_len*/sizeof(*pwd),
2428                                  /*timeout*/erase_timeout,
2429                                  /*quiet*/0);
2430
2431         if (error == 0 && quiet == 0)
2432                 printf("\nErase Complete\n");
2433
2434         return error;
2435 }
2436
2437 static int
2438 atasecurity_set_password(struct cam_device *device, union ccb *ccb,
2439                          int retry_count, u_int32_t timeout,
2440                          struct ata_security_password *pwd, int quiet)
2441 {
2442
2443         if (quiet == 0)
2444                 atasecurity_notify(ATA_SECURITY_SET_PASSWORD, pwd);
2445
2446         return ata_do_28bit_cmd(device,
2447                                  ccb,
2448                                  retry_count,
2449                                  /*flags*/CAM_DIR_OUT,
2450                                  /*protocol*/AP_PROTO_PIO_OUT,
2451                                  /*tag_action*/MSG_SIMPLE_Q_TAG,
2452                                  /*command*/ATA_SECURITY_SET_PASSWORD,
2453                                  /*features*/0,
2454                                  /*lba*/0,
2455                                  /*sector_count*/0,
2456                                  /*data_ptr*/(u_int8_t *)pwd,
2457                                  /*dxfer_len*/sizeof(*pwd),
2458                                  /*timeout*/timeout,
2459                                  /*quiet*/0);
2460 }
2461
2462 static void
2463 atasecurity_print(struct ata_params *parm)
2464 {
2465
2466         printf("\nSecurity Option           Value\n");
2467         if (arglist & CAM_ARG_VERBOSE) {
2468                 printf("status                    %04x\n",
2469                        parm->security_status);
2470         }
2471         printf("supported                 %s\n",
2472                 parm->security_status & ATA_SECURITY_SUPPORTED ? "yes" : "no");
2473         if (!(parm->security_status & ATA_SECURITY_SUPPORTED))
2474                 return;
2475         printf("enabled                   %s\n",
2476                 parm->security_status & ATA_SECURITY_ENABLED ? "yes" : "no");
2477         printf("drive locked              %s\n",
2478                 parm->security_status & ATA_SECURITY_LOCKED ? "yes" : "no");
2479         printf("security config frozen    %s\n",
2480                 parm->security_status & ATA_SECURITY_FROZEN ? "yes" : "no");
2481         printf("count expired             %s\n",
2482                 parm->security_status & ATA_SECURITY_COUNT_EXP ? "yes" : "no");
2483         printf("security level            %s\n",
2484                 parm->security_status & ATA_SECURITY_LEVEL ? "maximum" : "high");
2485         printf("enhanced erase supported  %s\n",
2486                 parm->security_status & ATA_SECURITY_ENH_SUPP ? "yes" : "no");
2487         printf("erase time                ");
2488         atasecurity_print_time(parm->erase_time);
2489         printf("\n");
2490         printf("enhanced erase time       ");
2491         atasecurity_print_time(parm->enhanced_erase_time);
2492         printf("\n");
2493         printf("master password rev       %04x%s\n",
2494                 parm->master_passwd_revision,
2495                 parm->master_passwd_revision == 0x0000 ||
2496                 parm->master_passwd_revision == 0xFFFF ?  " (unsupported)" : "");
2497 }
2498
2499 /*
2500  * Validates and copies the password in optarg to the passed buffer.
2501  * If the password in optarg is the same length as the buffer then
2502  * the data will still be copied but no null termination will occur.
2503  */
2504 static int
2505 ata_getpwd(u_int8_t *passwd, int max, char opt)
2506 {
2507         int len;
2508
2509         len = strlen(optarg);
2510         if (len > max) {
2511                 warnx("-%c password is too long", opt);
2512                 return (1);
2513         } else if (len == 0) {
2514                 warnx("-%c password is missing", opt);
2515                 return (1);
2516         } else if (optarg[0] == '-'){
2517                 warnx("-%c password starts with '-' (generic arg?)", opt);
2518                 return (1);
2519         } else if (strlen(passwd) != 0 && strcmp(passwd, optarg) != 0) {
2520                 warnx("-%c password conflicts with existing password from -%c",
2521                       opt, pwd_opt);
2522                 return (1);
2523         }
2524
2525         /* Callers pass in a buffer which does NOT need to be terminated */
2526         strncpy(passwd, optarg, max);
2527         pwd_opt = opt;
2528
2529         return (0);
2530 }
2531
2532 enum {
2533         ATA_HPA_ACTION_PRINT,
2534         ATA_HPA_ACTION_SET_MAX,
2535         ATA_HPA_ACTION_SET_PWD,
2536         ATA_HPA_ACTION_LOCK,
2537         ATA_HPA_ACTION_UNLOCK,
2538         ATA_HPA_ACTION_FREEZE_LOCK
2539 };
2540
2541 static int
2542 atahpa_set_confirm(struct cam_device *device, struct ata_params* ident_buf,
2543                    u_int64_t maxsize, int persist)
2544 {
2545         printf("\nYou are about to configure HPA to limit the user accessible\n"
2546                "sectors to %ju %s on the device:\n%s%d,%s%d: ", maxsize,
2547                persist ? "persistently" : "temporarily",
2548                device->device_name, device->dev_unit_num,
2549                device->given_dev_name, device->given_unit_number);
2550         ata_print_ident(ident_buf);
2551
2552         for(;;) {
2553                 char str[50];
2554                 printf("\nAre you SURE you want to configure HPA? (yes/no) ");
2555
2556                 if (NULL != fgets(str, sizeof(str), stdin)) {
2557                         if (0 == strncasecmp(str, "yes", 3)) {
2558                                 return (1);
2559                         } else if (0 == strncasecmp(str, "no", 2)) {
2560                                 return (0);
2561                         } else {
2562                                 printf("Please answer \"yes\" or "
2563                                        "\"no\"\n");
2564                         }
2565                 }
2566         }
2567
2568         /* NOTREACHED */
2569         return (0);
2570 }
2571
2572 static int
2573 atahpa(struct cam_device *device, int retry_count, int timeout,
2574        int argc, char **argv, char *combinedopt)
2575 {
2576         union ccb *ccb;
2577         struct ata_params *ident_buf;
2578         struct ccb_getdev cgd;
2579         struct ata_set_max_pwd pwd;
2580         int error, confirm, quiet, c, action, actions, persist;
2581         int security, is48bit, pwdsize;
2582         u_int64_t hpasize, maxsize;
2583
2584         actions = 0;
2585         confirm = 0;
2586         quiet = 0;
2587         maxsize = 0;
2588         persist = 0;
2589         security = 0;
2590
2591         memset(&pwd, 0, sizeof(pwd));
2592
2593         /* default action is to print hpa information */
2594         action = ATA_HPA_ACTION_PRINT;
2595         pwdsize = sizeof(pwd.password);
2596
2597         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2598                 switch(c){
2599                 case 's':
2600                         action = ATA_HPA_ACTION_SET_MAX;
2601                         maxsize = strtoumax(optarg, NULL, 0);
2602                         actions++;
2603                         break;
2604
2605                 case 'p':
2606                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2607                                 return (1);
2608                         action = ATA_HPA_ACTION_SET_PWD;
2609                         security = 1;
2610                         actions++;
2611                         break;
2612
2613                 case 'l':
2614                         action = ATA_HPA_ACTION_LOCK;
2615                         security = 1;
2616                         actions++;
2617                         break;
2618
2619                 case 'U':
2620                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2621                                 return (1);
2622                         action = ATA_HPA_ACTION_UNLOCK;
2623                         security = 1;
2624                         actions++;
2625                         break;
2626
2627                 case 'f':
2628                         action = ATA_HPA_ACTION_FREEZE_LOCK;
2629                         security = 1;
2630                         actions++;
2631                         break;
2632
2633                 case 'P':
2634                         persist = 1;
2635                         break;
2636
2637                 case 'y':
2638                         confirm++;
2639                         break;
2640
2641                 case 'q':
2642                         quiet++;
2643                         break;
2644                 }
2645         }
2646
2647         if (actions > 1) {
2648                 warnx("too many hpa actions specified");
2649                 return (1);
2650         }
2651
2652         if (get_cgd(device, &cgd) != 0) {
2653                 warnx("couldn't get CGD");
2654                 return (1);
2655         }
2656
2657         ccb = cam_getccb(device);
2658         if (ccb == NULL) {
2659                 warnx("couldn't allocate CCB");
2660                 return (1);
2661         }
2662
2663         error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2664         if (error != 0) {
2665                 cam_freeccb(ccb);
2666                 return (1);
2667         }
2668
2669         if (quiet == 0) {
2670                 printf("%s%d: ", device->device_name, device->dev_unit_num);
2671                 ata_print_ident(ident_buf);
2672                 camxferrate(device);
2673         }
2674
2675         if (action == ATA_HPA_ACTION_PRINT) {
2676                 error = ata_read_native_max(device, retry_count, timeout, ccb,
2677                                             ident_buf, &hpasize);
2678                 if (error == 0)
2679                         atahpa_print(ident_buf, hpasize, 1);
2680
2681                 cam_freeccb(ccb);
2682                 free(ident_buf);
2683                 return (error);
2684         }
2685
2686         if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) {
2687                 warnx("HPA is not supported by this device");
2688                 cam_freeccb(ccb);
2689                 free(ident_buf);
2690                 return (1);
2691         }
2692
2693         if (security && !(ident_buf->support.command1 & ATA_SUPPORT_MAXSECURITY)) {
2694                 warnx("HPA Security is not supported by this device");
2695                 cam_freeccb(ccb);
2696                 free(ident_buf);
2697                 return (1);
2698         }
2699
2700         is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48;
2701
2702         /*
2703          * The ATA spec requires:
2704          * 1. Read native max addr is called directly before set max addr
2705          * 2. Read native max addr is NOT called before any other set max call
2706          */
2707         switch(action) {
2708         case ATA_HPA_ACTION_SET_MAX:
2709                 if (confirm == 0 &&
2710                     atahpa_set_confirm(device, ident_buf, maxsize,
2711                     persist) == 0) {
2712                         cam_freeccb(ccb);
2713                         free(ident_buf);
2714                         return (1);
2715                 }
2716
2717                 error = ata_read_native_max(device, retry_count, timeout,
2718                                             ccb, ident_buf, &hpasize);
2719                 if (error == 0) {
2720                         error = atahpa_set_max(device, retry_count, timeout,
2721                                                ccb, is48bit, maxsize, persist);
2722                         if (error == 0) {
2723                                 /* redo identify to get new lba values */
2724                                 error = ata_do_identify(device, retry_count,
2725                                                         timeout, ccb,
2726                                                         &ident_buf);
2727                                 atahpa_print(ident_buf, hpasize, 1);
2728                         }
2729                 }
2730                 break;
2731
2732         case ATA_HPA_ACTION_SET_PWD:
2733                 error = atahpa_password(device, retry_count, timeout,
2734                                         ccb, is48bit, &pwd);
2735                 if (error == 0)
2736                         printf("HPA password has been set\n");
2737                 break;
2738
2739         case ATA_HPA_ACTION_LOCK:
2740                 error = atahpa_lock(device, retry_count, timeout,
2741                                     ccb, is48bit);
2742                 if (error == 0)
2743                         printf("HPA has been locked\n");
2744                 break;
2745
2746         case ATA_HPA_ACTION_UNLOCK:
2747                 error = atahpa_unlock(device, retry_count, timeout,
2748                                       ccb, is48bit, &pwd);
2749                 if (error == 0)
2750                         printf("HPA has been unlocked\n");
2751                 break;
2752
2753         case ATA_HPA_ACTION_FREEZE_LOCK:
2754                 error = atahpa_freeze_lock(device, retry_count, timeout,
2755                                            ccb, is48bit);
2756                 if (error == 0)
2757                         printf("HPA has been frozen\n");
2758                 break;
2759
2760         default:
2761                 errx(1, "Option currently not supported");
2762         }
2763
2764         cam_freeccb(ccb);
2765         free(ident_buf);
2766
2767         return (error);
2768 }
2769
2770 static int
2771 atasecurity(struct cam_device *device, int retry_count, int timeout,
2772             int argc, char **argv, char *combinedopt)
2773 {
2774         union ccb *ccb;
2775         struct ata_params *ident_buf;
2776         int error, confirm, quiet, c, action, actions, setpwd;
2777         int security_enabled, erase_timeout, pwdsize;
2778         struct ata_security_password pwd;
2779
2780         actions = 0;
2781         setpwd = 0;
2782         erase_timeout = 0;
2783         confirm = 0;
2784         quiet = 0;
2785
2786         memset(&pwd, 0, sizeof(pwd));
2787
2788         /* default action is to print security information */
2789         action = ATA_SECURITY_ACTION_PRINT;
2790
2791         /* user is master by default as its safer that way */
2792         pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2793         pwdsize = sizeof(pwd.password);
2794
2795         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2796                 switch(c){
2797                 case 'f':
2798                         action = ATA_SECURITY_ACTION_FREEZE;
2799                         actions++;
2800                         break;
2801
2802                 case 'U':
2803                         if (strcasecmp(optarg, "user") == 0) {
2804                                 pwd.ctrl |= ATA_SECURITY_PASSWORD_USER;
2805                                 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER;
2806                         } else if (strcasecmp(optarg, "master") == 0) {
2807                                 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2808                                 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER;
2809                         } else {
2810                                 warnx("-U argument '%s' is invalid (must be "
2811                                       "'user' or 'master')", optarg);
2812                                 return (1);
2813                         }
2814                         break;
2815
2816                 case 'l':
2817                         if (strcasecmp(optarg, "high") == 0) {
2818                                 pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH;
2819                                 pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM;
2820                         } else if (strcasecmp(optarg, "maximum") == 0) {
2821                                 pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM;
2822                                 pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH;
2823                         } else {
2824                                 warnx("-l argument '%s' is unknown (must be "
2825                                       "'high' or 'maximum')", optarg);
2826                                 return (1);
2827                         }
2828                         break;
2829
2830                 case 'k':
2831                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2832                                 return (1);
2833                         action = ATA_SECURITY_ACTION_UNLOCK;
2834                         actions++;
2835                         break;
2836
2837                 case 'd':
2838                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2839                                 return (1);
2840                         action = ATA_SECURITY_ACTION_DISABLE;
2841                         actions++;
2842                         break;
2843
2844                 case 'e':
2845                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2846                                 return (1);
2847                         action = ATA_SECURITY_ACTION_ERASE;
2848                         actions++;
2849                         break;
2850
2851                 case 'h':
2852                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2853                                 return (1);
2854                         pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED;
2855                         action = ATA_SECURITY_ACTION_ERASE_ENHANCED;
2856                         actions++;
2857                         break;
2858
2859                 case 's':
2860                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2861                                 return (1);
2862                         setpwd = 1;
2863                         if (action == ATA_SECURITY_ACTION_PRINT)
2864                                 action = ATA_SECURITY_ACTION_SET_PASSWORD;
2865                         /*
2866                          * Don't increment action as this can be combined
2867                          * with other actions.
2868                          */
2869                         break;
2870
2871                 case 'y':
2872                         confirm++;
2873                         break;
2874
2875                 case 'q':
2876                         quiet++;
2877                         break;
2878
2879                 case 'T':
2880                         erase_timeout = atoi(optarg) * 1000;
2881                         break;
2882                 }
2883         }
2884
2885         if (actions > 1) {
2886                 warnx("too many security actions specified");
2887                 return (1);
2888         }
2889
2890         if ((ccb = cam_getccb(device)) == NULL) {
2891                 warnx("couldn't allocate CCB");
2892                 return (1);
2893         }
2894
2895         error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2896         if (error != 0) {
2897                 cam_freeccb(ccb);
2898                 return (1);
2899         }
2900
2901         if (quiet == 0) {
2902                 printf("%s%d: ", device->device_name, device->dev_unit_num);
2903                 ata_print_ident(ident_buf);
2904                 camxferrate(device);
2905         }
2906
2907         if (action == ATA_SECURITY_ACTION_PRINT) {
2908                 atasecurity_print(ident_buf);
2909                 free(ident_buf);
2910                 cam_freeccb(ccb);
2911                 return (0);
2912         }
2913
2914         if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) {
2915                 warnx("Security not supported");
2916                 free(ident_buf);
2917                 cam_freeccb(ccb);
2918                 return (1);
2919         }
2920
2921         /* default timeout 15 seconds the same as linux hdparm */
2922         timeout = timeout ? timeout : 15 * 1000;
2923
2924         security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED;
2925
2926         /* first set the password if requested */
2927         if (setpwd == 1) {
2928                 /* confirm we can erase before setting the password if erasing */
2929                 if (confirm == 0 &&
2930                     (action == ATA_SECURITY_ACTION_ERASE_ENHANCED ||
2931                     action == ATA_SECURITY_ACTION_ERASE) &&
2932                     atasecurity_erase_confirm(device, ident_buf) == 0) {
2933                         cam_freeccb(ccb);
2934                         free(ident_buf);
2935                         return (error);
2936                 }
2937
2938                 if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) {
2939                         pwd.revision = ident_buf->master_passwd_revision;
2940                         if (pwd.revision != 0 && pwd.revision != 0xfff &&
2941                             --pwd.revision == 0) {
2942                                 pwd.revision = 0xfffe;
2943                         }
2944                 }
2945                 error = atasecurity_set_password(device, ccb, retry_count,
2946                                                  timeout, &pwd, quiet);
2947                 if (error != 0) {
2948                         cam_freeccb(ccb);
2949                         free(ident_buf);
2950                         return (error);
2951                 }
2952                 security_enabled = 1;
2953         }
2954
2955         switch(action) {
2956         case ATA_SECURITY_ACTION_FREEZE:
2957                 error = atasecurity_freeze(device, ccb, retry_count,
2958                                            timeout, quiet);
2959                 break;
2960
2961         case ATA_SECURITY_ACTION_UNLOCK:
2962                 if (security_enabled) {
2963                         if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2964                                 error = atasecurity_unlock(device, ccb,
2965                                         retry_count, timeout, &pwd, quiet);
2966                         } else {
2967                                 warnx("Can't unlock, drive is not locked");
2968                                 error = 1;
2969                         }
2970                 } else {
2971                         warnx("Can't unlock, security is disabled");
2972                         error = 1;
2973                 }
2974                 break;
2975
2976         case ATA_SECURITY_ACTION_DISABLE:
2977                 if (security_enabled) {
2978                         /* First unlock the drive if its locked */
2979                         if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2980                                 error = atasecurity_unlock(device, ccb,
2981                                                            retry_count,
2982                                                            timeout,
2983                                                            &pwd,
2984                                                            quiet);
2985                         }
2986
2987                         if (error == 0) {
2988                                 error = atasecurity_disable(device,
2989                                                             ccb,
2990                                                             retry_count,
2991                                                             timeout,
2992                                                             &pwd,
2993                                                             quiet);
2994                         }
2995                 } else {
2996                         warnx("Can't disable security (already disabled)");
2997                         error = 1;
2998                 }
2999                 break;
3000
3001         case ATA_SECURITY_ACTION_ERASE:
3002                 if (security_enabled) {
3003                         if (erase_timeout == 0) {
3004                                 erase_timeout = atasecurity_erase_timeout_msecs(
3005                                     ident_buf->erase_time);
3006                         }
3007
3008                         error = atasecurity_erase(device, ccb, retry_count,
3009                                                   timeout, erase_timeout, &pwd,
3010                                                   quiet);
3011                 } else {
3012                         warnx("Can't secure erase (security is disabled)");
3013                         error = 1;
3014                 }
3015                 break;
3016
3017         case ATA_SECURITY_ACTION_ERASE_ENHANCED:
3018                 if (security_enabled) {
3019                         if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) {
3020                                 if (erase_timeout == 0) {
3021                                         erase_timeout =
3022                                             atasecurity_erase_timeout_msecs(
3023                                                 ident_buf->enhanced_erase_time);
3024                                 }
3025
3026                                 error = atasecurity_erase(device, ccb,
3027                                                           retry_count, timeout,
3028                                                           erase_timeout, &pwd,
3029                                                           quiet);
3030                         } else {
3031                                 warnx("Enhanced erase is not supported");
3032                                 error = 1;
3033                         }
3034                 } else {
3035                         warnx("Can't secure erase (enhanced), "
3036                               "(security is disabled)");
3037                         error = 1;
3038                 }
3039                 break;
3040         }
3041
3042         cam_freeccb(ccb);
3043         free(ident_buf);
3044
3045         return (error);
3046 }
3047 #endif /* MINIMALISTIC */
3048
3049 /*
3050  * Parse out a bus, or a bus, target and lun in the following
3051  * format:
3052  * bus
3053  * bus:target
3054  * bus:target:lun
3055  *
3056  * Returns the number of parsed components, or 0.
3057  */
3058 static int
3059 parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun,
3060     cam_argmask *arglst)
3061 {
3062         char *tmpstr;
3063         int convs = 0;
3064
3065         while (isspace(*tstr) && (*tstr != '\0'))
3066                 tstr++;
3067
3068         tmpstr = (char *)strtok(tstr, ":");
3069         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3070                 *bus = strtol(tmpstr, NULL, 0);
3071                 *arglst |= CAM_ARG_BUS;
3072                 convs++;
3073                 tmpstr = (char *)strtok(NULL, ":");
3074                 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3075                         *target = strtol(tmpstr, NULL, 0);
3076                         *arglst |= CAM_ARG_TARGET;
3077                         convs++;
3078                         tmpstr = (char *)strtok(NULL, ":");
3079                         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3080                                 *lun = strtol(tmpstr, NULL, 0);
3081                                 *arglst |= CAM_ARG_LUN;
3082                                 convs++;
3083                         }
3084                 }
3085         }
3086
3087         return convs;
3088 }
3089
3090 static int
3091 dorescan_or_reset(int argc, char **argv, int rescan)
3092 {
3093         static const char must[] =
3094                 "you must specify \"all\", a bus, or a bus:target:lun to %s";
3095         int rv, error = 0;
3096         path_id_t bus = CAM_BUS_WILDCARD;
3097         target_id_t target = CAM_TARGET_WILDCARD;
3098         lun_id_t lun = CAM_LUN_WILDCARD;
3099         char *tstr;
3100
3101         if (argc < 3) {
3102                 warnx(must, rescan? "rescan" : "reset");
3103                 return(1);
3104         }
3105
3106         tstr = argv[optind];
3107         while (isspace(*tstr) && (*tstr != '\0'))
3108                 tstr++;
3109         if (strncasecmp(tstr, "all", strlen("all")) == 0)
3110                 arglist |= CAM_ARG_BUS;
3111         else {
3112                 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
3113                 if (rv != 1 && rv != 3) {
3114                         warnx(must, rescan? "rescan" : "reset");
3115                         return(1);
3116                 }
3117         }
3118
3119         if ((arglist & CAM_ARG_BUS)
3120             && (arglist & CAM_ARG_TARGET)
3121             && (arglist & CAM_ARG_LUN))
3122                 error = scanlun_or_reset_dev(bus, target, lun, rescan);
3123         else
3124                 error = rescan_or_reset_bus(bus, rescan);
3125
3126         return(error);
3127 }
3128
3129 static int
3130 rescan_or_reset_bus(path_id_t bus, int rescan)
3131 {
3132         union ccb ccb, matchccb;
3133         int fd, retval;
3134         int bufsize;
3135
3136         retval = 0;
3137
3138         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3139                 warnx("error opening transport layer device %s", XPT_DEVICE);
3140                 warn("%s", XPT_DEVICE);
3141                 return(1);
3142         }
3143
3144         if (bus != CAM_BUS_WILDCARD) {
3145                 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3146                 ccb.ccb_h.path_id = bus;
3147                 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3148                 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3149                 ccb.crcn.flags = CAM_FLAG_NONE;
3150
3151                 /* run this at a low priority */
3152                 ccb.ccb_h.pinfo.priority = 5;
3153
3154                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3155                         warn("CAMIOCOMMAND ioctl failed");
3156                         close(fd);
3157                         return(1);
3158                 }
3159
3160                 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3161                         fprintf(stdout, "%s of bus %d was successful\n",
3162                             rescan ? "Re-scan" : "Reset", bus);
3163                 } else {
3164                         fprintf(stdout, "%s of bus %d returned error %#x\n",
3165                                 rescan ? "Re-scan" : "Reset", bus,
3166                                 ccb.ccb_h.status & CAM_STATUS_MASK);
3167                         retval = 1;
3168                 }
3169
3170                 close(fd);
3171                 return(retval);
3172
3173         }
3174
3175
3176         /*
3177          * The right way to handle this is to modify the xpt so that it can
3178          * handle a wildcarded bus in a rescan or reset CCB.  At the moment
3179          * that isn't implemented, so instead we enumerate the busses and
3180          * send the rescan or reset to those busses in the case where the
3181          * given bus is -1 (wildcard).  We don't send a rescan or reset
3182          * to the xpt bus; sending a rescan to the xpt bus is effectively a
3183          * no-op, sending a rescan to the xpt bus would result in a status of
3184          * CAM_REQ_INVALID.
3185          */
3186         bzero(&(&matchccb.ccb_h)[1],
3187               sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
3188         matchccb.ccb_h.func_code = XPT_DEV_MATCH;
3189         matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
3190         bufsize = sizeof(struct dev_match_result) * 20;
3191         matchccb.cdm.match_buf_len = bufsize;
3192         matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
3193         if (matchccb.cdm.matches == NULL) {
3194                 warnx("can't malloc memory for matches");
3195                 retval = 1;
3196                 goto bailout;
3197         }
3198         matchccb.cdm.num_matches = 0;
3199
3200         matchccb.cdm.num_patterns = 1;
3201         matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3202
3203         matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
3204                 matchccb.cdm.pattern_buf_len);
3205         if (matchccb.cdm.patterns == NULL) {
3206                 warnx("can't malloc memory for patterns");
3207                 retval = 1;
3208                 goto bailout;
3209         }
3210         matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
3211         matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3212
3213         do {
3214                 unsigned int i;
3215
3216                 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
3217                         warn("CAMIOCOMMAND ioctl failed");
3218                         retval = 1;
3219                         goto bailout;
3220                 }
3221
3222                 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
3223                  || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
3224                    && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
3225                         warnx("got CAM error %#x, CDM error %d\n",
3226                               matchccb.ccb_h.status, matchccb.cdm.status);
3227                         retval = 1;
3228                         goto bailout;
3229                 }
3230
3231                 for (i = 0; i < matchccb.cdm.num_matches; i++) {
3232                         struct bus_match_result *bus_result;
3233
3234                         /* This shouldn't happen. */
3235                         if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
3236                                 continue;
3237
3238                         bus_result = &matchccb.cdm.matches[i].result.bus_result;
3239
3240                         /*
3241                          * We don't want to rescan or reset the xpt bus.
3242                          * See above.
3243                          */
3244                         if (bus_result->path_id == CAM_XPT_PATH_ID)
3245                                 continue;
3246
3247                         ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3248                                                        XPT_RESET_BUS;
3249                         ccb.ccb_h.path_id = bus_result->path_id;
3250                         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3251                         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3252                         ccb.crcn.flags = CAM_FLAG_NONE;
3253
3254                         /* run this at a low priority */
3255                         ccb.ccb_h.pinfo.priority = 5;
3256
3257                         if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3258                                 warn("CAMIOCOMMAND ioctl failed");
3259                                 retval = 1;
3260                                 goto bailout;
3261                         }
3262
3263                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
3264                                 fprintf(stdout, "%s of bus %d was successful\n",
3265                                         rescan? "Re-scan" : "Reset",
3266                                         bus_result->path_id);
3267                         } else {
3268                                 /*
3269                                  * Don't bail out just yet, maybe the other
3270                                  * rescan or reset commands will complete
3271                                  * successfully.
3272                                  */
3273                                 fprintf(stderr, "%s of bus %d returned error "
3274                                         "%#x\n", rescan? "Re-scan" : "Reset",
3275                                         bus_result->path_id,
3276                                         ccb.ccb_h.status & CAM_STATUS_MASK);
3277                                 retval = 1;
3278                         }
3279                 }
3280         } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
3281                  && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
3282
3283 bailout:
3284
3285         if (fd != -1)
3286                 close(fd);
3287
3288         if (matchccb.cdm.patterns != NULL)
3289                 free(matchccb.cdm.patterns);
3290         if (matchccb.cdm.matches != NULL)
3291                 free(matchccb.cdm.matches);
3292
3293         return(retval);
3294 }
3295
3296 static int
3297 scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3298 {
3299         union ccb ccb;
3300         struct cam_device *device;
3301         int fd;
3302
3303         device = NULL;
3304
3305         if (bus == CAM_BUS_WILDCARD) {
3306                 warnx("invalid bus number %d", bus);
3307                 return(1);
3308         }
3309
3310         if (target == CAM_TARGET_WILDCARD) {
3311                 warnx("invalid target number %d", target);
3312                 return(1);
3313         }
3314
3315         if (lun == CAM_LUN_WILDCARD) {
3316                 warnx("invalid lun number %jx", (uintmax_t)lun);
3317                 return(1);
3318         }
3319
3320         fd = -1;
3321
3322         bzero(&ccb, sizeof(union ccb));
3323
3324         if (scan) {
3325                 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3326                         warnx("error opening transport layer device %s\n",
3327                             XPT_DEVICE);
3328                         warn("%s", XPT_DEVICE);
3329                         return(1);
3330                 }
3331         } else {
3332                 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3333                 if (device == NULL) {
3334                         warnx("%s", cam_errbuf);
3335                         return(1);
3336                 }
3337         }
3338
3339         ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3340         ccb.ccb_h.path_id = bus;
3341         ccb.ccb_h.target_id = target;
3342         ccb.ccb_h.target_lun = lun;
3343         ccb.ccb_h.timeout = 5000;
3344         ccb.crcn.flags = CAM_FLAG_NONE;
3345
3346         /* run this at a low priority */
3347         ccb.ccb_h.pinfo.priority = 5;
3348
3349         if (scan) {
3350                 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3351                         warn("CAMIOCOMMAND ioctl failed");
3352                         close(fd);
3353                         return(1);
3354                 }
3355         } else {
3356                 if (cam_send_ccb(device, &ccb) < 0) {
3357                         warn("error sending XPT_RESET_DEV CCB");
3358                         cam_close_device(device);
3359                         return(1);
3360                 }
3361         }
3362
3363         if (scan)
3364                 close(fd);
3365         else
3366                 cam_close_device(device);
3367
3368         /*
3369          * An error code of CAM_BDR_SENT is normal for a BDR request.
3370          */
3371         if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3372          || ((!scan)
3373           && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3374                 fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3375                     scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3376                 return(0);
3377         } else {
3378                 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3379                     scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3380                     ccb.ccb_h.status & CAM_STATUS_MASK);
3381                 return(1);
3382         }
3383 }
3384
3385 #ifndef MINIMALISTIC
3386
3387 static struct scsi_nv defect_list_type_map[] = {
3388         { "block", SRDD10_BLOCK_FORMAT },
3389         { "extbfi", SRDD10_EXT_BFI_FORMAT },
3390         { "extphys", SRDD10_EXT_PHYS_FORMAT },
3391         { "longblock", SRDD10_LONG_BLOCK_FORMAT },
3392         { "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3393         { "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3394 };
3395
3396 static int
3397 readdefects(struct cam_device *device, int argc, char **argv,
3398             char *combinedopt, int retry_count, int timeout)
3399 {
3400         union ccb *ccb = NULL;
3401         struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3402         struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3403         size_t hdr_size = 0, entry_size = 0;
3404         int use_12byte = 0;
3405         int hex_format = 0;
3406         u_int8_t *defect_list = NULL;
3407         u_int8_t list_format = 0;
3408         int list_type_set = 0;
3409         u_int32_t dlist_length = 0;
3410         u_int32_t returned_length = 0, valid_len = 0;
3411         u_int32_t num_returned = 0, num_valid = 0;
3412         u_int32_t max_possible_size = 0, hdr_max = 0;
3413         u_int32_t starting_offset = 0;
3414         u_int8_t returned_format, returned_type;
3415         unsigned int i;
3416         int summary = 0, quiet = 0;
3417         int c, error = 0;
3418         int lists_specified = 0;
3419         int get_length = 1, first_pass = 1;
3420         int mads = 0;
3421
3422         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3423                 switch(c){
3424                 case 'f':
3425                 {
3426                         scsi_nv_status status;
3427                         int entry_num = 0;
3428
3429                         status = scsi_get_nv(defect_list_type_map,
3430                             sizeof(defect_list_type_map) /
3431                             sizeof(defect_list_type_map[0]), optarg,
3432                             &entry_num, SCSI_NV_FLAG_IG_CASE);
3433
3434                         if (status == SCSI_NV_FOUND) {
3435                                 list_format = defect_list_type_map[
3436                                     entry_num].value;
3437                                 list_type_set = 1;
3438                         } else {
3439                                 warnx("%s: %s %s option %s", __func__,
3440                                     (status == SCSI_NV_AMBIGUOUS) ?
3441                                     "ambiguous" : "invalid", "defect list type",
3442                                     optarg);
3443                                 error = 1;
3444                                 goto defect_bailout;
3445                         }
3446                         break;
3447                 }
3448                 case 'G':
3449                         arglist |= CAM_ARG_GLIST;
3450                         break;
3451                 case 'P':
3452                         arglist |= CAM_ARG_PLIST;
3453                         break;
3454                 case 'q':
3455                         quiet = 1;
3456                         break;
3457                 case 's':
3458                         summary = 1;
3459                         break;
3460                 case 'S': {
3461                         char *endptr;
3462
3463                         starting_offset = strtoul(optarg, &endptr, 0);
3464                         if (*endptr != '\0') {
3465                                 error = 1;
3466                                 warnx("invalid starting offset %s", optarg);
3467                                 goto defect_bailout;
3468                         }
3469                         break;
3470                 }
3471                 case 'X':
3472                         hex_format = 1;
3473                         break;
3474                 default:
3475                         break;
3476                 }
3477         }
3478
3479         if (list_type_set == 0) {
3480                 error = 1;
3481                 warnx("no defect list format specified");
3482                 goto defect_bailout;
3483         }
3484
3485         if (arglist & CAM_ARG_PLIST) {
3486                 list_format |= SRDD10_PLIST;
3487                 lists_specified++;
3488         }
3489
3490         if (arglist & CAM_ARG_GLIST) {
3491                 list_format |= SRDD10_GLIST;
3492                 lists_specified++;
3493         }
3494
3495         /*
3496          * This implies a summary, and was the previous behavior.
3497          */
3498         if (lists_specified == 0)
3499                 summary = 1;
3500
3501         ccb = cam_getccb(device);
3502
3503 retry_12byte:
3504
3505         /*
3506          * We start off asking for just the header to determine how much
3507          * defect data is available.  Some Hitachi drives return an error
3508          * if you ask for more data than the drive has.  Once we know the
3509          * length, we retry the command with the returned length.
3510          */
3511         if (use_12byte == 0)
3512                 dlist_length = sizeof(*hdr10);
3513         else
3514                 dlist_length = sizeof(*hdr12);
3515
3516 retry:
3517         if (defect_list != NULL) {
3518                 free(defect_list);
3519                 defect_list = NULL;
3520         }
3521         defect_list = malloc(dlist_length);
3522         if (defect_list == NULL) {
3523                 warnx("can't malloc memory for defect list");
3524                 error = 1;
3525                 goto defect_bailout;
3526         }
3527
3528 next_batch:
3529         bzero(defect_list, dlist_length);
3530
3531         /*
3532          * cam_getccb() zeros the CCB header only.  So we need to zero the
3533          * payload portion of the ccb.
3534          */
3535         bzero(&(&ccb->ccb_h)[1],
3536               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3537
3538         scsi_read_defects(&ccb->csio,
3539                           /*retries*/ retry_count,
3540                           /*cbfcnp*/ NULL,
3541                           /*tag_action*/ MSG_SIMPLE_Q_TAG,
3542                           /*list_format*/ list_format,
3543                           /*addr_desc_index*/ starting_offset,
3544                           /*data_ptr*/ defect_list,
3545                           /*dxfer_len*/ dlist_length,
3546                           /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3547                           /*sense_len*/ SSD_FULL_SIZE,
3548                           /*timeout*/ timeout ? timeout : 5000);
3549
3550         /* Disable freezing the device queue */
3551         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3552
3553         if (cam_send_ccb(device, ccb) < 0) {
3554                 perror("error reading defect list");
3555
3556                 if (arglist & CAM_ARG_VERBOSE) {
3557                         cam_error_print(device, ccb, CAM_ESF_ALL,
3558                                         CAM_EPF_ALL, stderr);
3559                 }
3560
3561                 error = 1;
3562                 goto defect_bailout;
3563         }
3564
3565         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3566
3567         if (use_12byte == 0) {
3568                 hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3569                 hdr_size = sizeof(*hdr10);
3570                 hdr_max = SRDDH10_MAX_LENGTH;
3571
3572                 if (valid_len >= hdr_size) {
3573                         returned_length = scsi_2btoul(hdr10->length);
3574                         returned_format = hdr10->format;
3575                 } else {
3576                         returned_length = 0;
3577                         returned_format = 0;
3578                 }
3579         } else {
3580                 hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3581                 hdr_size = sizeof(*hdr12);
3582                 hdr_max = SRDDH12_MAX_LENGTH;
3583
3584                 if (valid_len >= hdr_size) {
3585                         returned_length = scsi_4btoul(hdr12->length);
3586                         returned_format = hdr12->format;
3587                 } else {
3588                         returned_length = 0;
3589                         returned_format = 0;
3590                 }
3591         }
3592
3593         returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3594         switch (returned_type) {
3595         case SRDD10_BLOCK_FORMAT:
3596                 entry_size = sizeof(struct scsi_defect_desc_block);
3597                 break;
3598         case SRDD10_LONG_BLOCK_FORMAT:
3599                 entry_size = sizeof(struct scsi_defect_desc_long_block);
3600                 break;
3601         case SRDD10_EXT_PHYS_FORMAT:
3602         case SRDD10_PHYSICAL_SECTOR_FORMAT:
3603                 entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3604                 break;
3605         case SRDD10_EXT_BFI_FORMAT:
3606         case SRDD10_BYTES_FROM_INDEX_FORMAT:
3607                 entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3608                 break;
3609         default:
3610                 warnx("Unknown defect format 0x%x\n", returned_type);
3611                 error = 1;
3612                 goto defect_bailout;
3613                 break;
3614         } 
3615
3616         max_possible_size = (hdr_max / entry_size) * entry_size;
3617         num_returned = returned_length / entry_size;
3618         num_valid = min(returned_length, valid_len - hdr_size);
3619         num_valid /= entry_size;
3620
3621         if (get_length != 0) {
3622                 get_length = 0;
3623
3624                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3625                      CAM_SCSI_STATUS_ERROR) {
3626                         struct scsi_sense_data *sense;
3627                         int error_code, sense_key, asc, ascq;
3628
3629                         sense = &ccb->csio.sense_data;
3630                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
3631                             ccb->csio.sense_resid, &error_code, &sense_key,
3632                             &asc, &ascq, /*show_errors*/ 1);
3633
3634                         /*
3635                          * If the drive is reporting that it just doesn't
3636                          * support the defect list format, go ahead and use
3637                          * the length it reported.  Otherwise, the length
3638                          * may not be valid, so use the maximum.
3639                          */
3640                         if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3641                          && (asc == 0x1c) && (ascq == 0x00)
3642                          && (returned_length > 0)) {
3643                                 if ((use_12byte == 0)
3644                                  && (returned_length >= max_possible_size)) {
3645                                         get_length = 1;
3646                                         use_12byte = 1;
3647                                         goto retry_12byte;
3648                                 }
3649                                 dlist_length = returned_length + hdr_size;
3650                         } else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3651                                 && (asc == 0x1f) && (ascq == 0x00)
3652                                 && (returned_length > 0)) {
3653                                 /* Partial defect list transfer */
3654                                 /*
3655                                  * Hitachi drives return this error
3656                                  * along with a partial defect list if they
3657                                  * have more defects than the 10 byte
3658                                  * command can support.  Retry with the 12
3659                                  * byte command.
3660                                  */
3661                                 if (use_12byte == 0) {
3662                                         get_length = 1;
3663                                         use_12byte = 1;
3664                                         goto retry_12byte;
3665                                 }
3666                                 dlist_length = returned_length + hdr_size;
3667                         } else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3668                                 && (asc == 0x24) && (ascq == 0x00)) {
3669                                 /* Invalid field in CDB */
3670                                 /*
3671                                  * SBC-3 says that if the drive has more
3672                                  * defects than can be reported with the
3673                                  * 10 byte command, it should return this
3674                                  * error and no data.  Retry with the 12
3675                                  * byte command.
3676                                  */
3677                                 if (use_12byte == 0) {
3678                                         get_length = 1;
3679                                         use_12byte = 1;
3680                                         goto retry_12byte;
3681                                 }
3682                                 dlist_length = returned_length + hdr_size;
3683                         } else {
3684                                 /*
3685                                  * If we got a SCSI error and no valid length,
3686                                  * just use the 10 byte maximum.  The 12
3687                                  * byte maximum is too large.
3688                                  */
3689                                 if (returned_length == 0)
3690                                         dlist_length = SRDD10_MAX_LENGTH;
3691                                 else {
3692                                         if ((use_12byte == 0)
3693                                          && (returned_length >=
3694                                              max_possible_size)) {
3695                                                 get_length = 1;
3696                                                 use_12byte = 1;
3697                                                 goto retry_12byte;
3698                                         }
3699                                         dlist_length = returned_length +
3700                                             hdr_size;
3701                                 }
3702                         }
3703                 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3704                             CAM_REQ_CMP){
3705                         error = 1;
3706                         warnx("Error reading defect header");
3707                         if (arglist & CAM_ARG_VERBOSE)
3708                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3709                                                 CAM_EPF_ALL, stderr);
3710                         goto defect_bailout;
3711                 } else {
3712                         if ((use_12byte == 0)
3713                          && (returned_length >= max_possible_size)) {
3714                                 get_length = 1;
3715                                 use_12byte = 1;
3716                                 goto retry_12byte;
3717                         }
3718                         dlist_length = returned_length + hdr_size;
3719                 }
3720                 if (summary != 0) {
3721                         fprintf(stdout, "%u", num_returned);
3722                         if (quiet == 0) {
3723                                 fprintf(stdout, " defect%s",
3724                                         (num_returned != 1) ? "s" : "");
3725                         }
3726                         fprintf(stdout, "\n");
3727
3728                         goto defect_bailout;
3729                 }
3730
3731                 /*
3732                  * We always limit the list length to the 10-byte maximum
3733                  * length (0xffff).  The reason is that some controllers
3734                  * can't handle larger I/Os, and we can transfer the entire
3735                  * 10 byte list in one shot.  For drives that support the 12
3736                  * byte read defects command, we'll step through the list
3737                  * by specifying a starting offset.  For drives that don't
3738                  * support the 12 byte command's starting offset, we'll
3739                  * just display the first 64K.
3740                  */
3741                 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3742
3743                 goto retry;
3744         }
3745
3746
3747         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3748          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3749          && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3750                 struct scsi_sense_data *sense;
3751                 int error_code, sense_key, asc, ascq;
3752
3753                 sense = &ccb->csio.sense_data;
3754                 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3755                     ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3756                     &ascq, /*show_errors*/ 1);
3757
3758                 /*
3759                  * According to the SCSI spec, if the disk doesn't support
3760                  * the requested format, it will generally return a sense
3761                  * key of RECOVERED ERROR, and an additional sense code
3762                  * of "DEFECT LIST NOT FOUND".  HGST drives also return
3763                  * Primary/Grown defect list not found errors.  So just
3764                  * check for an ASC of 0x1c.
3765                  */
3766                 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3767                  && (asc == 0x1c)) {
3768                         const char *format_str;
3769
3770                         format_str = scsi_nv_to_str(defect_list_type_map,
3771                             sizeof(defect_list_type_map) /
3772                             sizeof(defect_list_type_map[0]),
3773                             list_format & SRDD10_DLIST_FORMAT_MASK);
3774                         warnx("requested defect format %s not available",
3775                             format_str ? format_str : "unknown");
3776
3777                         format_str = scsi_nv_to_str(defect_list_type_map,
3778                             sizeof(defect_list_type_map) /
3779                             sizeof(defect_list_type_map[0]), returned_type);
3780                         if (format_str != NULL) {
3781                                 warnx("Device returned %s format",
3782                                     format_str);
3783                         } else {
3784                                 error = 1;
3785                                 warnx("Device returned unknown defect"
3786                                      " data format %#x", returned_type);
3787                                 goto defect_bailout;
3788                         }
3789                 } else {
3790                         error = 1;
3791                         warnx("Error returned from read defect data command");
3792                         if (arglist & CAM_ARG_VERBOSE)
3793                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3794                                                 CAM_EPF_ALL, stderr);
3795                         goto defect_bailout;
3796                 }
3797         } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3798                 error = 1;
3799                 warnx("Error returned from read defect data command");
3800                 if (arglist & CAM_ARG_VERBOSE)
3801                         cam_error_print(device, ccb, CAM_ESF_ALL,
3802                                         CAM_EPF_ALL, stderr);
3803                 goto defect_bailout;
3804         }
3805
3806         if (first_pass != 0) {
3807                 fprintf(stderr, "Got %d defect", num_returned);
3808
3809                 if ((lists_specified == 0) || (num_returned == 0)) {
3810                         fprintf(stderr, "s.\n");
3811                         goto defect_bailout;
3812                 } else if (num_returned == 1)
3813                         fprintf(stderr, ":\n");
3814                 else
3815                         fprintf(stderr, "s:\n");
3816
3817                 first_pass = 0;
3818         }
3819
3820         /*
3821          * XXX KDM  I should probably clean up the printout format for the
3822          * disk defects.
3823          */
3824         switch (returned_type) {
3825         case SRDD10_PHYSICAL_SECTOR_FORMAT:
3826         case SRDD10_EXT_PHYS_FORMAT:
3827         {
3828                 struct scsi_defect_desc_phys_sector *dlist;
3829
3830                 dlist = (struct scsi_defect_desc_phys_sector *)
3831                         (defect_list + hdr_size);
3832
3833                 for (i = 0; i < num_valid; i++) {
3834                         uint32_t sector;
3835
3836                         sector = scsi_4btoul(dlist[i].sector);
3837                         if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
3838                                 mads = (sector & SDD_EXT_PHYS_MADS) ?
3839                                        0 : 1;
3840                                 sector &= ~SDD_EXT_PHYS_FLAG_MASK;
3841                         }
3842                         if (hex_format == 0)
3843                                 fprintf(stdout, "%d:%d:%d%s",
3844                                         scsi_3btoul(dlist[i].cylinder),
3845                                         dlist[i].head,
3846                                         scsi_4btoul(dlist[i].sector),
3847                                         mads ? " - " : "\n");
3848                         else
3849                                 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3850                                         scsi_3btoul(dlist[i].cylinder),
3851                                         dlist[i].head,
3852                                         scsi_4btoul(dlist[i].sector),
3853                                         mads ? " - " : "\n");
3854                         mads = 0;
3855                 }
3856                 if (num_valid < num_returned) {
3857                         starting_offset += num_valid;
3858                         goto next_batch;
3859                 }
3860                 break;
3861         }
3862         case SRDD10_BYTES_FROM_INDEX_FORMAT:
3863         case SRDD10_EXT_BFI_FORMAT:
3864         {
3865                 struct scsi_defect_desc_bytes_from_index *dlist;
3866
3867                 dlist = (struct scsi_defect_desc_bytes_from_index *)
3868                         (defect_list + hdr_size);
3869
3870                 for (i = 0; i < num_valid; i++) {
3871                         uint32_t bfi;
3872
3873                         bfi = scsi_4btoul(dlist[i].bytes_from_index);
3874                         if (returned_type == SRDD10_EXT_BFI_FORMAT) {
3875                                 mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
3876                                 bfi &= ~SDD_EXT_BFI_FLAG_MASK;
3877                         }
3878                         if (hex_format == 0)
3879                                 fprintf(stdout, "%d:%d:%d%s",
3880                                         scsi_3btoul(dlist[i].cylinder),
3881                                         dlist[i].head,
3882                                         scsi_4btoul(dlist[i].bytes_from_index),
3883                                         mads ? " - " : "\n");
3884                         else
3885                                 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3886                                         scsi_3btoul(dlist[i].cylinder),
3887                                         dlist[i].head,
3888                                         scsi_4btoul(dlist[i].bytes_from_index),
3889                                         mads ? " - " : "\n");
3890
3891                         mads = 0;
3892                 }
3893                 if (num_valid < num_returned) {
3894                         starting_offset += num_valid;
3895                         goto next_batch;
3896                 }
3897                 break;
3898         }
3899         case SRDDH10_BLOCK_FORMAT:
3900         {
3901                 struct scsi_defect_desc_block *dlist;
3902
3903                 dlist = (struct scsi_defect_desc_block *)
3904                         (defect_list + hdr_size);
3905
3906                 for (i = 0; i < num_valid; i++) {
3907                         if (hex_format == 0)
3908                                 fprintf(stdout, "%u\n",
3909                                         scsi_4btoul(dlist[i].address));
3910                         else
3911                                 fprintf(stdout, "0x%x\n",
3912                                         scsi_4btoul(dlist[i].address));
3913                 }
3914
3915                 if (num_valid < num_returned) {
3916                         starting_offset += num_valid;
3917                         goto next_batch;
3918                 }
3919
3920                 break;
3921         }
3922         case SRDD10_LONG_BLOCK_FORMAT:
3923         {
3924                 struct scsi_defect_desc_long_block *dlist;
3925
3926                 dlist = (struct scsi_defect_desc_long_block *)
3927                         (defect_list + hdr_size);
3928
3929                 for (i = 0; i < num_valid; i++) {
3930                         if (hex_format == 0)
3931                                 fprintf(stdout, "%ju\n",
3932                                         (uintmax_t)scsi_8btou64(
3933                                         dlist[i].address));
3934                         else
3935                                 fprintf(stdout, "0x%jx\n",
3936                                         (uintmax_t)scsi_8btou64(
3937                                         dlist[i].address));
3938                 }
3939
3940                 if (num_valid < num_returned) {
3941                         starting_offset += num_valid;
3942                         goto next_batch;
3943                 }
3944                 break;
3945         }
3946         default:
3947                 fprintf(stderr, "Unknown defect format 0x%x\n",
3948                         returned_type);
3949                 error = 1;
3950                 break;
3951         }
3952 defect_bailout:
3953
3954         if (defect_list != NULL)
3955                 free(defect_list);
3956
3957         if (ccb != NULL)
3958                 cam_freeccb(ccb);
3959
3960         return(error);
3961 }
3962 #endif /* MINIMALISTIC */
3963
3964 #if 0
3965 void
3966 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3967 {
3968         union ccb *ccb;
3969
3970         ccb = cam_getccb(device);
3971
3972         cam_freeccb(ccb);
3973 }
3974 #endif
3975
3976 #ifndef MINIMALISTIC
3977 void
3978 mode_sense(struct cam_device *device, int mode_page, int page_control,
3979            int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3980 {
3981         union ccb *ccb;
3982         int retval;
3983
3984         ccb = cam_getccb(device);
3985
3986         if (ccb == NULL)
3987                 errx(1, "mode_sense: couldn't allocate CCB");
3988
3989         bzero(&(&ccb->ccb_h)[1],
3990               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3991
3992         scsi_mode_sense(&ccb->csio,
3993                         /* retries */ retry_count,
3994                         /* cbfcnp */ NULL,
3995                         /* tag_action */ MSG_SIMPLE_Q_TAG,
3996                         /* dbd */ dbd,
3997                         /* page_code */ page_control << 6,
3998                         /* page */ mode_page,
3999                         /* param_buf */ data,
4000                         /* param_len */ datalen,
4001                         /* sense_len */ SSD_FULL_SIZE,
4002                         /* timeout */ timeout ? timeout : 5000);
4003
4004         if (arglist & CAM_ARG_ERR_RECOVER)
4005                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4006
4007         /* Disable freezing the device queue */
4008         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4009
4010         if (((retval = cam_send_ccb(device, ccb)) < 0)
4011          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4012                 if (arglist & CAM_ARG_VERBOSE) {
4013                         cam_error_print(device, ccb, CAM_ESF_ALL,
4014                                         CAM_EPF_ALL, stderr);
4015                 }
4016                 cam_freeccb(ccb);
4017                 cam_close_device(device);
4018                 if (retval < 0)
4019                         err(1, "error sending mode sense command");
4020                 else
4021                         errx(1, "error sending mode sense command");
4022         }
4023
4024         cam_freeccb(ccb);
4025 }
4026
4027 void
4028 mode_select(struct cam_device *device, int save_pages, int retry_count,
4029            int timeout, u_int8_t *data, int datalen)
4030 {
4031         union ccb *ccb;
4032         int retval;
4033
4034         ccb = cam_getccb(device);
4035
4036         if (ccb == NULL)
4037                 errx(1, "mode_select: couldn't allocate CCB");
4038
4039         bzero(&(&ccb->ccb_h)[1],
4040               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4041
4042         scsi_mode_select(&ccb->csio,
4043                          /* retries */ retry_count,
4044                          /* cbfcnp */ NULL,
4045                          /* tag_action */ MSG_SIMPLE_Q_TAG,
4046                          /* scsi_page_fmt */ 1,
4047                          /* save_pages */ save_pages,
4048                          /* param_buf */ data,
4049                          /* param_len */ datalen,
4050                          /* sense_len */ SSD_FULL_SIZE,
4051                          /* timeout */ timeout ? timeout : 5000);
4052
4053         if (arglist & CAM_ARG_ERR_RECOVER)
4054                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4055
4056         /* Disable freezing the device queue */
4057         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4058
4059         if (((retval = cam_send_ccb(device, ccb)) < 0)
4060          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4061                 if (arglist & CAM_ARG_VERBOSE) {
4062                         cam_error_print(device, ccb, CAM_ESF_ALL,
4063                                         CAM_EPF_ALL, stderr);
4064                 }
4065                 cam_freeccb(ccb);
4066                 cam_close_device(device);
4067
4068                 if (retval < 0)
4069                         err(1, "error sending mode select command");
4070                 else
4071                         errx(1, "error sending mode select command");
4072
4073         }
4074
4075         cam_freeccb(ccb);
4076 }
4077
4078 void
4079 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4080          int retry_count, int timeout)
4081 {
4082         int c, mode_page = -1, page_control = 0;
4083         int binary = 0, list = 0;
4084
4085         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4086                 switch(c) {
4087                 case 'b':
4088                         binary = 1;
4089                         break;
4090                 case 'd':
4091                         arglist |= CAM_ARG_DBD;
4092                         break;
4093                 case 'e':
4094                         arglist |= CAM_ARG_MODE_EDIT;
4095                         break;
4096                 case 'l':
4097                         list = 1;
4098                         break;
4099                 case 'm':
4100                         mode_page = strtol(optarg, NULL, 0);
4101                         if (mode_page < 0)
4102                                 errx(1, "invalid mode page %d", mode_page);
4103                         break;
4104                 case 'P':
4105                         page_control = strtol(optarg, NULL, 0);
4106                         if ((page_control < 0) || (page_control > 3))
4107                                 errx(1, "invalid page control field %d",
4108                                      page_control);
4109                         arglist |= CAM_ARG_PAGE_CNTL;
4110                         break;
4111                 default:
4112                         break;
4113                 }
4114         }
4115
4116         if (mode_page == -1 && list == 0)
4117                 errx(1, "you must specify a mode page!");
4118
4119         if (list) {
4120                 mode_list(device, page_control, arglist & CAM_ARG_DBD,
4121                     retry_count, timeout);
4122         } else {
4123                 mode_edit(device, mode_page, page_control,
4124                     arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
4125                     retry_count, timeout);
4126         }
4127 }
4128
4129 static int
4130 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4131         int retry_count, int timeout)
4132 {
4133         union ccb *ccb;
4134         u_int32_t flags = CAM_DIR_NONE;
4135         u_int8_t *data_ptr = NULL;
4136         u_int8_t cdb[20];
4137         u_int8_t atacmd[12];
4138         struct get_hook hook;
4139         int c, data_bytes = 0;
4140         int cdb_len = 0;
4141         int atacmd_len = 0;
4142         int dmacmd = 0;
4143         int fpdmacmd = 0;
4144         int need_res = 0;
4145         char *datastr = NULL, *tstr, *resstr = NULL;
4146         int error = 0;
4147         int fd_data = 0, fd_res = 0;
4148         int retval;
4149
4150         ccb = cam_getccb(device);
4151
4152         if (ccb == NULL) {
4153                 warnx("scsicmd: error allocating ccb");
4154                 return(1);
4155         }
4156
4157         bzero(&(&ccb->ccb_h)[1],
4158               sizeof(union ccb) - sizeof(struct ccb_hdr));
4159
4160         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4161                 switch(c) {
4162                 case 'a':
4163                         tstr = optarg;
4164                         while (isspace(*tstr) && (*tstr != '\0'))
4165                                 tstr++;
4166                         hook.argc = argc - optind;
4167                         hook.argv = argv + optind;
4168                         hook.got = 0;
4169                         atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4170                                                     iget, &hook);
4171                         /*
4172                          * Increment optind by the number of arguments the
4173                          * encoding routine processed.  After each call to
4174                          * getopt(3), optind points to the argument that
4175                          * getopt should process _next_.  In this case,
4176                          * that means it points to the first command string
4177                          * argument, if there is one.  Once we increment
4178                          * this, it should point to either the next command
4179                          * line argument, or it should be past the end of
4180                          * the list.
4181                          */
4182                         optind += hook.got;
4183                         break;
4184                 case 'c':
4185                         tstr = optarg;
4186                         while (isspace(*tstr) && (*tstr != '\0'))
4187                                 tstr++;
4188                         hook.argc = argc - optind;
4189                         hook.argv = argv + optind;
4190                         hook.got = 0;
4191                         cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4192                                                     iget, &hook);
4193                         /*
4194                          * Increment optind by the number of arguments the
4195                          * encoding routine processed.  After each call to
4196                          * getopt(3), optind points to the argument that
4197                          * getopt should process _next_.  In this case,
4198                          * that means it points to the first command string
4199                          * argument, if there is one.  Once we increment
4200                          * this, it should point to either the next command
4201                          * line argument, or it should be past the end of
4202                          * the list.
4203                          */
4204                         optind += hook.got;
4205                         break;
4206                 case 'd':
4207                         dmacmd = 1;
4208                         break;
4209                 case 'f':
4210                         fpdmacmd = 1;
4211                         break;
4212                 case 'i':
4213                         if (arglist & CAM_ARG_CMD_OUT) {
4214                                 warnx("command must either be "
4215                                       "read or write, not both");
4216                                 error = 1;
4217                                 goto scsicmd_bailout;
4218                         }
4219                         arglist |= CAM_ARG_CMD_IN;
4220                         flags = CAM_DIR_IN;
4221                         data_bytes = strtol(optarg, NULL, 0);
4222                         if (data_bytes <= 0) {
4223                                 warnx("invalid number of input bytes %d",
4224                                       data_bytes);
4225                                 error = 1;
4226                                 goto scsicmd_bailout;
4227                         }
4228                         hook.argc = argc - optind;
4229                         hook.argv = argv + optind;
4230                         hook.got = 0;
4231                         optind++;
4232                         datastr = cget(&hook, NULL);
4233                         /*
4234                          * If the user supplied "-" instead of a format, he
4235                          * wants the data to be written to stdout.
4236                          */
4237                         if ((datastr != NULL)
4238                          && (datastr[0] == '-'))
4239                                 fd_data = 1;
4240
4241                         data_ptr = (u_int8_t *)malloc(data_bytes);
4242                         if (data_ptr == NULL) {
4243                                 warnx("can't malloc memory for data_ptr");
4244                                 error = 1;
4245                                 goto scsicmd_bailout;
4246                         }
4247                         break;
4248                 case 'o':
4249                         if (arglist & CAM_ARG_CMD_IN) {
4250                                 warnx("command must either be "
4251                                       "read or write, not both");
4252                                 error = 1;
4253                                 goto scsicmd_bailout;
4254                         }
4255                         arglist |= CAM_ARG_CMD_OUT;
4256                         flags = CAM_DIR_OUT;
4257                         data_bytes = strtol(optarg, NULL, 0);
4258                         if (data_bytes <= 0) {
4259                                 warnx("invalid number of output bytes %d",
4260                                       data_bytes);
4261                                 error = 1;
4262                                 goto scsicmd_bailout;
4263                         }
4264                         hook.argc = argc - optind;
4265                         hook.argv = argv + optind;
4266                         hook.got = 0;
4267                         datastr = cget(&hook, NULL);
4268                         data_ptr = (u_int8_t *)malloc(data_bytes);
4269                         if (data_ptr == NULL) {
4270                                 warnx("can't malloc memory for data_ptr");
4271                                 error = 1;
4272                                 goto scsicmd_bailout;
4273                         }
4274                         bzero(data_ptr, data_bytes);
4275                         /*
4276                          * If the user supplied "-" instead of a format, he
4277                          * wants the data to be read from stdin.
4278                          */
4279                         if ((datastr != NULL)
4280                          && (datastr[0] == '-'))
4281                                 fd_data = 1;
4282                         else
4283                                 buff_encode_visit(data_ptr, data_bytes, datastr,
4284                                                   iget, &hook);
4285                         optind += hook.got;
4286                         break;
4287                 case 'r':
4288                         need_res = 1;
4289                         hook.argc = argc - optind;
4290                         hook.argv = argv + optind;
4291                         hook.got = 0;
4292                         resstr = cget(&hook, NULL);
4293                         if ((resstr != NULL) && (resstr[0] == '-'))
4294                                 fd_res = 1;
4295                         optind += hook.got;
4296                         break;
4297                 default:
4298                         break;
4299                 }
4300         }
4301
4302         /*
4303          * If fd_data is set, and we're writing to the device, we need to
4304          * read the data the user wants written from stdin.
4305          */
4306         if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4307                 ssize_t amt_read;
4308                 int amt_to_read = data_bytes;
4309                 u_int8_t *buf_ptr = data_ptr;
4310
4311                 for (amt_read = 0; amt_to_read > 0;
4312                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4313                         if (amt_read == -1) {
4314                                 warn("error reading data from stdin");
4315                                 error = 1;
4316                                 goto scsicmd_bailout;
4317                         }
4318                         amt_to_read -= amt_read;
4319                         buf_ptr += amt_read;
4320                 }
4321         }
4322
4323         if (arglist & CAM_ARG_ERR_RECOVER)
4324                 flags |= CAM_PASS_ERR_RECOVER;
4325
4326         /* Disable freezing the device queue */
4327         flags |= CAM_DEV_QFRZDIS;
4328
4329         if (cdb_len) {
4330                 /*
4331                  * This is taken from the SCSI-3 draft spec.
4332                  * (T10/1157D revision 0.3)
4333                  * The top 3 bits of an opcode are the group code.
4334                  * The next 5 bits are the command code.
4335                  * Group 0:  six byte commands
4336                  * Group 1:  ten byte commands
4337                  * Group 2:  ten byte commands
4338                  * Group 3:  reserved
4339                  * Group 4:  sixteen byte commands
4340                  * Group 5:  twelve byte commands
4341                  * Group 6:  vendor specific
4342                  * Group 7:  vendor specific
4343                  */
4344                 switch((cdb[0] >> 5) & 0x7) {
4345                         case 0:
4346                                 cdb_len = 6;
4347                                 break;
4348                         case 1:
4349                         case 2:
4350                                 cdb_len = 10;
4351                                 break;
4352                         case 3:
4353                         case 6:
4354                         case 7:
4355                                 /* computed by buff_encode_visit */
4356                                 break;
4357                         case 4:
4358                                 cdb_len = 16;
4359                                 break;
4360                         case 5:
4361                                 cdb_len = 12;
4362                                 break;
4363                 }
4364
4365                 /*
4366                  * We should probably use csio_build_visit or something like that
4367                  * here, but it's easier to encode arguments as you go.  The
4368                  * alternative would be skipping the CDB argument and then encoding
4369                  * it here, since we've got the data buffer argument by now.
4370                  */
4371                 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4372
4373                 cam_fill_csio(&ccb->csio,
4374                       /*retries*/ retry_count,
4375                       /*cbfcnp*/ NULL,
4376                       /*flags*/ flags,
4377                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
4378                       /*data_ptr*/ data_ptr,
4379                       /*dxfer_len*/ data_bytes,
4380                       /*sense_len*/ SSD_FULL_SIZE,
4381                       /*cdb_len*/ cdb_len,
4382                       /*timeout*/ timeout ? timeout : 5000);
4383         } else {
4384                 atacmd_len = 12;
4385                 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4386                 if (need_res)
4387                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4388                 if (dmacmd)
4389                         ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4390                 if (fpdmacmd)
4391                         ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4392
4393                 cam_fill_ataio(&ccb->ataio,
4394                       /*retries*/ retry_count,
4395                       /*cbfcnp*/ NULL,
4396                       /*flags*/ flags,
4397                       /*tag_action*/ 0,
4398                       /*data_ptr*/ data_ptr,
4399                       /*dxfer_len*/ data_bytes,
4400                       /*timeout*/ timeout ? timeout : 5000);
4401         }
4402
4403         if (((retval = cam_send_ccb(device, ccb)) < 0)
4404          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4405                 const char warnstr[] = "error sending command";
4406
4407                 if (retval < 0)
4408                         warn(warnstr);
4409                 else
4410                         warnx(warnstr);
4411
4412                 if (arglist & CAM_ARG_VERBOSE) {
4413                         cam_error_print(device, ccb, CAM_ESF_ALL,
4414                                         CAM_EPF_ALL, stderr);
4415                 }
4416
4417                 error = 1;
4418                 goto scsicmd_bailout;
4419         }
4420
4421         if (atacmd_len && need_res) {
4422                 if (fd_res == 0) {
4423                         buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4424                                           arg_put, NULL);
4425                         fprintf(stdout, "\n");
4426                 } else {
4427                         fprintf(stdout,
4428                             "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4429                             ccb->ataio.res.status,
4430                             ccb->ataio.res.error,
4431                             ccb->ataio.res.lba_low,
4432                             ccb->ataio.res.lba_mid,
4433                             ccb->ataio.res.lba_high,
4434                             ccb->ataio.res.device,
4435                             ccb->ataio.res.lba_low_exp,
4436                             ccb->ataio.res.lba_mid_exp,
4437                             ccb->ataio.res.lba_high_exp,
4438                             ccb->ataio.res.sector_count,
4439                             ccb->ataio.res.sector_count_exp);
4440                         fflush(stdout);
4441                 }
4442         }
4443
4444         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4445          && (arglist & CAM_ARG_CMD_IN)
4446          && (data_bytes > 0)) {
4447                 if (fd_data == 0) {
4448                         buff_decode_visit(data_ptr, data_bytes, datastr,
4449                                           arg_put, NULL);
4450                         fprintf(stdout, "\n");
4451                 } else {
4452                         ssize_t amt_written;
4453                         int amt_to_write = data_bytes;
4454                         u_int8_t *buf_ptr = data_ptr;
4455
4456                         for (amt_written = 0; (amt_to_write > 0) &&
4457                              (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4458                                 amt_to_write -= amt_written;
4459                                 buf_ptr += amt_written;
4460                         }
4461                         if (amt_written == -1) {
4462                                 warn("error writing data to stdout");
4463                                 error = 1;
4464                                 goto scsicmd_bailout;
4465                         } else if ((amt_written == 0)
4466                                 && (amt_to_write > 0)) {
4467                                 warnx("only wrote %u bytes out of %u",
4468                                       data_bytes - amt_to_write, data_bytes);
4469                         }
4470                 }
4471         }
4472
4473 scsicmd_bailout:
4474
4475         if ((data_bytes > 0) && (data_ptr != NULL))
4476                 free(data_ptr);
4477
4478         cam_freeccb(ccb);
4479
4480         return(error);
4481 }
4482
4483 static int
4484 camdebug(int argc, char **argv, char *combinedopt)
4485 {
4486         int c, fd;
4487         path_id_t bus = CAM_BUS_WILDCARD;
4488         target_id_t target = CAM_TARGET_WILDCARD;
4489         lun_id_t lun = CAM_LUN_WILDCARD;
4490         char *tstr, *tmpstr = NULL;
4491         union ccb ccb;
4492         int error = 0;
4493
4494         bzero(&ccb, sizeof(union ccb));
4495
4496         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4497                 switch(c) {
4498                 case 'I':
4499                         arglist |= CAM_ARG_DEBUG_INFO;
4500                         ccb.cdbg.flags |= CAM_DEBUG_INFO;
4501                         break;
4502                 case 'P':
4503                         arglist |= CAM_ARG_DEBUG_PERIPH;
4504                         ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4505                         break;
4506                 case 'S':
4507                         arglist |= CAM_ARG_DEBUG_SUBTRACE;
4508                         ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4509                         break;
4510                 case 'T':
4511                         arglist |= CAM_ARG_DEBUG_TRACE;
4512                         ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4513                         break;
4514                 case 'X':
4515                         arglist |= CAM_ARG_DEBUG_XPT;
4516                         ccb.cdbg.flags |= CAM_DEBUG_XPT;
4517                         break;
4518                 case 'c':
4519                         arglist |= CAM_ARG_DEBUG_CDB;
4520                         ccb.cdbg.flags |= CAM_DEBUG_CDB;
4521                         break;
4522                 case 'p':
4523                         arglist |= CAM_ARG_DEBUG_PROBE;
4524                         ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4525                         break;
4526                 default:
4527                         break;
4528                 }
4529         }
4530
4531         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4532                 warnx("error opening transport layer device %s", XPT_DEVICE);
4533                 warn("%s", XPT_DEVICE);
4534                 return(1);
4535         }
4536         argc -= optind;
4537         argv += optind;
4538
4539         if (argc <= 0) {
4540                 warnx("you must specify \"off\", \"all\" or a bus,");
4541                 warnx("bus:target, or bus:target:lun");
4542                 close(fd);
4543                 return(1);
4544         }
4545
4546         tstr = *argv;
4547
4548         while (isspace(*tstr) && (*tstr != '\0'))
4549                 tstr++;
4550
4551         if (strncmp(tstr, "off", 3) == 0) {
4552                 ccb.cdbg.flags = CAM_DEBUG_NONE;
4553                 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4554                              CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4555                              CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4556         } else if (strncmp(tstr, "all", 3) != 0) {
4557                 tmpstr = (char *)strtok(tstr, ":");
4558                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4559                         bus = strtol(tmpstr, NULL, 0);
4560                         arglist |= CAM_ARG_BUS;
4561                         tmpstr = (char *)strtok(NULL, ":");
4562                         if ((tmpstr != NULL) && (*tmpstr != '\0')){
4563                                 target = strtol(tmpstr, NULL, 0);
4564                                 arglist |= CAM_ARG_TARGET;
4565                                 tmpstr = (char *)strtok(NULL, ":");
4566                                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4567                                         lun = strtol(tmpstr, NULL, 0);
4568                                         arglist |= CAM_ARG_LUN;
4569                                 }
4570                         }
4571                 } else {
4572                         error = 1;
4573                         warnx("you must specify \"all\", \"off\", or a bus,");
4574                         warnx("bus:target, or bus:target:lun to debug");
4575                 }
4576         }
4577
4578         if (error == 0) {
4579
4580                 ccb.ccb_h.func_code = XPT_DEBUG;
4581                 ccb.ccb_h.path_id = bus;
4582                 ccb.ccb_h.target_id = target;
4583                 ccb.ccb_h.target_lun = lun;
4584
4585                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4586                         warn("CAMIOCOMMAND ioctl failed");
4587                         error = 1;
4588                 }
4589
4590                 if (error == 0) {
4591                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4592                              CAM_FUNC_NOTAVAIL) {
4593                                 warnx("CAM debugging not available");
4594                                 warnx("you need to put options CAMDEBUG in"
4595                                       " your kernel config file!");
4596                                 error = 1;
4597                         } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4598                                     CAM_REQ_CMP) {
4599                                 warnx("XPT_DEBUG CCB failed with status %#x",
4600                                       ccb.ccb_h.status);
4601                                 error = 1;
4602                         } else {
4603                                 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4604                                         fprintf(stderr,
4605                                                 "Debugging turned off\n");
4606                                 } else {
4607                                         fprintf(stderr,
4608                                                 "Debugging enabled for "
4609                                                 "%d:%d:%jx\n",
4610                                                 bus, target, (uintmax_t)lun);
4611                                 }
4612                         }
4613                 }
4614                 close(fd);
4615         }
4616
4617         return(error);
4618 }
4619
4620 static int
4621 tagcontrol(struct cam_device *device, int argc, char **argv,
4622            char *combinedopt)
4623 {
4624         int c;
4625         union ccb *ccb;
4626         int numtags = -1;
4627         int retval = 0;
4628         int quiet = 0;
4629         char pathstr[1024];
4630
4631         ccb = cam_getccb(device);
4632
4633         if (ccb == NULL) {
4634                 warnx("tagcontrol: error allocating ccb");
4635                 return(1);
4636         }
4637
4638         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4639                 switch(c) {
4640                 case 'N':
4641                         numtags = strtol(optarg, NULL, 0);
4642                         if (numtags < 0) {
4643                                 warnx("tag count %d is < 0", numtags);
4644                                 retval = 1;
4645                                 goto tagcontrol_bailout;
4646                         }
4647                         break;
4648                 case 'q':
4649                         quiet++;
4650                         break;
4651                 default:
4652                         break;
4653                 }
4654         }
4655
4656         cam_path_string(device, pathstr, sizeof(pathstr));
4657
4658         if (numtags >= 0) {
4659                 bzero(&(&ccb->ccb_h)[1],
4660                       sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4661                 ccb->ccb_h.func_code = XPT_REL_SIMQ;
4662                 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4663                 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4664                 ccb->crs.openings = numtags;
4665
4666
4667                 if (cam_send_ccb(device, ccb) < 0) {
4668                         perror("error sending XPT_REL_SIMQ CCB");
4669                         retval = 1;
4670                         goto tagcontrol_bailout;
4671                 }
4672
4673                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4674                         warnx("XPT_REL_SIMQ CCB failed");
4675                         cam_error_print(device, ccb, CAM_ESF_ALL,
4676                                         CAM_EPF_ALL, stderr);
4677                         retval = 1;
4678                         goto tagcontrol_bailout;
4679                 }
4680
4681
4682                 if (quiet == 0)
4683                         fprintf(stdout, "%stagged openings now %d\n",
4684                                 pathstr, ccb->crs.openings);
4685         }
4686
4687         bzero(&(&ccb->ccb_h)[1],
4688               sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4689
4690         ccb->ccb_h.func_code = XPT_GDEV_STATS;
4691
4692         if (cam_send_ccb(device, ccb) < 0) {
4693                 perror("error sending XPT_GDEV_STATS CCB");
4694                 retval = 1;
4695                 goto tagcontrol_bailout;
4696         }
4697
4698         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4699                 warnx("XPT_GDEV_STATS CCB failed");
4700                 cam_error_print(device, ccb, CAM_ESF_ALL,
4701                                 CAM_EPF_ALL, stderr);
4702                 retval = 1;
4703                 goto tagcontrol_bailout;
4704         }
4705
4706         if (arglist & CAM_ARG_VERBOSE) {
4707                 fprintf(stdout, "%s", pathstr);
4708                 fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4709                 fprintf(stdout, "%s", pathstr);
4710                 fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4711                 fprintf(stdout, "%s", pathstr);
4712                 fprintf(stdout, "allocated     %d\n", ccb->cgds.allocated);
4713                 fprintf(stdout, "%s", pathstr);
4714                 fprintf(stdout, "queued        %d\n", ccb->cgds.queued);
4715                 fprintf(stdout, "%s", pathstr);
4716                 fprintf(stdout, "held          %d\n", ccb->cgds.held);
4717                 fprintf(stdout, "%s", pathstr);
4718                 fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4719                 fprintf(stdout, "%s", pathstr);
4720                 fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4721         } else {
4722                 if (quiet == 0) {
4723                         fprintf(stdout, "%s", pathstr);
4724                         fprintf(stdout, "device openings: ");
4725                 }
4726                 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4727                         ccb->cgds.dev_active);
4728         }
4729
4730 tagcontrol_bailout:
4731
4732         cam_freeccb(ccb);
4733         return(retval);
4734 }
4735
4736 static void
4737 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4738 {
4739         char pathstr[1024];
4740
4741         cam_path_string(device, pathstr, sizeof(pathstr));
4742
4743         if (cts->transport == XPORT_SPI) {
4744                 struct ccb_trans_settings_spi *spi =
4745                     &cts->xport_specific.spi;
4746
4747                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4748
4749                         fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4750                                 spi->sync_period);
4751
4752                         if (spi->sync_offset != 0) {
4753                                 u_int freq;
4754
4755                                 freq = scsi_calc_syncsrate(spi->sync_period);
4756                                 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4757                                         pathstr, freq / 1000, freq % 1000);
4758                         }
4759                 }
4760
4761                 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4762                         fprintf(stdout, "%soffset: %d\n", pathstr,
4763                             spi->sync_offset);
4764                 }
4765
4766                 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4767                         fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4768                                 (0x01 << spi->bus_width) * 8);
4769                 }
4770
4771                 if (spi->valid & CTS_SPI_VALID_DISC) {
4772                         fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4773                                 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4774                                 "enabled" : "disabled");
4775                 }
4776         }
4777         if (cts->transport == XPORT_FC) {
4778                 struct ccb_trans_settings_fc *fc =
4779                     &cts->xport_specific.fc;
4780
4781                 if (fc->valid & CTS_FC_VALID_WWNN)
4782                         fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4783                             (long long) fc->wwnn);
4784                 if (fc->valid & CTS_FC_VALID_WWPN)
4785                         fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4786                             (long long) fc->wwpn);
4787                 if (fc->valid & CTS_FC_VALID_PORT)
4788                         fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4789                 if (fc->valid & CTS_FC_VALID_SPEED)
4790                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4791                             pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4792         }
4793         if (cts->transport == XPORT_SAS) {
4794                 struct ccb_trans_settings_sas *sas =
4795                     &cts->xport_specific.sas;
4796
4797                 if (sas->valid & CTS_SAS_VALID_SPEED)
4798                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4799                             pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4800         }
4801         if (cts->transport == XPORT_ATA) {
4802                 struct ccb_trans_settings_pata *pata =
4803                     &cts->xport_specific.ata;
4804
4805                 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4806                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4807                                 ata_mode2string(pata->mode));
4808                 }
4809                 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4810                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4811                                 pata->atapi);
4812                 }
4813                 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4814                         fprintf(stdout, "%sPIO transaction length: %d\n",
4815                                 pathstr, pata->bytecount);
4816                 }
4817         }
4818         if (cts->transport == XPORT_SATA) {
4819                 struct ccb_trans_settings_sata *sata =
4820                     &cts->xport_specific.sata;
4821
4822                 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4823                         fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4824                                 sata->revision);
4825                 }
4826                 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4827                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4828                                 ata_mode2string(sata->mode));
4829                 }
4830                 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4831                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4832                                 sata->atapi);
4833                 }
4834                 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4835                         fprintf(stdout, "%sPIO transaction length: %d\n",
4836                                 pathstr, sata->bytecount);
4837                 }
4838                 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4839                         fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4840                                 sata->pm_present);
4841                 }
4842                 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4843                         fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4844                                 sata->tags);
4845                 }
4846                 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4847                         fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4848                                 sata->caps);
4849                 }
4850         }
4851         if (cts->protocol == PROTO_ATA) {
4852                 struct ccb_trans_settings_ata *ata=
4853                     &cts->proto_specific.ata;
4854
4855                 if (ata->valid & CTS_ATA_VALID_TQ) {
4856                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4857                                 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4858                                 "enabled" : "disabled");
4859                 }
4860         }
4861         if (cts->protocol == PROTO_SCSI) {
4862                 struct ccb_trans_settings_scsi *scsi=
4863                     &cts->proto_specific.scsi;
4864
4865                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
4866                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4867                                 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4868                                 "enabled" : "disabled");
4869                 }
4870         }
4871
4872 }
4873
4874 /*
4875  * Get a path inquiry CCB for the specified device.
4876  */
4877 static int
4878 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4879 {
4880         union ccb *ccb;
4881         int retval = 0;
4882
4883         ccb = cam_getccb(device);
4884         if (ccb == NULL) {
4885                 warnx("get_cpi: couldn't allocate CCB");
4886                 return(1);
4887         }
4888         bzero(&(&ccb->ccb_h)[1],
4889               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4890         ccb->ccb_h.func_code = XPT_PATH_INQ;
4891         if (cam_send_ccb(device, ccb) < 0) {
4892                 warn("get_cpi: error sending Path Inquiry CCB");
4893                 if (arglist & CAM_ARG_VERBOSE)
4894                         cam_error_print(device, ccb, CAM_ESF_ALL,
4895                                         CAM_EPF_ALL, stderr);
4896                 retval = 1;
4897                 goto get_cpi_bailout;
4898         }
4899         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4900                 if (arglist & CAM_ARG_VERBOSE)
4901                         cam_error_print(device, ccb, CAM_ESF_ALL,
4902                                         CAM_EPF_ALL, stderr);
4903                 retval = 1;
4904                 goto get_cpi_bailout;
4905         }
4906         bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4907
4908 get_cpi_bailout:
4909         cam_freeccb(ccb);
4910         return(retval);
4911 }
4912
4913 /*
4914  * Get a get device CCB for the specified device.
4915  */
4916 static int
4917 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4918 {
4919         union ccb *ccb;
4920         int retval = 0;
4921
4922         ccb = cam_getccb(device);
4923         if (ccb == NULL) {
4924                 warnx("get_cgd: couldn't allocate CCB");
4925                 return(1);
4926         }
4927         bzero(&(&ccb->ccb_h)[1],
4928               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4929         ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4930         if (cam_send_ccb(device, ccb) < 0) {
4931                 warn("get_cgd: error sending Path Inquiry CCB");
4932                 if (arglist & CAM_ARG_VERBOSE)
4933                         cam_error_print(device, ccb, CAM_ESF_ALL,
4934                                         CAM_EPF_ALL, stderr);
4935                 retval = 1;
4936                 goto get_cgd_bailout;
4937         }
4938         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4939                 if (arglist & CAM_ARG_VERBOSE)
4940                         cam_error_print(device, ccb, CAM_ESF_ALL,
4941                                         CAM_EPF_ALL, stderr);
4942                 retval = 1;
4943                 goto get_cgd_bailout;
4944         }
4945         bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4946
4947 get_cgd_bailout:
4948         cam_freeccb(ccb);
4949         return(retval);
4950 }
4951
4952 /*
4953  * Returns 1 if the device has the VPD page, 0 if it does not, and -1 on an
4954  * error.
4955  */
4956 int
4957 dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count,
4958                  int timeout, int verbosemode)
4959 {
4960         union ccb *ccb = NULL;
4961         struct scsi_vpd_supported_page_list sup_pages;
4962         int i;
4963         int retval = 0;
4964
4965         ccb = cam_getccb(dev);
4966         if (ccb == NULL) {
4967                 warn("Unable to allocate CCB");
4968                 retval = -1;
4969                 goto bailout;
4970         }
4971         
4972         /* cam_getccb cleans up the header, caller has to zero the payload */
4973         bzero(&(&ccb->ccb_h)[1],
4974               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4975
4976         bzero(&sup_pages, sizeof(sup_pages));
4977
4978         scsi_inquiry(&ccb->csio,
4979                      /*retries*/ retry_count,
4980                      /*cbfcnp*/ NULL,
4981                      /* tag_action */ MSG_SIMPLE_Q_TAG,
4982                      /* inq_buf */ (u_int8_t *)&sup_pages,
4983                      /* inq_len */ sizeof(sup_pages),
4984                      /* evpd */ 1,
4985                      /* page_code */ SVPD_SUPPORTED_PAGE_LIST,
4986                      /* sense_len */ SSD_FULL_SIZE,
4987                      /* timeout */ timeout ? timeout : 5000);
4988
4989         /* Disable freezing the device queue */
4990         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4991
4992         if (retry_count != 0)
4993                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4994
4995         if (cam_send_ccb(dev, ccb) < 0) {
4996                 cam_freeccb(ccb);
4997                 ccb = NULL;
4998                 retval = -1;
4999                 goto bailout;
5000         }
5001
5002         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5003                 if (verbosemode != 0)
5004                         cam_error_print(dev, ccb, CAM_ESF_ALL,
5005                                         CAM_EPF_ALL, stderr);
5006                 retval = -1;
5007                 goto bailout;
5008         }
5009
5010         for (i = 0; i < sup_pages.length; i++) {
5011                 if (sup_pages.list[i] == page_id) {
5012                         retval = 1;
5013                         goto bailout;
5014                 }
5015         }
5016 bailout:
5017         if (ccb != NULL)
5018                 cam_freeccb(ccb);
5019         
5020         return (retval);
5021 }
5022
5023 /*
5024  * devtype is filled in with the type of device.
5025  * Returns 0 for success, non-zero for failure.
5026  */
5027 int
5028 get_device_type(struct cam_device *dev, int retry_count, int timeout,
5029                     int verbosemode, camcontrol_devtype *devtype)
5030 {
5031         struct ccb_getdev cgd;
5032         int retval = 0;
5033
5034         retval = get_cgd(dev, &cgd);
5035         if (retval != 0)
5036                 goto bailout;
5037
5038         switch (cgd.protocol) {
5039         case PROTO_SCSI:
5040                 break;
5041         case PROTO_ATA:
5042         case PROTO_ATAPI:
5043         case PROTO_SATAPM:
5044                 *devtype = CC_DT_ATA;
5045                 goto bailout;
5046                 break; /*NOTREACHED*/
5047         default:
5048                 *devtype = CC_DT_UNKNOWN;
5049                 goto bailout; 
5050                 break; /*NOTREACHED*/
5051         }
5052
5053         /*
5054          * Check for the ATA Information VPD page (0x89).  If this is an
5055          * ATA device behind a SCSI to ATA translation layer, this VPD page
5056          * should be present.
5057          *
5058          * If that VPD page isn't present, or we get an error back from the
5059          * INQUIRY command, we'll just treat it as a normal SCSI device.
5060          */
5061         retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5062                                   timeout, verbosemode);
5063         if (retval == 1)
5064                 *devtype = CC_DT_ATA_BEHIND_SCSI;
5065         else
5066                 *devtype = CC_DT_SCSI;
5067
5068         retval = 0;
5069
5070 bailout:
5071         return (retval);
5072 }
5073
5074 void
5075 build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5076     uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5077     uint16_t sector_count, uint64_t lba, uint8_t command, uint8_t *data_ptr,
5078     uint16_t dxfer_len, uint8_t sense_len, uint32_t timeout,
5079     int is48bit, camcontrol_devtype devtype)
5080 {
5081         if (devtype == CC_DT_ATA) {
5082                 cam_fill_ataio(&ccb->ataio,
5083                     /*retries*/ retry_count,
5084                     /*cbfcnp*/ NULL,
5085                     /*flags*/ flags,
5086                     /*tag_action*/ tag_action,
5087                     /*data_ptr*/ data_ptr,
5088                     /*dxfer_len*/ dxfer_len,
5089                     /*timeout*/ timeout);
5090                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5091                         ata_48bit_cmd(&ccb->ataio, command, features, lba,
5092                             sector_count);
5093                 else
5094                         ata_28bit_cmd(&ccb->ataio, command, features, lba,
5095                             sector_count);
5096         } else {
5097                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5098                         protocol |= AP_EXTEND;
5099
5100                 scsi_ata_pass_16(&ccb->csio,
5101                     /*retries*/ retry_count,
5102                     /*cbfcnp*/ NULL,
5103                     /*flags*/ flags,
5104                     /*tag_action*/ tag_action,
5105                     /*protocol*/ protocol,
5106                     /*ata_flags*/ ata_flags,
5107                     /*features*/ features,
5108                     /*sector_count*/ sector_count, 
5109                     /*lba*/ lba,
5110                     /*command*/ command,
5111                     /*control*/ 0,
5112                     /*data_ptr*/ data_ptr,
5113                     /*dxfer_len*/ dxfer_len,
5114                     /*sense_len*/ sense_len,
5115                     /*timeout*/ timeout);
5116         }
5117 }
5118
5119
5120 static void
5121 cpi_print(struct ccb_pathinq *cpi)
5122 {
5123         char adapter_str[1024];
5124         int i;
5125
5126         snprintf(adapter_str, sizeof(adapter_str),
5127                  "%s%d:", cpi->dev_name, cpi->unit_number);
5128
5129         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5130                 cpi->version_num);
5131
5132         for (i = 1; i < 0xff; i = i << 1) {
5133                 const char *str;
5134
5135                 if ((i & cpi->hba_inquiry) == 0)
5136                         continue;
5137
5138                 fprintf(stdout, "%s supports ", adapter_str);
5139
5140                 switch(i) {
5141                 case PI_MDP_ABLE:
5142                         str = "MDP message";
5143                         break;
5144                 case PI_WIDE_32:
5145                         str = "32 bit wide SCSI";
5146                         break;
5147                 case PI_WIDE_16:
5148                         str = "16 bit wide SCSI";
5149                         break;
5150                 case PI_SDTR_ABLE:
5151                         str = "SDTR message";
5152                         break;
5153                 case PI_LINKED_CDB:
5154                         str = "linked CDBs";
5155                         break;
5156                 case PI_TAG_ABLE:
5157                         str = "tag queue messages";
5158                         break;
5159                 case PI_SOFT_RST:
5160                         str = "soft reset alternative";
5161                         break;
5162                 case PI_SATAPM:
5163                         str = "SATA Port Multiplier";
5164                         break;
5165                 default:
5166                         str = "unknown PI bit set";
5167                         break;
5168                 }
5169                 fprintf(stdout, "%s\n", str);
5170         }
5171
5172         for (i = 1; i < 0xff; i = i << 1) {
5173                 const char *str;
5174
5175                 if ((i & cpi->hba_misc) == 0)
5176                         continue;
5177
5178                 fprintf(stdout, "%s ", adapter_str);
5179
5180                 switch(i) {
5181                 case PIM_SCANHILO:
5182                         str = "bus scans from high ID to low ID";
5183                         break;
5184                 case PIM_NOREMOVE:
5185                         str = "removable devices not included in scan";
5186                         break;
5187                 case PIM_NOINITIATOR:
5188                         str = "initiator role not supported";
5189                         break;
5190                 case PIM_NOBUSRESET:
5191                         str = "user has disabled initial BUS RESET or"
5192                               " controller is in target/mixed mode";
5193                         break;
5194                 case PIM_NO_6_BYTE:
5195                         str = "do not send 6-byte commands";
5196                         break;
5197                 case PIM_SEQSCAN:
5198                         str = "scan bus sequentially";
5199                         break;
5200                 default:
5201                         str = "unknown PIM bit set";
5202                         break;
5203                 }
5204                 fprintf(stdout, "%s\n", str);
5205         }
5206
5207         for (i = 1; i < 0xff; i = i << 1) {
5208                 const char *str;
5209
5210                 if ((i & cpi->target_sprt) == 0)
5211                         continue;
5212
5213                 fprintf(stdout, "%s supports ", adapter_str);
5214                 switch(i) {
5215                 case PIT_PROCESSOR:
5216                         str = "target mode processor mode";
5217                         break;
5218                 case PIT_PHASE:
5219                         str = "target mode phase cog. mode";
5220                         break;
5221                 case PIT_DISCONNECT:
5222                         str = "disconnects in target mode";
5223                         break;
5224                 case PIT_TERM_IO:
5225                         str = "terminate I/O message in target mode";
5226                         break;
5227                 case PIT_GRP_6:
5228                         str = "group 6 commands in target mode";
5229                         break;
5230                 case PIT_GRP_7:
5231                         str = "group 7 commands in target mode";
5232                         break;
5233                 default:
5234                         str = "unknown PIT bit set";
5235                         break;
5236                 }
5237
5238                 fprintf(stdout, "%s\n", str);
5239         }
5240         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5241                 cpi->hba_eng_cnt);
5242         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5243                 cpi->max_target);
5244         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5245                 cpi->max_lun);
5246         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5247                 adapter_str, cpi->hpath_id);
5248         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5249                 cpi->initiator_id);
5250         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5251         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5252         fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5253             adapter_str, cpi->hba_vendor);
5254         fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5255             adapter_str, cpi->hba_device);
5256         fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5257             adapter_str, cpi->hba_subvendor);
5258         fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5259             adapter_str, cpi->hba_subdevice);
5260         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5261         fprintf(stdout, "%s base transfer speed: ", adapter_str);
5262         if (cpi->base_transfer_speed > 1000)
5263                 fprintf(stdout, "%d.%03dMB/sec\n",
5264                         cpi->base_transfer_speed / 1000,
5265                         cpi->base_transfer_speed % 1000);
5266         else
5267                 fprintf(stdout, "%dKB/sec\n",
5268                         (cpi->base_transfer_speed % 1000) * 1000);
5269         fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5270             adapter_str, cpi->maxio);
5271 }
5272
5273 static int
5274 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5275               struct ccb_trans_settings *cts)
5276 {
5277         int retval;
5278         union ccb *ccb;
5279
5280         retval = 0;
5281         ccb = cam_getccb(device);
5282
5283         if (ccb == NULL) {
5284                 warnx("get_print_cts: error allocating ccb");
5285                 return(1);
5286         }
5287
5288         bzero(&(&ccb->ccb_h)[1],
5289               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5290
5291         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5292
5293         if (user_settings == 0)
5294                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5295         else
5296                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5297
5298         if (cam_send_ccb(device, ccb) < 0) {
5299                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5300                 if (arglist & CAM_ARG_VERBOSE)
5301                         cam_error_print(device, ccb, CAM_ESF_ALL,
5302                                         CAM_EPF_ALL, stderr);
5303                 retval = 1;
5304                 goto get_print_cts_bailout;
5305         }
5306
5307         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5308                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5309                 if (arglist & CAM_ARG_VERBOSE)
5310                         cam_error_print(device, ccb, CAM_ESF_ALL,
5311                                         CAM_EPF_ALL, stderr);
5312                 retval = 1;
5313                 goto get_print_cts_bailout;
5314         }
5315
5316         if (quiet == 0)
5317                 cts_print(device, &ccb->cts);
5318
5319         if (cts != NULL)
5320                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5321
5322 get_print_cts_bailout:
5323
5324         cam_freeccb(ccb);
5325
5326         return(retval);
5327 }
5328
5329 static int
5330 ratecontrol(struct cam_device *device, int retry_count, int timeout,
5331             int argc, char **argv, char *combinedopt)
5332 {
5333         int c;
5334         union ccb *ccb;
5335         int user_settings = 0;
5336         int retval = 0;
5337         int disc_enable = -1, tag_enable = -1;
5338         int mode = -1;
5339         int offset = -1;
5340         double syncrate = -1;
5341         int bus_width = -1;
5342         int quiet = 0;
5343         int change_settings = 0, send_tur = 0;
5344         struct ccb_pathinq cpi;
5345
5346         ccb = cam_getccb(device);
5347         if (ccb == NULL) {
5348                 warnx("ratecontrol: error allocating ccb");
5349                 return(1);
5350         }
5351         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5352                 switch(c){
5353                 case 'a':
5354                         send_tur = 1;
5355                         break;
5356                 case 'c':
5357                         user_settings = 0;
5358                         break;
5359                 case 'D':
5360                         if (strncasecmp(optarg, "enable", 6) == 0)
5361                                 disc_enable = 1;
5362                         else if (strncasecmp(optarg, "disable", 7) == 0)
5363                                 disc_enable = 0;
5364                         else {
5365                                 warnx("-D argument \"%s\" is unknown", optarg);
5366                                 retval = 1;
5367                                 goto ratecontrol_bailout;
5368                         }
5369                         change_settings = 1;
5370                         break;
5371                 case 'M':
5372                         mode = ata_string2mode(optarg);
5373                         if (mode < 0) {
5374                                 warnx("unknown mode '%s'", optarg);
5375                                 retval = 1;
5376                                 goto ratecontrol_bailout;
5377                         }
5378                         change_settings = 1;
5379                         break;
5380                 case 'O':
5381                         offset = strtol(optarg, NULL, 0);
5382                         if (offset < 0) {
5383                                 warnx("offset value %d is < 0", offset);
5384                                 retval = 1;
5385                                 goto ratecontrol_bailout;
5386                         }
5387                         change_settings = 1;
5388                         break;
5389                 case 'q':
5390                         quiet++;
5391                         break;
5392                 case 'R':
5393                         syncrate = atof(optarg);
5394                         if (syncrate < 0) {
5395                                 warnx("sync rate %f is < 0", syncrate);
5396                                 retval = 1;
5397                                 goto ratecontrol_bailout;
5398                         }
5399                         change_settings = 1;
5400                         break;
5401                 case 'T':
5402                         if (strncasecmp(optarg, "enable", 6) == 0)
5403                                 tag_enable = 1;
5404                         else if (strncasecmp(optarg, "disable", 7) == 0)
5405                                 tag_enable = 0;
5406                         else {
5407                                 warnx("-T argument \"%s\" is unknown", optarg);
5408                                 retval = 1;
5409                                 goto ratecontrol_bailout;
5410                         }
5411                         change_settings = 1;
5412                         break;
5413                 case 'U':
5414                         user_settings = 1;
5415                         break;
5416                 case 'W':
5417                         bus_width = strtol(optarg, NULL, 0);
5418                         if (bus_width < 0) {
5419                                 warnx("bus width %d is < 0", bus_width);
5420                                 retval = 1;
5421                                 goto ratecontrol_bailout;
5422                         }
5423                         change_settings = 1;
5424                         break;
5425                 default:
5426                         break;
5427                 }
5428         }
5429         bzero(&(&ccb->ccb_h)[1],
5430               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5431         /*
5432          * Grab path inquiry information, so we can determine whether
5433          * or not the initiator is capable of the things that the user
5434          * requests.
5435          */
5436         ccb->ccb_h.func_code = XPT_PATH_INQ;
5437         if (cam_send_ccb(device, ccb) < 0) {
5438                 perror("error sending XPT_PATH_INQ CCB");
5439                 if (arglist & CAM_ARG_VERBOSE) {
5440                         cam_error_print(device, ccb, CAM_ESF_ALL,
5441                                         CAM_EPF_ALL, stderr);
5442                 }
5443                 retval = 1;
5444                 goto ratecontrol_bailout;
5445         }
5446         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5447                 warnx("XPT_PATH_INQ CCB failed");
5448                 if (arglist & CAM_ARG_VERBOSE) {
5449                         cam_error_print(device, ccb, CAM_ESF_ALL,
5450                                         CAM_EPF_ALL, stderr);
5451                 }
5452                 retval = 1;
5453                 goto ratecontrol_bailout;
5454         }
5455         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5456         bzero(&(&ccb->ccb_h)[1],
5457               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5458         if (quiet == 0) {
5459                 fprintf(stdout, "%s parameters:\n",
5460                     user_settings ? "User" : "Current");
5461         }
5462         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5463         if (retval != 0)
5464                 goto ratecontrol_bailout;
5465
5466         if (arglist & CAM_ARG_VERBOSE)
5467                 cpi_print(&cpi);
5468
5469         if (change_settings) {
5470                 int didsettings = 0;
5471                 struct ccb_trans_settings_spi *spi = NULL;
5472                 struct ccb_trans_settings_pata *pata = NULL;
5473                 struct ccb_trans_settings_sata *sata = NULL;
5474                 struct ccb_trans_settings_ata *ata = NULL;
5475                 struct ccb_trans_settings_scsi *scsi = NULL;
5476
5477                 if (ccb->cts.transport == XPORT_SPI)
5478                         spi = &ccb->cts.xport_specific.spi;
5479                 if (ccb->cts.transport == XPORT_ATA)
5480                         pata = &ccb->cts.xport_specific.ata;
5481                 if (ccb->cts.transport == XPORT_SATA)
5482                         sata = &ccb->cts.xport_specific.sata;
5483                 if (ccb->cts.protocol == PROTO_ATA)
5484                         ata = &ccb->cts.proto_specific.ata;
5485                 if (ccb->cts.protocol == PROTO_SCSI)
5486                         scsi = &ccb->cts.proto_specific.scsi;
5487                 ccb->cts.xport_specific.valid = 0;
5488                 ccb->cts.proto_specific.valid = 0;
5489                 if (spi && disc_enable != -1) {
5490                         spi->valid |= CTS_SPI_VALID_DISC;
5491                         if (disc_enable == 0)
5492                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5493                         else
5494                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5495                         didsettings++;
5496                 }
5497                 if (tag_enable != -1) {
5498                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5499                                 warnx("HBA does not support tagged queueing, "
5500                                       "so you cannot modify tag settings");
5501                                 retval = 1;
5502                                 goto ratecontrol_bailout;
5503                         }
5504                         if (ata) {
5505                                 ata->valid |= CTS_SCSI_VALID_TQ;
5506                                 if (tag_enable == 0)
5507                                         ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5508                                 else
5509                                         ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5510                                 didsettings++;
5511                         } else if (scsi) {
5512                                 scsi->valid |= CTS_SCSI_VALID_TQ;
5513                                 if (tag_enable == 0)
5514                                         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5515                                 else
5516                                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5517                                 didsettings++;
5518                         }
5519                 }
5520                 if (spi && offset != -1) {
5521                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5522                                 warnx("HBA is not capable of changing offset");
5523                                 retval = 1;
5524                                 goto ratecontrol_bailout;
5525                         }
5526                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5527                         spi->sync_offset = offset;
5528                         didsettings++;
5529                 }
5530                 if (spi && syncrate != -1) {
5531                         int prelim_sync_period;
5532
5533                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5534                                 warnx("HBA is not capable of changing "
5535                                       "transfer rates");
5536                                 retval = 1;
5537                                 goto ratecontrol_bailout;
5538                         }
5539                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5540                         /*
5541                          * The sync rate the user gives us is in MHz.
5542                          * We need to translate it into KHz for this
5543                          * calculation.
5544                          */
5545                         syncrate *= 1000;
5546                         /*
5547                          * Next, we calculate a "preliminary" sync period
5548                          * in tenths of a nanosecond.
5549                          */
5550                         if (syncrate == 0)
5551                                 prelim_sync_period = 0;
5552                         else
5553                                 prelim_sync_period = 10000000 / syncrate;
5554                         spi->sync_period =
5555                                 scsi_calc_syncparam(prelim_sync_period);
5556                         didsettings++;
5557                 }
5558                 if (sata && syncrate != -1) {
5559                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5560                                 warnx("HBA is not capable of changing "
5561                                       "transfer rates");
5562                                 retval = 1;
5563                                 goto ratecontrol_bailout;
5564                         }
5565                         if  (!user_settings) {
5566                                 warnx("You can modify only user rate "
5567                                     "settings for SATA");
5568                                 retval = 1;
5569                                 goto ratecontrol_bailout;
5570                         }
5571                         sata->revision = ata_speed2revision(syncrate * 100);
5572                         if (sata->revision < 0) {
5573                                 warnx("Invalid rate %f", syncrate);
5574                                 retval = 1;
5575                                 goto ratecontrol_bailout;
5576                         }
5577                         sata->valid |= CTS_SATA_VALID_REVISION;
5578                         didsettings++;
5579                 }
5580                 if ((pata || sata) && mode != -1) {
5581                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5582                                 warnx("HBA is not capable of changing "
5583                                       "transfer rates");
5584                                 retval = 1;
5585                                 goto ratecontrol_bailout;
5586                         }
5587                         if  (!user_settings) {
5588                                 warnx("You can modify only user mode "
5589                                     "settings for ATA/SATA");
5590                                 retval = 1;
5591                                 goto ratecontrol_bailout;
5592                         }
5593                         if (pata) {
5594                                 pata->mode = mode;
5595                                 pata->valid |= CTS_ATA_VALID_MODE;
5596                         } else {
5597                                 sata->mode = mode;
5598                                 sata->valid |= CTS_SATA_VALID_MODE;
5599                         }
5600                         didsettings++;
5601                 }
5602                 /*
5603                  * The bus_width argument goes like this:
5604                  * 0 == 8 bit
5605                  * 1 == 16 bit
5606                  * 2 == 32 bit
5607                  * Therefore, if you shift the number of bits given on the
5608                  * command line right by 4, you should get the correct
5609                  * number.
5610                  */
5611                 if (spi && bus_width != -1) {
5612                         /*
5613                          * We might as well validate things here with a
5614                          * decipherable error message, rather than what
5615                          * will probably be an indecipherable error message
5616                          * by the time it gets back to us.
5617                          */
5618                         if ((bus_width == 16)
5619                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5620                                 warnx("HBA does not support 16 bit bus width");
5621                                 retval = 1;
5622                                 goto ratecontrol_bailout;
5623                         } else if ((bus_width == 32)
5624                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5625                                 warnx("HBA does not support 32 bit bus width");
5626                                 retval = 1;
5627                                 goto ratecontrol_bailout;
5628                         } else if ((bus_width != 8)
5629                                 && (bus_width != 16)
5630                                 && (bus_width != 32)) {
5631                                 warnx("Invalid bus width %d", bus_width);
5632                                 retval = 1;
5633                                 goto ratecontrol_bailout;
5634                         }
5635                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5636                         spi->bus_width = bus_width >> 4;
5637                         didsettings++;
5638                 }
5639                 if  (didsettings == 0) {
5640                         goto ratecontrol_bailout;
5641                 }
5642                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5643                 if (cam_send_ccb(device, ccb) < 0) {
5644                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5645                         if (arglist & CAM_ARG_VERBOSE) {
5646                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5647                                                 CAM_EPF_ALL, stderr);
5648                         }
5649                         retval = 1;
5650                         goto ratecontrol_bailout;
5651                 }
5652                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5653                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5654                         if (arglist & CAM_ARG_VERBOSE) {
5655                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5656                                                 CAM_EPF_ALL, stderr);
5657                         }
5658                         retval = 1;
5659                         goto ratecontrol_bailout;
5660                 }
5661         }
5662         if (send_tur) {
5663                 retval = testunitready(device, retry_count, timeout,
5664                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5665                 /*
5666                  * If the TUR didn't succeed, just bail.
5667                  */
5668                 if (retval != 0) {
5669                         if (quiet == 0)
5670                                 fprintf(stderr, "Test Unit Ready failed\n");
5671                         goto ratecontrol_bailout;
5672                 }
5673         }
5674         if ((change_settings || send_tur) && !quiet &&
5675             (ccb->cts.transport == XPORT_ATA ||
5676              ccb->cts.transport == XPORT_SATA || send_tur)) {
5677                 fprintf(stdout, "New parameters:\n");
5678                 retval = get_print_cts(device, user_settings, 0, NULL);
5679         }
5680
5681 ratecontrol_bailout:
5682         cam_freeccb(ccb);
5683         return(retval);
5684 }
5685
5686 static int
5687 scsiformat(struct cam_device *device, int argc, char **argv,
5688            char *combinedopt, int retry_count, int timeout)
5689 {
5690         union ccb *ccb;
5691         int c;
5692         int ycount = 0, quiet = 0;
5693         int error = 0, retval = 0;
5694         int use_timeout = 10800 * 1000;
5695         int immediate = 1;
5696         struct format_defect_list_header fh;
5697         u_int8_t *data_ptr = NULL;
5698         u_int32_t dxfer_len = 0;
5699         u_int8_t byte2 = 0;
5700         int num_warnings = 0;
5701         int reportonly = 0;
5702
5703         ccb = cam_getccb(device);
5704
5705         if (ccb == NULL) {
5706                 warnx("scsiformat: error allocating ccb");
5707                 return(1);
5708         }
5709
5710         bzero(&(&ccb->ccb_h)[1],
5711               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5712
5713         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5714                 switch(c) {
5715                 case 'q':
5716                         quiet++;
5717                         break;
5718                 case 'r':
5719                         reportonly = 1;
5720                         break;
5721                 case 'w':
5722                         immediate = 0;
5723                         break;
5724                 case 'y':
5725                         ycount++;
5726                         break;
5727                 }
5728         }
5729
5730         if (reportonly)
5731                 goto doreport;
5732
5733         if (quiet == 0) {
5734                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5735                         "following device:\n");
5736
5737                 error = scsidoinquiry(device, argc, argv, combinedopt,
5738                                       retry_count, timeout);
5739
5740                 if (error != 0) {
5741                         warnx("scsiformat: error sending inquiry");
5742                         goto scsiformat_bailout;
5743                 }
5744         }
5745
5746         if (ycount == 0) {
5747                 if (!get_confirmation()) {
5748                         error = 1;
5749                         goto scsiformat_bailout;
5750                 }
5751         }
5752
5753         if (timeout != 0)
5754                 use_timeout = timeout;
5755
5756         if (quiet == 0) {
5757                 fprintf(stdout, "Current format timeout is %d seconds\n",
5758                         use_timeout / 1000);
5759         }
5760
5761         /*
5762          * If the user hasn't disabled questions and didn't specify a
5763          * timeout on the command line, ask them if they want the current
5764          * timeout.
5765          */
5766         if ((ycount == 0)
5767          && (timeout == 0)) {
5768                 char str[1024];
5769                 int new_timeout = 0;
5770
5771                 fprintf(stdout, "Enter new timeout in seconds or press\n"
5772                         "return to keep the current timeout [%d] ",
5773                         use_timeout / 1000);
5774
5775                 if (fgets(str, sizeof(str), stdin) != NULL) {
5776                         if (str[0] != '\0')
5777                                 new_timeout = atoi(str);
5778                 }
5779
5780                 if (new_timeout != 0) {
5781                         use_timeout = new_timeout * 1000;
5782                         fprintf(stdout, "Using new timeout value %d\n",
5783                                 use_timeout / 1000);
5784                 }
5785         }
5786
5787         /*
5788          * Keep this outside the if block below to silence any unused
5789          * variable warnings.
5790          */
5791         bzero(&fh, sizeof(fh));
5792
5793         /*
5794          * If we're in immediate mode, we've got to include the format
5795          * header
5796          */
5797         if (immediate != 0) {
5798                 fh.byte2 = FU_DLH_IMMED;
5799                 data_ptr = (u_int8_t *)&fh;
5800                 dxfer_len = sizeof(fh);
5801                 byte2 = FU_FMT_DATA;
5802         } else if (quiet == 0) {
5803                 fprintf(stdout, "Formatting...");
5804                 fflush(stdout);
5805         }
5806
5807         scsi_format_unit(&ccb->csio,
5808                          /* retries */ retry_count,
5809                          /* cbfcnp */ NULL,
5810                          /* tag_action */ MSG_SIMPLE_Q_TAG,
5811                          /* byte2 */ byte2,
5812                          /* ileave */ 0,
5813                          /* data_ptr */ data_ptr,
5814                          /* dxfer_len */ dxfer_len,
5815                          /* sense_len */ SSD_FULL_SIZE,
5816                          /* timeout */ use_timeout);
5817
5818         /* Disable freezing the device queue */
5819         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5820
5821         if (arglist & CAM_ARG_ERR_RECOVER)
5822                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5823
5824         if (((retval = cam_send_ccb(device, ccb)) < 0)
5825          || ((immediate == 0)
5826            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5827                 const char errstr[] = "error sending format command";
5828
5829                 if (retval < 0)
5830                         warn(errstr);
5831                 else
5832                         warnx(errstr);
5833
5834                 if (arglist & CAM_ARG_VERBOSE) {
5835                         cam_error_print(device, ccb, CAM_ESF_ALL,
5836                                         CAM_EPF_ALL, stderr);
5837                 }
5838                 error = 1;
5839                 goto scsiformat_bailout;
5840         }
5841
5842         /*
5843          * If we ran in non-immediate mode, we already checked for errors
5844          * above and printed out any necessary information.  If we're in
5845          * immediate mode, we need to loop through and get status
5846          * information periodically.
5847          */
5848         if (immediate == 0) {
5849                 if (quiet == 0) {
5850                         fprintf(stdout, "Format Complete\n");
5851                 }
5852                 goto scsiformat_bailout;
5853         }
5854
5855 doreport:
5856         do {
5857                 cam_status status;
5858
5859                 bzero(&(&ccb->ccb_h)[1],
5860                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5861
5862                 /*
5863                  * There's really no need to do error recovery or
5864                  * retries here, since we're just going to sit in a
5865                  * loop and wait for the device to finish formatting.
5866                  */
5867                 scsi_test_unit_ready(&ccb->csio,
5868                                      /* retries */ 0,
5869                                      /* cbfcnp */ NULL,
5870                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
5871                                      /* sense_len */ SSD_FULL_SIZE,
5872                                      /* timeout */ 5000);
5873
5874                 /* Disable freezing the device queue */
5875                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5876
5877                 retval = cam_send_ccb(device, ccb);
5878
5879                 /*
5880                  * If we get an error from the ioctl, bail out.  SCSI
5881                  * errors are expected.
5882                  */
5883                 if (retval < 0) {
5884                         warn("error sending CAMIOCOMMAND ioctl");
5885                         if (arglist & CAM_ARG_VERBOSE) {
5886                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5887                                                 CAM_EPF_ALL, stderr);
5888                         }
5889                         error = 1;
5890                         goto scsiformat_bailout;
5891                 }
5892
5893                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5894
5895                 if ((status != CAM_REQ_CMP)
5896                  && (status == CAM_SCSI_STATUS_ERROR)
5897                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5898                         struct scsi_sense_data *sense;
5899                         int error_code, sense_key, asc, ascq;
5900
5901                         sense = &ccb->csio.sense_data;
5902                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
5903                             ccb->csio.sense_resid, &error_code, &sense_key,
5904                             &asc, &ascq, /*show_errors*/ 1);
5905
5906                         /*
5907                          * According to the SCSI-2 and SCSI-3 specs, a
5908                          * drive that is in the middle of a format should
5909                          * return NOT READY with an ASC of "logical unit
5910                          * not ready, format in progress".  The sense key
5911                          * specific bytes will then be a progress indicator.
5912                          */
5913                         if ((sense_key == SSD_KEY_NOT_READY)
5914                          && (asc == 0x04) && (ascq == 0x04)) {
5915                                 uint8_t sks[3];
5916
5917                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5918                                      ccb->csio.sense_resid, sks) == 0)
5919                                  && (quiet == 0)) {
5920                                         int val;
5921                                         u_int64_t percentage;
5922
5923                                         val = scsi_2btoul(&sks[1]);
5924                                         percentage = 10000 * val;
5925
5926                                         fprintf(stdout,
5927                                                 "\rFormatting:  %ju.%02u %% "
5928                                                 "(%d/%d) done",
5929                                                 (uintmax_t)(percentage /
5930                                                 (0x10000 * 100)),
5931                                                 (unsigned)((percentage /
5932                                                 0x10000) % 100),
5933                                                 val, 0x10000);
5934                                         fflush(stdout);
5935                                 } else if ((quiet == 0)
5936                                         && (++num_warnings <= 1)) {
5937                                         warnx("Unexpected SCSI Sense Key "
5938                                               "Specific value returned "
5939                                               "during format:");
5940                                         scsi_sense_print(device, &ccb->csio,
5941                                                          stderr);
5942                                         warnx("Unable to print status "
5943                                               "information, but format will "
5944                                               "proceed.");
5945                                         warnx("will exit when format is "
5946                                               "complete");
5947                                 }
5948                                 sleep(1);
5949                         } else {
5950                                 warnx("Unexpected SCSI error during format");
5951                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5952                                                 CAM_EPF_ALL, stderr);
5953                                 error = 1;
5954                                 goto scsiformat_bailout;
5955                         }
5956
5957                 } else if (status != CAM_REQ_CMP) {
5958                         warnx("Unexpected CAM status %#x", status);
5959                         if (arglist & CAM_ARG_VERBOSE)
5960                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5961                                                 CAM_EPF_ALL, stderr);
5962                         error = 1;
5963                         goto scsiformat_bailout;
5964                 }
5965
5966         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5967
5968         if (quiet == 0)
5969                 fprintf(stdout, "\nFormat Complete\n");
5970
5971 scsiformat_bailout:
5972
5973         cam_freeccb(ccb);
5974
5975         return(error);
5976 }
5977
5978 static int
5979 scsisanitize(struct cam_device *device, int argc, char **argv,
5980              char *combinedopt, int retry_count, int timeout)
5981 {
5982         union ccb *ccb;
5983         u_int8_t action = 0;
5984         int c;
5985         int ycount = 0, quiet = 0;
5986         int error = 0, retval = 0;
5987         int use_timeout = 10800 * 1000;
5988         int immediate = 1;
5989         int invert = 0;
5990         int passes = 0;
5991         int ause = 0;
5992         int fd = -1;
5993         const char *pattern = NULL;
5994         u_int8_t *data_ptr = NULL;
5995         u_int32_t dxfer_len = 0;
5996         u_int8_t byte2 = 0;
5997         int num_warnings = 0;
5998         int reportonly = 0;
5999
6000         ccb = cam_getccb(device);
6001
6002         if (ccb == NULL) {
6003                 warnx("scsisanitize: error allocating ccb");
6004                 return(1);
6005         }
6006
6007         bzero(&(&ccb->ccb_h)[1],
6008               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6009
6010         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6011                 switch(c) {
6012                 case 'a':
6013                         if (strcasecmp(optarg, "overwrite") == 0)
6014                                 action = SSZ_SERVICE_ACTION_OVERWRITE;
6015                         else if (strcasecmp(optarg, "block") == 0)
6016                                 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6017                         else if (strcasecmp(optarg, "crypto") == 0)
6018                                 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6019                         else if (strcasecmp(optarg, "exitfailure") == 0)
6020                                 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6021                         else {
6022                                 warnx("invalid service operation \"%s\"",
6023                                       optarg);
6024                                 error = 1;
6025                                 goto scsisanitize_bailout;
6026                         }
6027                         break;
6028                 case 'c':
6029                         passes = strtol(optarg, NULL, 0);
6030                         if (passes < 1 || passes > 31) {
6031                                 warnx("invalid passes value %d", passes);
6032                                 error = 1;
6033                                 goto scsisanitize_bailout;
6034                         }
6035                         break;
6036                 case 'I':
6037                         invert = 1;
6038                         break;
6039                 case 'P':
6040                         pattern = optarg;
6041                         break;
6042                 case 'q':
6043                         quiet++;
6044                         break;
6045                 case 'U':
6046                         ause = 1;
6047                         break;
6048                 case 'r':
6049                         reportonly = 1;
6050                         break;
6051                 case 'w':
6052                         immediate = 0;
6053                         break;
6054                 case 'y':
6055                         ycount++;
6056                         break;
6057                 }
6058         }
6059
6060         if (reportonly)
6061                 goto doreport;
6062
6063         if (action == 0) {
6064                 warnx("an action is required");
6065                 error = 1;
6066                 goto scsisanitize_bailout;
6067         } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6068                 struct scsi_sanitize_parameter_list *pl;
6069                 struct stat sb;
6070                 ssize_t sz, amt;
6071
6072                 if (pattern == NULL) {
6073                         warnx("overwrite action requires -P argument");
6074                         error = 1;
6075                         goto scsisanitize_bailout;
6076                 }
6077                 fd = open(pattern, O_RDONLY);
6078                 if (fd < 0) {
6079                         warn("cannot open pattern file %s", pattern);
6080                         error = 1;
6081                         goto scsisanitize_bailout;
6082                 }
6083                 if (fstat(fd, &sb) < 0) {
6084                         warn("cannot stat pattern file %s", pattern);
6085                         error = 1;
6086                         goto scsisanitize_bailout;
6087                 }
6088                 sz = sb.st_size;
6089                 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6090                         warnx("pattern file size exceeds maximum value %d",
6091                               SSZPL_MAX_PATTERN_LENGTH);
6092                         error = 1;
6093                         goto scsisanitize_bailout;
6094                 }
6095                 dxfer_len = sizeof(*pl) + sz;
6096                 data_ptr = calloc(1, dxfer_len);
6097                 if (data_ptr == NULL) {
6098                         warnx("cannot allocate parameter list buffer");
6099                         error = 1;
6100                         goto scsisanitize_bailout;
6101                 }
6102
6103                 amt = read(fd, data_ptr + sizeof(*pl), sz);
6104                 if (amt < 0) {
6105                         warn("cannot read pattern file");
6106                         error = 1;
6107                         goto scsisanitize_bailout;
6108                 } else if (amt != sz) {
6109                         warnx("short pattern file read");
6110                         error = 1;
6111                         goto scsisanitize_bailout;
6112                 }
6113
6114                 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6115                 if (passes == 0)
6116                         pl->byte1 = 1;
6117                 else
6118                         pl->byte1 = passes;
6119                 if (invert != 0)
6120                         pl->byte1 |= SSZPL_INVERT;
6121                 scsi_ulto2b(sz, pl->length);
6122         } else {
6123                 const char *arg;
6124
6125                 if (passes != 0)
6126                         arg = "-c";
6127                 else if (invert != 0)
6128                         arg = "-I";
6129                 else if (pattern != NULL)
6130                         arg = "-P";
6131                 else
6132                         arg = NULL;
6133                 if (arg != NULL) {
6134                         warnx("%s argument only valid with overwrite "
6135                               "operation", arg);
6136                         error = 1;
6137                         goto scsisanitize_bailout;
6138                 }
6139         }
6140
6141         if (quiet == 0) {
6142                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6143                         "following device:\n");
6144
6145                 error = scsidoinquiry(device, argc, argv, combinedopt,
6146                                       retry_count, timeout);
6147
6148                 if (error != 0) {
6149                         warnx("scsisanitize: error sending inquiry");
6150                         goto scsisanitize_bailout;
6151                 }
6152         }
6153
6154         if (ycount == 0) {
6155                 if (!get_confirmation()) {
6156                         error = 1;
6157                         goto scsisanitize_bailout;
6158                 }
6159         }
6160
6161         if (timeout != 0)
6162                 use_timeout = timeout;
6163
6164         if (quiet == 0) {
6165                 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6166                         use_timeout / 1000);
6167         }
6168
6169         /*
6170          * If the user hasn't disabled questions and didn't specify a
6171          * timeout on the command line, ask them if they want the current
6172          * timeout.
6173          */
6174         if ((ycount == 0)
6175          && (timeout == 0)) {
6176                 char str[1024];
6177                 int new_timeout = 0;
6178
6179                 fprintf(stdout, "Enter new timeout in seconds or press\n"
6180                         "return to keep the current timeout [%d] ",
6181                         use_timeout / 1000);
6182
6183                 if (fgets(str, sizeof(str), stdin) != NULL) {
6184                         if (str[0] != '\0')
6185                                 new_timeout = atoi(str);
6186                 }
6187
6188                 if (new_timeout != 0) {
6189                         use_timeout = new_timeout * 1000;
6190                         fprintf(stdout, "Using new timeout value %d\n",
6191                                 use_timeout / 1000);
6192                 }
6193         }
6194
6195         byte2 = action;
6196         if (ause != 0)
6197                 byte2 |= SSZ_UNRESTRICTED_EXIT;
6198         if (immediate != 0)
6199                 byte2 |= SSZ_IMMED;
6200
6201         scsi_sanitize(&ccb->csio,
6202                       /* retries */ retry_count,
6203                       /* cbfcnp */ NULL,
6204                       /* tag_action */ MSG_SIMPLE_Q_TAG,
6205                       /* byte2 */ byte2,
6206                       /* control */ 0,
6207                       /* data_ptr */ data_ptr,
6208                       /* dxfer_len */ dxfer_len,
6209                       /* sense_len */ SSD_FULL_SIZE,
6210                       /* timeout */ use_timeout);
6211
6212         /* Disable freezing the device queue */
6213         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6214
6215         if (arglist & CAM_ARG_ERR_RECOVER)
6216                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6217
6218         if (cam_send_ccb(device, ccb) < 0) {
6219                 warn("error sending sanitize command");
6220                 error = 1;
6221                 goto scsisanitize_bailout;
6222         }
6223
6224         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6225                 struct scsi_sense_data *sense;
6226                 int error_code, sense_key, asc, ascq;
6227
6228                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6229                     CAM_SCSI_STATUS_ERROR) {
6230                         sense = &ccb->csio.sense_data;
6231                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6232                             ccb->csio.sense_resid, &error_code, &sense_key,
6233                             &asc, &ascq, /*show_errors*/ 1);
6234
6235                         if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6236                             asc == 0x20 && ascq == 0x00)
6237                                 warnx("sanitize is not supported by "
6238                                       "this device");
6239                         else
6240                                 warnx("error sanitizing this device");
6241                 } else
6242                         warnx("error sanitizing this device");
6243
6244                 if (arglist & CAM_ARG_VERBOSE) {
6245                         cam_error_print(device, ccb, CAM_ESF_ALL,
6246                                         CAM_EPF_ALL, stderr);
6247                 }
6248                 error = 1;
6249                 goto scsisanitize_bailout;
6250         }
6251
6252         /*
6253          * If we ran in non-immediate mode, we already checked for errors
6254          * above and printed out any necessary information.  If we're in
6255          * immediate mode, we need to loop through and get status
6256          * information periodically.
6257          */
6258         if (immediate == 0) {
6259                 if (quiet == 0) {
6260                         fprintf(stdout, "Sanitize Complete\n");
6261                 }
6262                 goto scsisanitize_bailout;
6263         }
6264
6265 doreport:
6266         do {
6267                 cam_status status;
6268
6269                 bzero(&(&ccb->ccb_h)[1],
6270                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6271
6272                 /*
6273                  * There's really no need to do error recovery or
6274                  * retries here, since we're just going to sit in a
6275                  * loop and wait for the device to finish sanitizing.
6276                  */
6277                 scsi_test_unit_ready(&ccb->csio,
6278                                      /* retries */ 0,
6279                                      /* cbfcnp */ NULL,
6280                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
6281                                      /* sense_len */ SSD_FULL_SIZE,
6282                                      /* timeout */ 5000);
6283
6284                 /* Disable freezing the device queue */
6285                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6286
6287                 retval = cam_send_ccb(device, ccb);
6288
6289                 /*
6290                  * If we get an error from the ioctl, bail out.  SCSI
6291                  * errors are expected.
6292                  */
6293                 if (retval < 0) {
6294                         warn("error sending CAMIOCOMMAND ioctl");
6295                         if (arglist & CAM_ARG_VERBOSE) {
6296                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6297                                                 CAM_EPF_ALL, stderr);
6298                         }
6299                         error = 1;
6300                         goto scsisanitize_bailout;
6301                 }
6302
6303                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6304
6305                 if ((status != CAM_REQ_CMP)
6306                  && (status == CAM_SCSI_STATUS_ERROR)
6307                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6308                         struct scsi_sense_data *sense;
6309                         int error_code, sense_key, asc, ascq;
6310
6311                         sense = &ccb->csio.sense_data;
6312                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6313                             ccb->csio.sense_resid, &error_code, &sense_key,
6314                             &asc, &ascq, /*show_errors*/ 1);
6315
6316                         /*
6317                          * According to the SCSI-3 spec, a drive that is in the
6318                          * middle of a sanitize should return NOT READY with an
6319                          * ASC of "logical unit not ready, sanitize in
6320                          * progress". The sense key specific bytes will then
6321                          * be a progress indicator.
6322                          */
6323                         if ((sense_key == SSD_KEY_NOT_READY)
6324                          && (asc == 0x04) && (ascq == 0x1b)) {
6325                                 uint8_t sks[3];
6326
6327                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6328                                      ccb->csio.sense_resid, sks) == 0)
6329                                  && (quiet == 0)) {
6330                                         int val;
6331                                         u_int64_t percentage;
6332
6333                                         val = scsi_2btoul(&sks[1]);
6334                                         percentage = 10000 * val;
6335
6336                                         fprintf(stdout,
6337                                                 "\rSanitizing:  %ju.%02u %% "
6338                                                 "(%d/%d) done",
6339                                                 (uintmax_t)(percentage /
6340                                                 (0x10000 * 100)),
6341                                                 (unsigned)((percentage /
6342                                                 0x10000) % 100),
6343                                                 val, 0x10000);
6344                                         fflush(stdout);
6345                                 } else if ((quiet == 0)
6346                                         && (++num_warnings <= 1)) {
6347                                         warnx("Unexpected SCSI Sense Key "
6348                                               "Specific value returned "
6349                                               "during sanitize:");
6350                                         scsi_sense_print(device, &ccb->csio,
6351                                                          stderr);
6352                                         warnx("Unable to print status "
6353                                               "information, but sanitze will "
6354                                               "proceed.");
6355                                         warnx("will exit when sanitize is "
6356                                               "complete");
6357                                 }
6358                                 sleep(1);
6359                         } else {
6360                                 warnx("Unexpected SCSI error during sanitize");
6361                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6362                                                 CAM_EPF_ALL, stderr);
6363                                 error = 1;
6364                                 goto scsisanitize_bailout;
6365                         }
6366
6367                 } else if (status != CAM_REQ_CMP) {
6368                         warnx("Unexpected CAM status %#x", status);
6369                         if (arglist & CAM_ARG_VERBOSE)
6370                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6371                                                 CAM_EPF_ALL, stderr);
6372                         error = 1;
6373                         goto scsisanitize_bailout;
6374                 }
6375         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6376
6377         if (quiet == 0)
6378                 fprintf(stdout, "\nSanitize Complete\n");
6379
6380 scsisanitize_bailout:
6381         if (fd >= 0)
6382                 close(fd);
6383         if (data_ptr != NULL)
6384                 free(data_ptr);
6385         cam_freeccb(ccb);
6386
6387         return(error);
6388 }
6389
6390 static int
6391 scsireportluns(struct cam_device *device, int argc, char **argv,
6392                char *combinedopt, int retry_count, int timeout)
6393 {
6394         union ccb *ccb;
6395         int c, countonly, lunsonly;
6396         struct scsi_report_luns_data *lundata;
6397         int alloc_len;
6398         uint8_t report_type;
6399         uint32_t list_len, i, j;
6400         int retval;
6401
6402         retval = 0;
6403         lundata = NULL;
6404         report_type = RPL_REPORT_DEFAULT;
6405         ccb = cam_getccb(device);
6406
6407         if (ccb == NULL) {
6408                 warnx("%s: error allocating ccb", __func__);
6409                 return (1);
6410         }
6411
6412         bzero(&(&ccb->ccb_h)[1],
6413               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6414
6415         countonly = 0;
6416         lunsonly = 0;
6417
6418         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6419                 switch (c) {
6420                 case 'c':
6421                         countonly++;
6422                         break;
6423                 case 'l':
6424                         lunsonly++;
6425                         break;
6426                 case 'r':
6427                         if (strcasecmp(optarg, "default") == 0)
6428                                 report_type = RPL_REPORT_DEFAULT;
6429                         else if (strcasecmp(optarg, "wellknown") == 0)
6430                                 report_type = RPL_REPORT_WELLKNOWN;
6431                         else if (strcasecmp(optarg, "all") == 0)
6432                                 report_type = RPL_REPORT_ALL;
6433                         else {
6434                                 warnx("%s: invalid report type \"%s\"",
6435                                       __func__, optarg);
6436                                 retval = 1;
6437                                 goto bailout;
6438                         }
6439                         break;
6440                 default:
6441                         break;
6442                 }
6443         }
6444
6445         if ((countonly != 0)
6446          && (lunsonly != 0)) {
6447                 warnx("%s: you can only specify one of -c or -l", __func__);
6448                 retval = 1;
6449                 goto bailout;
6450         }
6451         /*
6452          * According to SPC-4, the allocation length must be at least 16
6453          * bytes -- enough for the header and one LUN.
6454          */
6455         alloc_len = sizeof(*lundata) + 8;
6456
6457 retry:
6458
6459         lundata = malloc(alloc_len);
6460
6461         if (lundata == NULL) {
6462                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6463                 retval = 1;
6464                 goto bailout;
6465         }
6466
6467         scsi_report_luns(&ccb->csio,
6468                          /*retries*/ retry_count,
6469                          /*cbfcnp*/ NULL,
6470                          /*tag_action*/ MSG_SIMPLE_Q_TAG,
6471                          /*select_report*/ report_type,
6472                          /*rpl_buf*/ lundata,
6473                          /*alloc_len*/ alloc_len,
6474                          /*sense_len*/ SSD_FULL_SIZE,
6475                          /*timeout*/ timeout ? timeout : 5000);
6476
6477         /* Disable freezing the device queue */
6478         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6479
6480         if (arglist & CAM_ARG_ERR_RECOVER)
6481                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6482
6483         if (cam_send_ccb(device, ccb) < 0) {
6484                 warn("error sending REPORT LUNS command");
6485
6486                 if (arglist & CAM_ARG_VERBOSE)
6487                         cam_error_print(device, ccb, CAM_ESF_ALL,
6488                                         CAM_EPF_ALL, stderr);
6489
6490                 retval = 1;
6491                 goto bailout;
6492         }
6493
6494         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6495                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6496                 retval = 1;
6497                 goto bailout;
6498         }
6499
6500
6501         list_len = scsi_4btoul(lundata->length);
6502
6503         /*
6504          * If we need to list the LUNs, and our allocation
6505          * length was too short, reallocate and retry.
6506          */
6507         if ((countonly == 0)
6508          && (list_len > (alloc_len - sizeof(*lundata)))) {
6509                 alloc_len = list_len + sizeof(*lundata);
6510                 free(lundata);
6511                 goto retry;
6512         }
6513
6514         if (lunsonly == 0)
6515                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6516                         ((list_len / 8) > 1) ? "s" : "");
6517
6518         if (countonly != 0)
6519                 goto bailout;
6520
6521         for (i = 0; i < (list_len / 8); i++) {
6522                 int no_more;
6523
6524                 no_more = 0;
6525                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6526                         if (j != 0)
6527                                 fprintf(stdout, ",");
6528                         switch (lundata->luns[i].lundata[j] &
6529                                 RPL_LUNDATA_ATYP_MASK) {
6530                         case RPL_LUNDATA_ATYP_PERIPH:
6531                                 if ((lundata->luns[i].lundata[j] &
6532                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6533                                         fprintf(stdout, "%d:",
6534                                                 lundata->luns[i].lundata[j] &
6535                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
6536                                 else if ((j == 0)
6537                                       && ((lundata->luns[i].lundata[j+2] &
6538                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6539                                         no_more = 1;
6540
6541                                 fprintf(stdout, "%d",
6542                                         lundata->luns[i].lundata[j+1]);
6543                                 break;
6544                         case RPL_LUNDATA_ATYP_FLAT: {
6545                                 uint8_t tmplun[2];
6546                                 tmplun[0] = lundata->luns[i].lundata[j] &
6547                                         RPL_LUNDATA_FLAT_LUN_MASK;
6548                                 tmplun[1] = lundata->luns[i].lundata[j+1];
6549
6550                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6551                                 no_more = 1;
6552                                 break;
6553                         }
6554                         case RPL_LUNDATA_ATYP_LUN:
6555                                 fprintf(stdout, "%d:%d:%d",
6556                                         (lundata->luns[i].lundata[j+1] &
6557                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6558                                         lundata->luns[i].lundata[j] &
6559                                         RPL_LUNDATA_LUN_TARG_MASK,
6560                                         lundata->luns[i].lundata[j+1] &
6561                                         RPL_LUNDATA_LUN_LUN_MASK);
6562                                 break;
6563                         case RPL_LUNDATA_ATYP_EXTLUN: {
6564                                 int field_len_code, eam_code;
6565
6566                                 eam_code = lundata->luns[i].lundata[j] &
6567                                         RPL_LUNDATA_EXT_EAM_MASK;
6568                                 field_len_code = (lundata->luns[i].lundata[j] &
6569                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6570
6571                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6572                                  && (field_len_code == 0x00)) {
6573                                         fprintf(stdout, "%d",
6574                                                 lundata->luns[i].lundata[j+1]);
6575                                 } else if ((eam_code ==
6576                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6577                                         && (field_len_code == 0x03)) {
6578                                         uint8_t tmp_lun[8];
6579
6580                                         /*
6581                                          * This format takes up all 8 bytes.
6582                                          * If we aren't starting at offset 0,
6583                                          * that's a bug.
6584                                          */
6585                                         if (j != 0) {
6586                                                 fprintf(stdout, "Invalid "
6587                                                         "offset %d for "
6588                                                         "Extended LUN not "
6589                                                         "specified format", j);
6590                                                 no_more = 1;
6591                                                 break;
6592                                         }
6593                                         bzero(tmp_lun, sizeof(tmp_lun));
6594                                         bcopy(&lundata->luns[i].lundata[j+1],
6595                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
6596                                         fprintf(stdout, "%#jx",
6597                                                (intmax_t)scsi_8btou64(tmp_lun));
6598                                         no_more = 1;
6599                                 } else {
6600                                         fprintf(stderr, "Unknown Extended LUN"
6601                                                 "Address method %#x, length "
6602                                                 "code %#x", eam_code,
6603                                                 field_len_code);
6604                                         no_more = 1;
6605                                 }
6606                                 break;
6607                         }
6608                         default:
6609                                 fprintf(stderr, "Unknown LUN address method "
6610                                         "%#x\n", lundata->luns[i].lundata[0] &
6611                                         RPL_LUNDATA_ATYP_MASK);
6612                                 break;
6613                         }
6614                         /*
6615                          * For the flat addressing method, there are no
6616                          * other levels after it.
6617                          */
6618                         if (no_more != 0)
6619                                 break;
6620                 }
6621                 fprintf(stdout, "\n");
6622         }
6623
6624 bailout:
6625
6626         cam_freeccb(ccb);
6627
6628         free(lundata);
6629
6630         return (retval);
6631 }
6632
6633 static int
6634 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6635                  char *combinedopt, int retry_count, int timeout)
6636 {
6637         union ccb *ccb;
6638         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6639         struct scsi_read_capacity_data rcap;
6640         struct scsi_read_capacity_data_long rcaplong;
6641         uint64_t maxsector;
6642         uint32_t block_len;
6643         int retval;
6644         int c;
6645
6646         blocksizeonly = 0;
6647         humanize = 0;
6648         numblocks = 0;
6649         quiet = 0;
6650         sizeonly = 0;
6651         baseten = 0;
6652         retval = 0;
6653
6654         ccb = cam_getccb(device);
6655
6656         if (ccb == NULL) {
6657                 warnx("%s: error allocating ccb", __func__);
6658                 return (1);
6659         }
6660
6661         bzero(&(&ccb->ccb_h)[1],
6662               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6663
6664         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6665                 switch (c) {
6666                 case 'b':
6667                         blocksizeonly++;
6668                         break;
6669                 case 'h':
6670                         humanize++;
6671                         baseten = 0;
6672                         break;
6673                 case 'H':
6674                         humanize++;
6675                         baseten++;
6676                         break;
6677                 case 'N':
6678                         numblocks++;
6679                         break;
6680                 case 'q':
6681                         quiet++;
6682                         break;
6683                 case 's':
6684                         sizeonly++;
6685                         break;
6686                 default:
6687                         break;
6688                 }
6689         }
6690
6691         if ((blocksizeonly != 0)
6692          && (numblocks != 0)) {
6693                 warnx("%s: you can only specify one of -b or -N", __func__);
6694                 retval = 1;
6695                 goto bailout;
6696         }
6697
6698         if ((blocksizeonly != 0)
6699          && (sizeonly != 0)) {
6700                 warnx("%s: you can only specify one of -b or -s", __func__);
6701                 retval = 1;
6702                 goto bailout;
6703         }
6704
6705         if ((humanize != 0)
6706          && (quiet != 0)) {
6707                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6708                 retval = 1;
6709                 goto bailout;
6710         }
6711
6712         if ((humanize != 0)
6713          && (blocksizeonly != 0)) {
6714                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6715                 retval = 1;
6716                 goto bailout;
6717         }
6718
6719         scsi_read_capacity(&ccb->csio,
6720                            /*retries*/ retry_count,
6721                            /*cbfcnp*/ NULL,
6722                            /*tag_action*/ MSG_SIMPLE_Q_TAG,
6723                            &rcap,
6724                            SSD_FULL_SIZE,
6725                            /*timeout*/ timeout ? timeout : 5000);
6726
6727         /* Disable freezing the device queue */
6728         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6729
6730         if (arglist & CAM_ARG_ERR_RECOVER)
6731                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6732
6733         if (cam_send_ccb(device, ccb) < 0) {
6734                 warn("error sending READ CAPACITY command");
6735
6736                 if (arglist & CAM_ARG_VERBOSE)
6737                         cam_error_print(device, ccb, CAM_ESF_ALL,
6738                                         CAM_EPF_ALL, stderr);
6739
6740                 retval = 1;
6741                 goto bailout;
6742         }
6743
6744         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6745                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6746                 retval = 1;
6747                 goto bailout;
6748         }
6749
6750         maxsector = scsi_4btoul(rcap.addr);
6751         block_len = scsi_4btoul(rcap.length);
6752
6753         /*
6754          * A last block of 2^32-1 means that the true capacity is over 2TB,
6755          * and we need to issue the long READ CAPACITY to get the real
6756          * capacity.  Otherwise, we're all set.
6757          */
6758         if (maxsector != 0xffffffff)
6759                 goto do_print;
6760
6761         scsi_read_capacity_16(&ccb->csio,
6762                               /*retries*/ retry_count,
6763                               /*cbfcnp*/ NULL,
6764                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
6765                               /*lba*/ 0,
6766                               /*reladdr*/ 0,
6767                               /*pmi*/ 0,
6768                               /*rcap_buf*/ (uint8_t *)&rcaplong,
6769                               /*rcap_buf_len*/ sizeof(rcaplong),
6770                               /*sense_len*/ SSD_FULL_SIZE,
6771                               /*timeout*/ timeout ? timeout : 5000);
6772
6773         /* Disable freezing the device queue */
6774         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6775
6776         if (arglist & CAM_ARG_ERR_RECOVER)
6777                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6778
6779         if (cam_send_ccb(device, ccb) < 0) {
6780                 warn("error sending READ CAPACITY (16) command");
6781
6782                 if (arglist & CAM_ARG_VERBOSE)
6783                         cam_error_print(device, ccb, CAM_ESF_ALL,
6784                                         CAM_EPF_ALL, stderr);
6785
6786                 retval = 1;
6787                 goto bailout;
6788         }
6789
6790         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6791                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6792                 retval = 1;
6793                 goto bailout;
6794         }
6795
6796         maxsector = scsi_8btou64(rcaplong.addr);
6797         block_len = scsi_4btoul(rcaplong.length);
6798
6799 do_print:
6800         if (blocksizeonly == 0) {
6801                 /*
6802                  * Humanize implies !quiet, and also implies numblocks.
6803                  */
6804                 if (humanize != 0) {
6805                         char tmpstr[6];
6806                         int64_t tmpbytes;
6807                         int ret;
6808
6809                         tmpbytes = (maxsector + 1) * block_len;
6810                         ret = humanize_number(tmpstr, sizeof(tmpstr),
6811                                               tmpbytes, "", HN_AUTOSCALE,
6812                                               HN_B | HN_DECIMAL |
6813                                               ((baseten != 0) ?
6814                                               HN_DIVISOR_1000 : 0));
6815                         if (ret == -1) {
6816                                 warnx("%s: humanize_number failed!", __func__);
6817                                 retval = 1;
6818                                 goto bailout;
6819                         }
6820                         fprintf(stdout, "Device Size: %s%s", tmpstr,
6821                                 (sizeonly == 0) ?  ", " : "\n");
6822                 } else if (numblocks != 0) {
6823                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6824                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
6825                                 (sizeonly == 0) ? ", " : "\n");
6826                 } else {
6827                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6828                                 "Last Block: " : "", (uintmax_t)maxsector,
6829                                 (sizeonly == 0) ? ", " : "\n");
6830                 }
6831         }
6832         if (sizeonly == 0)
6833                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6834                         "Block Length: " : "", block_len, (quiet == 0) ?
6835                         " bytes" : "");
6836 bailout:
6837         cam_freeccb(ccb);
6838
6839         return (retval);
6840 }
6841
6842 static int
6843 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6844        int retry_count, int timeout)
6845 {
6846         int c, error = 0;
6847         union ccb *ccb;
6848         uint8_t *smp_request = NULL, *smp_response = NULL;
6849         int request_size = 0, response_size = 0;
6850         int fd_request = 0, fd_response = 0;
6851         char *datastr = NULL;
6852         struct get_hook hook;
6853         int retval;
6854         int flags = 0;
6855
6856         /*
6857          * Note that at the moment we don't support sending SMP CCBs to
6858          * devices that aren't probed by CAM.
6859          */
6860         ccb = cam_getccb(device);
6861         if (ccb == NULL) {
6862                 warnx("%s: error allocating CCB", __func__);
6863                 return (1);
6864         }
6865
6866         bzero(&(&ccb->ccb_h)[1],
6867               sizeof(union ccb) - sizeof(struct ccb_hdr));
6868
6869         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6870                 switch (c) {
6871                 case 'R':
6872                         arglist |= CAM_ARG_CMD_IN;
6873                         response_size = strtol(optarg, NULL, 0);
6874                         if (response_size <= 0) {
6875                                 warnx("invalid number of response bytes %d",
6876                                       response_size);
6877                                 error = 1;
6878                                 goto smpcmd_bailout;
6879                         }
6880                         hook.argc = argc - optind;
6881                         hook.argv = argv + optind;
6882                         hook.got = 0;
6883                         optind++;
6884                         datastr = cget(&hook, NULL);
6885                         /*
6886                          * If the user supplied "-" instead of a format, he
6887                          * wants the data to be written to stdout.
6888                          */
6889                         if ((datastr != NULL)
6890                          && (datastr[0] == '-'))
6891                                 fd_response = 1;
6892
6893                         smp_response = (u_int8_t *)malloc(response_size);
6894                         if (smp_response == NULL) {
6895                                 warn("can't malloc memory for SMP response");
6896                                 error = 1;
6897                                 goto smpcmd_bailout;
6898                         }
6899                         break;
6900                 case 'r':
6901                         arglist |= CAM_ARG_CMD_OUT;
6902                         request_size = strtol(optarg, NULL, 0);
6903                         if (request_size <= 0) {
6904                                 warnx("invalid number of request bytes %d",
6905                                       request_size);
6906                                 error = 1;
6907                                 goto smpcmd_bailout;
6908                         }
6909                         hook.argc = argc - optind;
6910                         hook.argv = argv + optind;
6911                         hook.got = 0;
6912                         datastr = cget(&hook, NULL);
6913                         smp_request = (u_int8_t *)malloc(request_size);
6914                         if (smp_request == NULL) {
6915                                 warn("can't malloc memory for SMP request");
6916                                 error = 1;
6917                                 goto smpcmd_bailout;
6918                         }
6919                         bzero(smp_request, request_size);
6920                         /*
6921                          * If the user supplied "-" instead of a format, he
6922                          * wants the data to be read from stdin.
6923                          */
6924                         if ((datastr != NULL)
6925                          && (datastr[0] == '-'))
6926                                 fd_request = 1;
6927                         else
6928                                 buff_encode_visit(smp_request, request_size,
6929                                                   datastr,
6930                                                   iget, &hook);
6931                         optind += hook.got;
6932                         break;
6933                 default:
6934                         break;
6935                 }
6936         }
6937
6938         /*
6939          * If fd_data is set, and we're writing to the device, we need to
6940          * read the data the user wants written from stdin.
6941          */
6942         if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6943                 ssize_t amt_read;
6944                 int amt_to_read = request_size;
6945                 u_int8_t *buf_ptr = smp_request;
6946
6947                 for (amt_read = 0; amt_to_read > 0;
6948                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6949                         if (amt_read == -1) {
6950                                 warn("error reading data from stdin");
6951                                 error = 1;
6952                                 goto smpcmd_bailout;
6953                         }
6954                         amt_to_read -= amt_read;
6955                         buf_ptr += amt_read;
6956                 }
6957         }
6958
6959         if (((arglist & CAM_ARG_CMD_IN) == 0)
6960          || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6961                 warnx("%s: need both the request (-r) and response (-R) "
6962                       "arguments", __func__);
6963                 error = 1;
6964                 goto smpcmd_bailout;
6965         }
6966
6967         flags |= CAM_DEV_QFRZDIS;
6968
6969         cam_fill_smpio(&ccb->smpio,
6970                        /*retries*/ retry_count,
6971                        /*cbfcnp*/ NULL,
6972                        /*flags*/ flags,
6973                        /*smp_request*/ smp_request,
6974                        /*smp_request_len*/ request_size,
6975                        /*smp_response*/ smp_response,
6976                        /*smp_response_len*/ response_size,
6977                        /*timeout*/ timeout ? timeout : 5000);
6978
6979         ccb->smpio.flags = SMP_FLAG_NONE;
6980
6981         if (((retval = cam_send_ccb(device, ccb)) < 0)
6982          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6983                 const char warnstr[] = "error sending command";
6984
6985                 if (retval < 0)
6986                         warn(warnstr);
6987                 else
6988                         warnx(warnstr);
6989
6990                 if (arglist & CAM_ARG_VERBOSE) {
6991                         cam_error_print(device, ccb, CAM_ESF_ALL,
6992                                         CAM_EPF_ALL, stderr);
6993                 }
6994         }
6995
6996         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6997          && (response_size > 0)) {
6998                 if (fd_response == 0) {
6999                         buff_decode_visit(smp_response, response_size,
7000                                           datastr, arg_put, NULL);
7001                         fprintf(stdout, "\n");
7002                 } else {
7003                         ssize_t amt_written;
7004                         int amt_to_write = response_size;
7005                         u_int8_t *buf_ptr = smp_response;
7006
7007                         for (amt_written = 0; (amt_to_write > 0) &&
7008                              (amt_written = write(STDOUT_FILENO, buf_ptr,
7009                                                   amt_to_write)) > 0;){
7010                                 amt_to_write -= amt_written;
7011                                 buf_ptr += amt_written;
7012                         }
7013                         if (amt_written == -1) {
7014                                 warn("error writing data to stdout");
7015                                 error = 1;
7016                                 goto smpcmd_bailout;
7017                         } else if ((amt_written == 0)
7018                                 && (amt_to_write > 0)) {
7019                                 warnx("only wrote %u bytes out of %u",
7020                                       response_size - amt_to_write, 
7021                                       response_size);
7022                         }
7023                 }
7024         }
7025 smpcmd_bailout:
7026         if (ccb != NULL)
7027                 cam_freeccb(ccb);
7028
7029         if (smp_request != NULL)
7030                 free(smp_request);
7031
7032         if (smp_response != NULL)
7033                 free(smp_response);
7034
7035         return (error);
7036 }
7037
7038 static int
7039 smpreportgeneral(struct cam_device *device, int argc, char **argv,
7040                  char *combinedopt, int retry_count, int timeout)
7041 {
7042         union ccb *ccb;
7043         struct smp_report_general_request *request = NULL;
7044         struct smp_report_general_response *response = NULL;
7045         struct sbuf *sb = NULL;
7046         int error = 0;
7047         int c, long_response = 0;
7048         int retval;
7049
7050         /*
7051          * Note that at the moment we don't support sending SMP CCBs to
7052          * devices that aren't probed by CAM.
7053          */
7054         ccb = cam_getccb(device);
7055         if (ccb == NULL) {
7056                 warnx("%s: error allocating CCB", __func__);
7057                 return (1);
7058         }
7059
7060         bzero(&(&ccb->ccb_h)[1],
7061               sizeof(union ccb) - sizeof(struct ccb_hdr));
7062
7063         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7064                 switch (c) {
7065                 case 'l':
7066                         long_response = 1;
7067                         break;
7068                 default:
7069                         break;
7070                 }
7071         }
7072         request = malloc(sizeof(*request));
7073         if (request == NULL) {
7074                 warn("%s: unable to allocate %zd bytes", __func__,
7075                      sizeof(*request));
7076                 error = 1;
7077                 goto bailout;
7078         }
7079
7080         response = malloc(sizeof(*response));
7081         if (response == NULL) {
7082                 warn("%s: unable to allocate %zd bytes", __func__,
7083                      sizeof(*response));
7084                 error = 1;
7085                 goto bailout;
7086         }
7087
7088 try_long:
7089         smp_report_general(&ccb->smpio,
7090                            retry_count,
7091                            /*cbfcnp*/ NULL,
7092                            request,
7093                            /*request_len*/ sizeof(*request),
7094                            (uint8_t *)response,
7095                            /*response_len*/ sizeof(*response),
7096                            /*long_response*/ long_response,
7097                            timeout);
7098
7099         if (((retval = cam_send_ccb(device, ccb)) < 0)
7100          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7101                 const char warnstr[] = "error sending command";
7102
7103                 if (retval < 0)
7104                         warn(warnstr);
7105                 else
7106                         warnx(warnstr);
7107
7108                 if (arglist & CAM_ARG_VERBOSE) {
7109                         cam_error_print(device, ccb, CAM_ESF_ALL,
7110                                         CAM_EPF_ALL, stderr);
7111                 }
7112                 error = 1;
7113                 goto bailout;
7114         }
7115
7116         /*
7117          * If the device supports the long response bit, try again and see
7118          * if we can get all of the data.
7119          */
7120         if ((response->long_response & SMP_RG_LONG_RESPONSE)
7121          && (long_response == 0)) {
7122                 ccb->ccb_h.status = CAM_REQ_INPROG;
7123                 bzero(&(&ccb->ccb_h)[1],
7124                       sizeof(union ccb) - sizeof(struct ccb_hdr));
7125                 long_response = 1;
7126                 goto try_long;
7127         }
7128
7129         /*
7130          * XXX KDM detect and decode SMP errors here.
7131          */
7132         sb = sbuf_new_auto();
7133         if (sb == NULL) {
7134                 warnx("%s: error allocating sbuf", __func__);
7135                 goto bailout;
7136         }
7137
7138         smp_report_general_sbuf(response, sizeof(*response), sb);
7139
7140         if (sbuf_finish(sb) != 0) {
7141                 warnx("%s: sbuf_finish", __func__);
7142                 goto bailout;
7143         }
7144
7145         printf("%s", sbuf_data(sb));
7146
7147 bailout:
7148         if (ccb != NULL)
7149                 cam_freeccb(ccb);
7150
7151         if (request != NULL)
7152                 free(request);
7153
7154         if (response != NULL)
7155                 free(response);
7156
7157         if (sb != NULL)
7158                 sbuf_delete(sb);
7159
7160         return (error);
7161 }
7162
7163 static struct camcontrol_opts phy_ops[] = {
7164         {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7165         {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7166         {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7167         {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7168         {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7169         {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7170         {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7171         {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7172         {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7173         {NULL, 0, 0, NULL}
7174 };
7175
7176 static int
7177 smpphycontrol(struct cam_device *device, int argc, char **argv,
7178               char *combinedopt, int retry_count, int timeout)
7179 {
7180         union ccb *ccb;
7181         struct smp_phy_control_request *request = NULL;
7182         struct smp_phy_control_response *response = NULL;
7183         int long_response = 0;
7184         int retval = 0;
7185         int phy = -1;
7186         uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7187         int phy_op_set = 0;
7188         uint64_t attached_dev_name = 0;
7189         int dev_name_set = 0;
7190         uint32_t min_plr = 0, max_plr = 0;
7191         uint32_t pp_timeout_val = 0;
7192         int slumber_partial = 0;
7193         int set_pp_timeout_val = 0;
7194         int c;
7195
7196         /*
7197          * Note that at the moment we don't support sending SMP CCBs to
7198          * devices that aren't probed by CAM.
7199          */
7200         ccb = cam_getccb(device);
7201         if (ccb == NULL) {
7202                 warnx("%s: error allocating CCB", __func__);
7203                 return (1);
7204         }
7205
7206         bzero(&(&ccb->ccb_h)[1],
7207               sizeof(union ccb) - sizeof(struct ccb_hdr));
7208
7209         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7210                 switch (c) {
7211                 case 'a':
7212                 case 'A':
7213                 case 's':
7214                 case 'S': {
7215                         int enable = -1;
7216
7217                         if (strcasecmp(optarg, "enable") == 0)
7218                                 enable = 1;
7219                         else if (strcasecmp(optarg, "disable") == 0)
7220                                 enable = 2;
7221                         else {
7222                                 warnx("%s: Invalid argument %s", __func__,
7223                                       optarg);
7224                                 retval = 1;
7225                                 goto bailout;
7226                         }
7227                         switch (c) {
7228                         case 's':
7229                                 slumber_partial |= enable <<
7230                                                    SMP_PC_SAS_SLUMBER_SHIFT;
7231                                 break;
7232                         case 'S':
7233                                 slumber_partial |= enable <<
7234                                                    SMP_PC_SAS_PARTIAL_SHIFT;
7235                                 break;
7236                         case 'a':
7237                                 slumber_partial |= enable <<
7238                                                    SMP_PC_SATA_SLUMBER_SHIFT;
7239                                 break;
7240                         case 'A':
7241                                 slumber_partial |= enable <<
7242                                                    SMP_PC_SATA_PARTIAL_SHIFT;
7243                                 break;
7244                         default:
7245                                 warnx("%s: programmer error", __func__);
7246                                 retval = 1;
7247                                 goto bailout;
7248                                 break; /*NOTREACHED*/
7249                         }
7250                         break;
7251                 }
7252                 case 'd':
7253                         attached_dev_name = (uintmax_t)strtoumax(optarg,
7254                                                                  NULL,0);
7255                         dev_name_set = 1;
7256                         break;
7257                 case 'l':
7258                         long_response = 1;
7259                         break;
7260                 case 'm':
7261                         /*
7262                          * We don't do extensive checking here, so this
7263                          * will continue to work when new speeds come out.
7264                          */
7265                         min_plr = strtoul(optarg, NULL, 0);
7266                         if ((min_plr == 0)
7267                          || (min_plr > 0xf)) {
7268                                 warnx("%s: invalid link rate %x",
7269                                       __func__, min_plr);
7270                                 retval = 1;
7271                                 goto bailout;
7272                         }
7273                         break;
7274                 case 'M':
7275                         /*
7276                          * We don't do extensive checking here, so this
7277                          * will continue to work when new speeds come out.
7278                          */
7279                         max_plr = strtoul(optarg, NULL, 0);
7280                         if ((max_plr == 0)
7281                          || (max_plr > 0xf)) {
7282                                 warnx("%s: invalid link rate %x",
7283                                       __func__, max_plr);
7284                                 retval = 1;
7285                                 goto bailout;
7286                         }
7287                         break;
7288                 case 'o': {
7289                         camcontrol_optret optreturn;
7290                         cam_argmask argnums;
7291                         const char *subopt;
7292
7293                         if (phy_op_set != 0) {
7294                                 warnx("%s: only one phy operation argument "
7295                                       "(-o) allowed", __func__);
7296                                 retval = 1;
7297                                 goto bailout;
7298                         }
7299
7300                         phy_op_set = 1;
7301
7302                         /*
7303                          * Allow the user to specify the phy operation
7304                          * numerically, as well as with a name.  This will
7305                          * future-proof it a bit, so options that are added
7306                          * in future specs can be used.
7307                          */
7308                         if (isdigit(optarg[0])) {
7309                                 phy_operation = strtoul(optarg, NULL, 0);
7310                                 if ((phy_operation == 0)
7311                                  || (phy_operation > 0xff)) {
7312                                         warnx("%s: invalid phy operation %#x",
7313                                               __func__, phy_operation);
7314                                         retval = 1;
7315                                         goto bailout;
7316                                 }
7317                                 break;
7318                         }
7319                         optreturn = getoption(phy_ops, optarg, &phy_operation,
7320                                               &argnums, &subopt);
7321
7322                         if (optreturn == CC_OR_AMBIGUOUS) {
7323                                 warnx("%s: ambiguous option %s", __func__,
7324                                       optarg);
7325                                 usage(0);
7326                                 retval = 1;
7327                                 goto bailout;
7328                         } else if (optreturn == CC_OR_NOT_FOUND) {
7329                                 warnx("%s: option %s not found", __func__,
7330                                       optarg);
7331                                 usage(0);
7332                                 retval = 1;
7333                                 goto bailout;
7334                         }
7335                         break;
7336                 }
7337                 case 'p':
7338                         phy = atoi(optarg);
7339                         break;
7340                 case 'T':
7341                         pp_timeout_val = strtoul(optarg, NULL, 0);
7342                         if (pp_timeout_val > 15) {
7343                                 warnx("%s: invalid partial pathway timeout "
7344                                       "value %u, need a value less than 16",
7345                                       __func__, pp_timeout_val);
7346                                 retval = 1;
7347                                 goto bailout;
7348                         }
7349                         set_pp_timeout_val = 1;
7350                         break;
7351                 default:
7352                         break;
7353                 }
7354         }
7355
7356         if (phy == -1) {
7357                 warnx("%s: a PHY (-p phy) argument is required",__func__);
7358                 retval = 1;
7359                 goto bailout;
7360         }
7361
7362         if (((dev_name_set != 0)
7363           && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7364          || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7365           && (dev_name_set == 0))) {
7366                 warnx("%s: -d name and -o setdevname arguments both "
7367                       "required to set device name", __func__);
7368                 retval = 1;
7369                 goto bailout;
7370         }
7371
7372         request = malloc(sizeof(*request));
7373         if (request == NULL) {
7374                 warn("%s: unable to allocate %zd bytes", __func__,
7375                      sizeof(*request));
7376                 retval = 1;
7377                 goto bailout;
7378         }
7379
7380         response = malloc(sizeof(*response));
7381         if (response == NULL) {
7382                 warn("%s: unable to allocate %zd bytes", __func__,
7383                      sizeof(*request));
7384                 retval = 1;
7385                 goto bailout;
7386         }
7387
7388         smp_phy_control(&ccb->smpio,
7389                         retry_count,
7390                         /*cbfcnp*/ NULL,
7391                         request,
7392                         sizeof(*request),
7393                         (uint8_t *)response,
7394                         sizeof(*response),
7395                         long_response,
7396                         /*expected_exp_change_count*/ 0,
7397                         phy,
7398                         phy_operation,
7399                         (set_pp_timeout_val != 0) ? 1 : 0,
7400                         attached_dev_name,
7401                         min_plr,
7402                         max_plr,
7403                         slumber_partial,
7404                         pp_timeout_val,
7405                         timeout);
7406
7407         if (((retval = cam_send_ccb(device, ccb)) < 0)
7408          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7409                 const char warnstr[] = "error sending command";
7410
7411                 if (retval < 0)
7412                         warn(warnstr);
7413                 else
7414                         warnx(warnstr);
7415
7416                 if (arglist & CAM_ARG_VERBOSE) {
7417                         /*
7418                          * Use CAM_EPF_NORMAL so we only get one line of
7419                          * SMP command decoding.
7420                          */
7421                         cam_error_print(device, ccb, CAM_ESF_ALL,
7422                                         CAM_EPF_NORMAL, stderr);
7423                 }
7424                 retval = 1;
7425                 goto bailout;
7426         }
7427
7428         /* XXX KDM print out something here for success? */
7429 bailout:
7430         if (ccb != NULL)
7431                 cam_freeccb(ccb);
7432
7433         if (request != NULL)
7434                 free(request);
7435
7436         if (response != NULL)
7437                 free(response);
7438
7439         return (retval);
7440 }
7441
7442 static int
7443 smpmaninfo(struct cam_device *device, int argc, char **argv,
7444            char *combinedopt, int retry_count, int timeout)
7445 {
7446         union ccb *ccb;
7447         struct smp_report_manuf_info_request request;
7448         struct smp_report_manuf_info_response response;
7449         struct sbuf *sb = NULL;
7450         int long_response = 0;
7451         int retval = 0;
7452         int c;
7453
7454         /*
7455          * Note that at the moment we don't support sending SMP CCBs to
7456          * devices that aren't probed by CAM.
7457          */
7458         ccb = cam_getccb(device);
7459         if (ccb == NULL) {
7460                 warnx("%s: error allocating CCB", __func__);
7461                 return (1);
7462         }
7463
7464         bzero(&(&ccb->ccb_h)[1],
7465               sizeof(union ccb) - sizeof(struct ccb_hdr));
7466
7467         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7468                 switch (c) {
7469                 case 'l':
7470                         long_response = 1;
7471                         break;
7472                 default:
7473                         break;
7474                 }
7475         }
7476         bzero(&request, sizeof(request));
7477         bzero(&response, sizeof(response));
7478
7479         smp_report_manuf_info(&ccb->smpio,
7480                               retry_count,
7481                               /*cbfcnp*/ NULL,
7482                               &request,
7483                               sizeof(request),
7484                               (uint8_t *)&response,
7485                               sizeof(response),
7486                               long_response,
7487                               timeout);
7488
7489         if (((retval = cam_send_ccb(device, ccb)) < 0)
7490          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7491                 const char warnstr[] = "error sending command";
7492
7493                 if (retval < 0)
7494                         warn(warnstr);
7495                 else
7496                         warnx(warnstr);
7497
7498                 if (arglist & CAM_ARG_VERBOSE) {
7499                         cam_error_print(device, ccb, CAM_ESF_ALL,
7500                                         CAM_EPF_ALL, stderr);
7501                 }
7502                 retval = 1;
7503                 goto bailout;
7504         }
7505
7506         sb = sbuf_new_auto();
7507         if (sb == NULL) {
7508                 warnx("%s: error allocating sbuf", __func__);
7509                 goto bailout;
7510         }
7511
7512         smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7513
7514         if (sbuf_finish(sb) != 0) {
7515                 warnx("%s: sbuf_finish", __func__);
7516                 goto bailout;
7517         }
7518
7519         printf("%s", sbuf_data(sb));
7520
7521 bailout:
7522
7523         if (ccb != NULL)
7524                 cam_freeccb(ccb);
7525
7526         if (sb != NULL)
7527                 sbuf_delete(sb);
7528
7529         return (retval);
7530 }
7531
7532 static int
7533 getdevid(struct cam_devitem *item)
7534 {
7535         int retval = 0;
7536         union ccb *ccb = NULL;
7537
7538         struct cam_device *dev;
7539
7540         dev = cam_open_btl(item->dev_match.path_id,
7541                            item->dev_match.target_id,
7542                            item->dev_match.target_lun, O_RDWR, NULL);
7543
7544         if (dev == NULL) {
7545                 warnx("%s", cam_errbuf);
7546                 retval = 1;
7547                 goto bailout;
7548         }
7549
7550         item->device_id_len = 0;
7551
7552         ccb = cam_getccb(dev);
7553         if (ccb == NULL) {
7554                 warnx("%s: error allocating CCB", __func__);
7555                 retval = 1;
7556                 goto bailout;
7557         }
7558
7559         bzero(&(&ccb->ccb_h)[1],
7560               sizeof(union ccb) - sizeof(struct ccb_hdr));
7561
7562         /*
7563          * On the first try, we just probe for the size of the data, and
7564          * then allocate that much memory and try again.
7565          */
7566 retry:
7567         ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7568         ccb->ccb_h.flags = CAM_DIR_IN;
7569         ccb->cdai.flags = CDAI_FLAG_NONE;
7570         ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7571         ccb->cdai.bufsiz = item->device_id_len;
7572         if (item->device_id_len != 0)
7573                 ccb->cdai.buf = (uint8_t *)item->device_id;
7574
7575         if (cam_send_ccb(dev, ccb) < 0) {
7576                 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7577                 retval = 1;
7578                 goto bailout;
7579         }
7580
7581         if (ccb->ccb_h.status != CAM_REQ_CMP) {
7582                 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7583                 retval = 1;
7584                 goto bailout;
7585         }
7586
7587         if (item->device_id_len == 0) {
7588                 /*
7589                  * This is our first time through.  Allocate the buffer,
7590                  * and then go back to get the data.
7591                  */
7592                 if (ccb->cdai.provsiz == 0) {
7593                         warnx("%s: invalid .provsiz field returned with "
7594                              "XPT_GDEV_ADVINFO CCB", __func__);
7595                         retval = 1;
7596                         goto bailout;
7597                 }
7598                 item->device_id_len = ccb->cdai.provsiz;
7599                 item->device_id = malloc(item->device_id_len);
7600                 if (item->device_id == NULL) {
7601                         warn("%s: unable to allocate %d bytes", __func__,
7602                              item->device_id_len);
7603                         retval = 1;
7604                         goto bailout;
7605                 }
7606                 ccb->ccb_h.status = CAM_REQ_INPROG;
7607                 goto retry;
7608         }
7609
7610 bailout:
7611         if (dev != NULL)
7612                 cam_close_device(dev);
7613
7614         if (ccb != NULL)
7615                 cam_freeccb(ccb);
7616
7617         return (retval);
7618 }
7619
7620 /*
7621  * XXX KDM merge this code with getdevtree()?
7622  */
7623 static int
7624 buildbusdevlist(struct cam_devlist *devlist)
7625 {
7626         union ccb ccb;
7627         int bufsize, fd = -1;
7628         struct dev_match_pattern *patterns;
7629         struct cam_devitem *item = NULL;
7630         int skip_device = 0;
7631         int retval = 0;
7632
7633         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7634                 warn("couldn't open %s", XPT_DEVICE);
7635                 return(1);
7636         }
7637
7638         bzero(&ccb, sizeof(union ccb));
7639
7640         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7641         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7642         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7643
7644         ccb.ccb_h.func_code = XPT_DEV_MATCH;
7645         bufsize = sizeof(struct dev_match_result) * 100;
7646         ccb.cdm.match_buf_len = bufsize;
7647         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7648         if (ccb.cdm.matches == NULL) {
7649                 warnx("can't malloc memory for matches");
7650                 close(fd);
7651                 return(1);
7652         }
7653         ccb.cdm.num_matches = 0;
7654         ccb.cdm.num_patterns = 2;
7655         ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7656                 ccb.cdm.num_patterns;
7657
7658         patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7659         if (patterns == NULL) {
7660                 warnx("can't malloc memory for patterns");
7661                 retval = 1;
7662                 goto bailout;
7663         }
7664
7665         ccb.cdm.patterns = patterns;
7666         bzero(patterns, ccb.cdm.pattern_buf_len);
7667
7668         patterns[0].type = DEV_MATCH_DEVICE;
7669         patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7670         patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7671         patterns[1].type = DEV_MATCH_PERIPH;
7672         patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7673         patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7674
7675         /*
7676          * We do the ioctl multiple times if necessary, in case there are
7677          * more than 100 nodes in the EDT.
7678          */
7679         do {
7680                 unsigned int i;
7681
7682                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7683                         warn("error sending CAMIOCOMMAND ioctl");
7684                         retval = 1;
7685                         goto bailout;
7686                 }
7687
7688                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7689                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7690                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7691                         warnx("got CAM error %#x, CDM error %d\n",
7692                               ccb.ccb_h.status, ccb.cdm.status);
7693                         retval = 1;
7694                         goto bailout;
7695                 }
7696
7697                 for (i = 0; i < ccb.cdm.num_matches; i++) {
7698                         switch (ccb.cdm.matches[i].type) {
7699                         case DEV_MATCH_DEVICE: {
7700                                 struct device_match_result *dev_result;
7701
7702                                 dev_result = 
7703                                      &ccb.cdm.matches[i].result.device_result;
7704
7705                                 if (dev_result->flags &
7706                                     DEV_RESULT_UNCONFIGURED) {
7707                                         skip_device = 1;
7708                                         break;
7709                                 } else
7710                                         skip_device = 0;
7711
7712                                 item = malloc(sizeof(*item));
7713                                 if (item == NULL) {
7714                                         warn("%s: unable to allocate %zd bytes",
7715                                              __func__, sizeof(*item));
7716                                         retval = 1;
7717                                         goto bailout;
7718                                 }
7719                                 bzero(item, sizeof(*item));
7720                                 bcopy(dev_result, &item->dev_match,
7721                                       sizeof(*dev_result));
7722                                 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7723                                                    links);
7724
7725                                 if (getdevid(item) != 0) {
7726                                         retval = 1;
7727                                         goto bailout;
7728                                 }
7729                                 break;
7730                         }
7731                         case DEV_MATCH_PERIPH: {
7732                                 struct periph_match_result *periph_result;
7733
7734                                 periph_result =
7735                                       &ccb.cdm.matches[i].result.periph_result;
7736
7737                                 if (skip_device != 0)
7738                                         break;
7739                                 item->num_periphs++;
7740                                 item->periph_matches = realloc(
7741                                         item->periph_matches,
7742                                         item->num_periphs *
7743                                         sizeof(struct periph_match_result));
7744                                 if (item->periph_matches == NULL) {
7745                                         warn("%s: error allocating periph "
7746                                              "list", __func__);
7747                                         retval = 1;
7748                                         goto bailout;
7749                                 }
7750                                 bcopy(periph_result, &item->periph_matches[
7751                                       item->num_periphs - 1],
7752                                       sizeof(*periph_result));
7753                                 break;
7754                         }
7755                         default:
7756                                 fprintf(stderr, "%s: unexpected match "
7757                                         "type %d\n", __func__,
7758                                         ccb.cdm.matches[i].type);
7759                                 retval = 1;
7760                                 goto bailout;
7761                                 break; /*NOTREACHED*/
7762                         }
7763                 }
7764         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7765                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7766 bailout:
7767
7768         if (fd != -1)
7769                 close(fd);
7770
7771         free(patterns);
7772
7773         free(ccb.cdm.matches);
7774
7775         if (retval != 0)
7776                 freebusdevlist(devlist);
7777
7778         return (retval);
7779 }
7780
7781 static void
7782 freebusdevlist(struct cam_devlist *devlist)
7783 {
7784         struct cam_devitem *item, *item2;
7785
7786         STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7787                 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7788                               links);
7789                 free(item->device_id);
7790                 free(item->periph_matches);
7791                 free(item);
7792         }
7793 }
7794
7795 static struct cam_devitem *
7796 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7797 {
7798         struct cam_devitem *item;
7799
7800         STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7801                 struct scsi_vpd_id_descriptor *idd;
7802
7803                 /*
7804                  * XXX KDM look for LUN IDs as well?
7805                  */
7806                 idd = scsi_get_devid(item->device_id,
7807                                            item->device_id_len,
7808                                            scsi_devid_is_sas_target);
7809                 if (idd == NULL)
7810                         continue;
7811
7812                 if (scsi_8btou64(idd->identifier) == sasaddr)
7813                         return (item);
7814         }
7815
7816         return (NULL);
7817 }
7818
7819 static int
7820 smpphylist(struct cam_device *device, int argc, char **argv,
7821            char *combinedopt, int retry_count, int timeout)
7822 {
7823         struct smp_report_general_request *rgrequest = NULL;
7824         struct smp_report_general_response *rgresponse = NULL;
7825         struct smp_discover_request *disrequest = NULL;
7826         struct smp_discover_response *disresponse = NULL;
7827         struct cam_devlist devlist;
7828         union ccb *ccb;
7829         int long_response = 0;
7830         int num_phys = 0;
7831         int quiet = 0;
7832         int retval;
7833         int i, c;
7834
7835         /*
7836          * Note that at the moment we don't support sending SMP CCBs to
7837          * devices that aren't probed by CAM.
7838          */
7839         ccb = cam_getccb(device);
7840         if (ccb == NULL) {
7841                 warnx("%s: error allocating CCB", __func__);
7842                 return (1);
7843         }
7844
7845         bzero(&(&ccb->ccb_h)[1],
7846               sizeof(union ccb) - sizeof(struct ccb_hdr));
7847         STAILQ_INIT(&devlist.dev_queue);
7848
7849         rgrequest = malloc(sizeof(*rgrequest));
7850         if (rgrequest == NULL) {
7851                 warn("%s: unable to allocate %zd bytes", __func__,
7852                      sizeof(*rgrequest));
7853                 retval = 1;
7854                 goto bailout;
7855         }
7856
7857         rgresponse = malloc(sizeof(*rgresponse));
7858         if (rgresponse == NULL) {
7859                 warn("%s: unable to allocate %zd bytes", __func__,
7860                      sizeof(*rgresponse));
7861                 retval = 1;
7862                 goto bailout;
7863         }
7864
7865         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7866                 switch (c) {
7867                 case 'l':
7868                         long_response = 1;
7869                         break;
7870                 case 'q':
7871                         quiet = 1;
7872                         break;
7873                 default:
7874                         break;
7875                 }
7876         }
7877
7878         smp_report_general(&ccb->smpio,
7879                            retry_count,
7880                            /*cbfcnp*/ NULL,
7881                            rgrequest,
7882                            /*request_len*/ sizeof(*rgrequest),
7883                            (uint8_t *)rgresponse,
7884                            /*response_len*/ sizeof(*rgresponse),
7885                            /*long_response*/ long_response,
7886                            timeout);
7887
7888         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7889
7890         if (((retval = cam_send_ccb(device, ccb)) < 0)
7891          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7892                 const char warnstr[] = "error sending command";
7893
7894                 if (retval < 0)
7895                         warn(warnstr);
7896                 else
7897                         warnx(warnstr);
7898
7899                 if (arglist & CAM_ARG_VERBOSE) {
7900                         cam_error_print(device, ccb, CAM_ESF_ALL,
7901                                         CAM_EPF_ALL, stderr);
7902                 }
7903                 retval = 1;
7904                 goto bailout;
7905         }
7906
7907         num_phys = rgresponse->num_phys;
7908
7909         if (num_phys == 0) {
7910                 if (quiet == 0)
7911                         fprintf(stdout, "%s: No Phys reported\n", __func__);
7912                 retval = 1;
7913                 goto bailout;
7914         }
7915
7916         devlist.path_id = device->path_id;
7917
7918         retval = buildbusdevlist(&devlist);
7919         if (retval != 0)
7920                 goto bailout;
7921
7922         if (quiet == 0) {
7923                 fprintf(stdout, "%d PHYs:\n", num_phys);
7924                 fprintf(stdout, "PHY  Attached SAS Address\n");
7925         }
7926
7927         disrequest = malloc(sizeof(*disrequest));
7928         if (disrequest == NULL) {
7929                 warn("%s: unable to allocate %zd bytes", __func__,
7930                      sizeof(*disrequest));
7931                 retval = 1;
7932                 goto bailout;
7933         }
7934
7935         disresponse = malloc(sizeof(*disresponse));
7936         if (disresponse == NULL) {
7937                 warn("%s: unable to allocate %zd bytes", __func__,
7938                      sizeof(*disresponse));
7939                 retval = 1;
7940                 goto bailout;
7941         }
7942
7943         for (i = 0; i < num_phys; i++) {
7944                 struct cam_devitem *item;
7945                 struct device_match_result *dev_match;
7946                 char vendor[16], product[48], revision[16];
7947                 char tmpstr[256];
7948                 int j;
7949
7950                 bzero(&(&ccb->ccb_h)[1],
7951                       sizeof(union ccb) - sizeof(struct ccb_hdr));
7952
7953                 ccb->ccb_h.status = CAM_REQ_INPROG;
7954                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7955
7956                 smp_discover(&ccb->smpio,
7957                              retry_count,
7958                              /*cbfcnp*/ NULL,
7959                              disrequest,
7960                              sizeof(*disrequest),
7961                              (uint8_t *)disresponse,
7962                              sizeof(*disresponse),
7963                              long_response,
7964                              /*ignore_zone_group*/ 0,
7965                              /*phy*/ i,
7966                              timeout);
7967
7968                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7969                  || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7970                   && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7971                         const char warnstr[] = "error sending command";
7972
7973                         if (retval < 0)
7974                                 warn(warnstr);
7975                         else
7976                                 warnx(warnstr);
7977
7978                         if (arglist & CAM_ARG_VERBOSE) {
7979                                 cam_error_print(device, ccb, CAM_ESF_ALL,
7980                                                 CAM_EPF_ALL, stderr);
7981                         }
7982                         retval = 1;
7983                         goto bailout;
7984                 }
7985
7986                 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7987                         if (quiet == 0)
7988                                 fprintf(stdout, "%3d  <vacant>\n", i);
7989                         continue;
7990                 }
7991
7992                 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7993                         item = NULL;
7994                 } else {
7995                         item = findsasdevice(&devlist,
7996                             scsi_8btou64(disresponse->attached_sas_address));
7997                 }
7998
7999                 if ((quiet == 0)
8000                  || (item != NULL)) {
8001                         fprintf(stdout, "%3d  0x%016jx", i,
8002                                 (uintmax_t)scsi_8btou64(
8003                                 disresponse->attached_sas_address));
8004                         if (item == NULL) {
8005                                 fprintf(stdout, "\n");
8006                                 continue;
8007                         }
8008                 } else if (quiet != 0)
8009                         continue;
8010
8011                 dev_match = &item->dev_match;
8012
8013                 if (dev_match->protocol == PROTO_SCSI) {
8014                         cam_strvis(vendor, dev_match->inq_data.vendor,
8015                                    sizeof(dev_match->inq_data.vendor),
8016                                    sizeof(vendor));
8017                         cam_strvis(product, dev_match->inq_data.product,
8018                                    sizeof(dev_match->inq_data.product),
8019                                    sizeof(product));
8020                         cam_strvis(revision, dev_match->inq_data.revision,
8021                                    sizeof(dev_match->inq_data.revision),
8022                                    sizeof(revision));
8023                         sprintf(tmpstr, "<%s %s %s>", vendor, product,
8024                                 revision);
8025                 } else if ((dev_match->protocol == PROTO_ATA)
8026                         || (dev_match->protocol == PROTO_SATAPM)) {
8027                         cam_strvis(product, dev_match->ident_data.model,
8028                                    sizeof(dev_match->ident_data.model),
8029                                    sizeof(product));
8030                         cam_strvis(revision, dev_match->ident_data.revision,
8031                                    sizeof(dev_match->ident_data.revision),
8032                                    sizeof(revision));
8033                         sprintf(tmpstr, "<%s %s>", product, revision);
8034                 } else {
8035                         sprintf(tmpstr, "<>");
8036                 }
8037                 fprintf(stdout, "   %-33s ", tmpstr);
8038
8039                 /*
8040                  * If we have 0 periphs, that's a bug...
8041                  */
8042                 if (item->num_periphs == 0) {
8043                         fprintf(stdout, "\n");
8044                         continue;
8045                 }
8046
8047                 fprintf(stdout, "(");
8048                 for (j = 0; j < item->num_periphs; j++) {
8049                         if (j > 0)
8050                                 fprintf(stdout, ",");
8051
8052                         fprintf(stdout, "%s%d",
8053                                 item->periph_matches[j].periph_name,
8054                                 item->periph_matches[j].unit_number);
8055                                 
8056                 }
8057                 fprintf(stdout, ")\n");
8058         }
8059 bailout:
8060         if (ccb != NULL)
8061                 cam_freeccb(ccb);
8062
8063         free(rgrequest);
8064
8065         free(rgresponse);
8066
8067         free(disrequest);
8068
8069         free(disresponse);
8070
8071         freebusdevlist(&devlist);
8072
8073         return (retval);
8074 }
8075
8076 static int
8077 atapm(struct cam_device *device, int argc, char **argv,
8078                  char *combinedopt, int retry_count, int timeout)
8079 {
8080         union ccb *ccb;
8081         int retval = 0;
8082         int t = -1;
8083         int c;
8084         u_char cmd, sc;
8085
8086         ccb = cam_getccb(device);
8087
8088         if (ccb == NULL) {
8089                 warnx("%s: error allocating ccb", __func__);
8090                 return (1);
8091         }
8092
8093         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8094                 switch (c) {
8095                 case 't':
8096                         t = atoi(optarg);
8097                         break;
8098                 default:
8099                         break;
8100                 }
8101         }
8102         if (strcmp(argv[1], "idle") == 0) {
8103                 if (t == -1)
8104                         cmd = ATA_IDLE_IMMEDIATE;
8105                 else
8106                         cmd = ATA_IDLE_CMD;
8107         } else if (strcmp(argv[1], "standby") == 0) {
8108                 if (t == -1)
8109                         cmd = ATA_STANDBY_IMMEDIATE;
8110                 else
8111                         cmd = ATA_STANDBY_CMD;
8112         } else {
8113                 cmd = ATA_SLEEP;
8114                 t = -1;
8115         }
8116
8117         if (t < 0)
8118                 sc = 0;
8119         else if (t <= (240 * 5))
8120                 sc = (t + 4) / 5;
8121         else if (t <= (252 * 5))
8122                 /* special encoding for 21 minutes */
8123                 sc = 252;
8124         else if (t <= (11 * 30 * 60))
8125                 sc = (t - 1) / (30 * 60) + 241;
8126         else
8127                 sc = 253;
8128
8129         retval = ata_do_28bit_cmd(device,
8130             ccb,
8131             /*retries*/retry_count,
8132             /*flags*/CAM_DIR_NONE,
8133             /*protocol*/AP_PROTO_NON_DATA,
8134             /*tag_action*/MSG_SIMPLE_Q_TAG,
8135             /*command*/cmd,
8136             /*features*/0,
8137             /*lba*/0,
8138             /*sector_count*/sc,
8139             /*data_ptr*/NULL,
8140             /*dxfer_len*/0,
8141             /*timeout*/timeout ? timeout : 30 * 1000,
8142             /*quiet*/1);
8143
8144         cam_freeccb(ccb);
8145         return (retval);
8146 }
8147
8148 static int
8149 ataaxm(struct cam_device *device, int argc, char **argv,
8150                  char *combinedopt, int retry_count, int timeout)
8151 {
8152         union ccb *ccb;
8153         int retval = 0;
8154         int l = -1;
8155         int c;
8156         u_char cmd, sc;
8157
8158         ccb = cam_getccb(device);
8159
8160         if (ccb == NULL) {
8161                 warnx("%s: error allocating ccb", __func__);
8162                 return (1);
8163         }
8164
8165         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8166                 switch (c) {
8167                 case 'l':
8168                         l = atoi(optarg);
8169                         break;
8170                 default:
8171                         break;
8172                 }
8173         }
8174         sc = 0;
8175         if (strcmp(argv[1], "apm") == 0) {
8176                 if (l == -1)
8177                         cmd = 0x85;
8178                 else {
8179                         cmd = 0x05;
8180                         sc = l;
8181                 }
8182         } else /* aam */ {
8183                 if (l == -1)
8184                         cmd = 0xC2;
8185                 else {
8186                         cmd = 0x42;
8187                         sc = l;
8188                 }
8189         }
8190
8191         retval = ata_do_28bit_cmd(device,
8192             ccb,
8193             /*retries*/retry_count,
8194             /*flags*/CAM_DIR_NONE,
8195             /*protocol*/AP_PROTO_NON_DATA,
8196             /*tag_action*/MSG_SIMPLE_Q_TAG,
8197             /*command*/ATA_SETFEATURES,
8198             /*features*/cmd,
8199             /*lba*/0,
8200             /*sector_count*/sc,
8201             /*data_ptr*/NULL,
8202             /*dxfer_len*/0,
8203             /*timeout*/timeout ? timeout : 30 * 1000,
8204             /*quiet*/1);
8205
8206         cam_freeccb(ccb);
8207         return (retval);
8208 }
8209
8210 int
8211 scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8212                int show_sa_errors, int sa_set, int service_action,
8213                int timeout_desc, int retry_count, int timeout, int verbosemode,
8214                uint32_t *fill_len, uint8_t **data_ptr)
8215 {
8216         union ccb *ccb = NULL;
8217         uint8_t *buf = NULL;
8218         uint32_t alloc_len = 0, num_opcodes;
8219         uint32_t valid_len = 0;
8220         uint32_t avail_len = 0;
8221         struct scsi_report_supported_opcodes_all *all_hdr;
8222         struct scsi_report_supported_opcodes_one *one;
8223         int options = 0;
8224         int retval = 0;
8225
8226         /*
8227          * Make it clear that we haven't yet allocated or filled anything.
8228          */
8229         *fill_len = 0;
8230         *data_ptr = NULL;
8231
8232         ccb = cam_getccb(device);
8233         if (ccb == NULL) {
8234                 warnx("couldn't allocate CCB");
8235                 retval = 1;
8236                 goto bailout;
8237         }
8238
8239         /* cam_getccb cleans up the header, caller has to zero the payload */
8240         bzero(&(&ccb->ccb_h)[1],
8241               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
8242
8243         if (opcode_set != 0) {
8244                 options |= RSO_OPTIONS_OC;
8245                 num_opcodes = 1;
8246                 alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8247         } else {
8248                 num_opcodes = 256;
8249                 alloc_len = sizeof(*all_hdr) + (num_opcodes *
8250                     sizeof(struct scsi_report_supported_opcodes_descr));
8251         }
8252
8253         if (timeout_desc != 0) {
8254                 options |= RSO_RCTD;
8255                 alloc_len += num_opcodes *
8256                     sizeof(struct scsi_report_supported_opcodes_timeout);
8257         }
8258         
8259         if (sa_set != 0) {
8260                 options |= RSO_OPTIONS_OC_SA;
8261                 if (show_sa_errors != 0)
8262                         options &= ~RSO_OPTIONS_OC;
8263         }
8264
8265 retry_alloc:
8266         if (buf != NULL) {
8267                 free(buf);
8268                 buf = NULL;
8269         } 
8270
8271         buf = malloc(alloc_len);
8272         if (buf == NULL) {
8273                 warn("Unable to allocate %u bytes", alloc_len);
8274                 retval = 1;
8275                 goto bailout;
8276         }
8277         bzero(buf, alloc_len);
8278
8279         scsi_report_supported_opcodes(&ccb->csio,
8280                                       /*retries*/ retry_count,
8281                                       /*cbfcnp*/ NULL,
8282                                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
8283                                       /*options*/ options,
8284                                       /*req_opcode*/ opcode,
8285                                       /*req_service_action*/ service_action,
8286                                       /*data_ptr*/ buf,
8287                                       /*dxfer_len*/ alloc_len,
8288                                       /*sense_len*/ SSD_FULL_SIZE,
8289                                       /*timeout*/ timeout ? timeout : 10000);
8290
8291         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8292
8293         if (retry_count != 0)
8294                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
8295
8296         if (cam_send_ccb(device, ccb) < 0) {
8297                 perror("error sending REPORT SUPPORTED OPERATION CODES");
8298                 retval = 1;
8299                 goto bailout;
8300         }
8301
8302         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8303                 if (verbosemode != 0)
8304                         cam_error_print(device, ccb, CAM_ESF_ALL,
8305                                         CAM_EPF_ALL, stderr);
8306                 
8307                 retval = 1;
8308                 goto bailout;
8309         }
8310
8311         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
8312
8313         if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
8314          && (valid_len >= sizeof(*all_hdr))) {
8315                 all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
8316                 avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
8317         } else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
8318                 && (valid_len >= sizeof(*one))) {
8319                 uint32_t cdb_length;
8320
8321                 one = (struct scsi_report_supported_opcodes_one *)buf;
8322                 cdb_length = scsi_2btoul(one->cdb_length);
8323                 avail_len = sizeof(*one) + cdb_length;
8324                 if (one->support & RSO_ONE_CTDP) {
8325                         struct scsi_report_supported_opcodes_timeout *td;
8326
8327                         td = (struct scsi_report_supported_opcodes_timeout *)
8328                             &buf[avail_len];
8329                         if (valid_len >= (avail_len + sizeof(td->length))) {
8330                                 avail_len += scsi_2btoul(td->length) +
8331                                     sizeof(td->length);
8332                         } else {
8333                                 avail_len += sizeof(*td);
8334                         }
8335                 }
8336         }
8337
8338         /*
8339          * avail_len could be zero if we didn't get enough data back from
8340          * thet target to determine
8341          */
8342         if ((avail_len != 0)
8343          && (avail_len > valid_len)) {
8344                 alloc_len = avail_len;
8345                 goto retry_alloc;
8346         }
8347
8348         *fill_len = valid_len;
8349         *data_ptr = buf;
8350 bailout:
8351         if (retval != 0)
8352                 free(buf);
8353
8354         cam_freeccb(ccb);
8355
8356         return (retval);
8357 }
8358
8359 static int
8360 scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
8361                    int req_sa, uint8_t *buf, uint32_t valid_len)
8362 {
8363         struct scsi_report_supported_opcodes_one *one;
8364         struct scsi_report_supported_opcodes_timeout *td;
8365         uint32_t cdb_len = 0, td_len = 0;
8366         const char *op_desc = NULL;
8367         unsigned int i;
8368         int retval = 0;
8369
8370         one = (struct scsi_report_supported_opcodes_one *)buf;
8371
8372         /*
8373          * If we don't have the full single opcode descriptor, no point in
8374          * continuing.
8375          */
8376         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8377             cdb_length)) {
8378                 warnx("Only %u bytes returned, not enough to verify support",
8379                       valid_len);
8380                 retval = 1;
8381                 goto bailout;
8382         }
8383
8384         op_desc = scsi_op_desc(req_opcode, &device->inq_data);
8385
8386         printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
8387                req_opcode);
8388         if (sa_set != 0)
8389                 printf(", SA 0x%x", req_sa);
8390         printf(": ");
8391
8392         switch (one->support & RSO_ONE_SUP_MASK) {
8393         case RSO_ONE_SUP_UNAVAIL:
8394                 printf("No command support information currently available\n");
8395                 break;
8396         case RSO_ONE_SUP_NOT_SUP:
8397                 printf("Command not supported\n");
8398                 retval = 1;
8399                 goto bailout;
8400                 break; /*NOTREACHED*/
8401         case RSO_ONE_SUP_AVAIL:
8402                 printf("Command is supported, complies with a SCSI standard\n");
8403                 break;
8404         case RSO_ONE_SUP_VENDOR:
8405                 printf("Command is supported, vendor-specific "
8406                        "implementation\n");
8407                 break;
8408         default:
8409                 printf("Unknown command support flags 0x%#x\n",
8410                        one->support & RSO_ONE_SUP_MASK);
8411                 break;
8412         }
8413
8414         /*
8415          * If we don't have the CDB length, it isn't exactly an error, the
8416          * command probably isn't supported.
8417          */
8418         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8419             cdb_usage))
8420                 goto bailout;
8421
8422         cdb_len = scsi_2btoul(one->cdb_length);
8423
8424         /*
8425          * If our valid data doesn't include the full reported length,
8426          * return.  The caller should have detected this and adjusted his
8427          * allocation length to get all of the available data.
8428          */
8429         if (valid_len < sizeof(*one) + cdb_len) {
8430                 retval = 1;
8431                 goto bailout;
8432         }
8433
8434         /*
8435          * If all we have is the opcode, there is no point in printing out
8436          * the usage bitmap.
8437          */
8438         if (cdb_len <= 1) {
8439                 retval = 1;
8440                 goto bailout;
8441         }
8442
8443         printf("CDB usage bitmap:");
8444         for (i = 0; i < cdb_len; i++) {
8445                 printf(" %02x", one->cdb_usage[i]);
8446         }
8447         printf("\n");
8448
8449         /*
8450          * If we don't have a timeout descriptor, we're done.
8451          */
8452         if ((one->support & RSO_ONE_CTDP) == 0)
8453                 goto bailout;
8454
8455         /*
8456          * If we don't have enough valid length to include the timeout
8457          * descriptor length, we're done.
8458          */
8459         if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
8460                 goto bailout;
8461
8462         td = (struct scsi_report_supported_opcodes_timeout *)
8463             &buf[sizeof(*one) + cdb_len];
8464         td_len = scsi_2btoul(td->length);
8465         td_len += sizeof(td->length);
8466
8467         /*
8468          * If we don't have the full timeout descriptor, we're done.
8469          */
8470         if (td_len < sizeof(*td))
8471                 goto bailout;
8472
8473         /*
8474          * If we don't have enough valid length to contain the full timeout
8475          * descriptor, we're done.
8476          */
8477         if (valid_len < (sizeof(*one) + cdb_len + td_len))
8478                 goto bailout;
8479
8480         printf("Timeout information:\n");
8481         printf("Command-specific:    0x%02x\n", td->cmd_specific);
8482         printf("Nominal timeout:     %u seconds\n",
8483                scsi_4btoul(td->nominal_time));
8484         printf("Recommended timeout: %u seconds\n",
8485                scsi_4btoul(td->recommended_time));
8486
8487 bailout:
8488         return (retval);
8489 }
8490
8491 static int
8492 scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
8493                  uint32_t valid_len)
8494 {
8495         struct scsi_report_supported_opcodes_all *hdr;
8496         struct scsi_report_supported_opcodes_descr *desc;
8497         uint32_t avail_len = 0, used_len = 0;
8498         uint8_t *cur_ptr;
8499         int retval = 0;
8500
8501         if (valid_len < sizeof(*hdr)) {
8502                 warnx("%s: not enough returned data (%u bytes) opcode list",
8503                       __func__, valid_len);
8504                 retval = 1;
8505                 goto bailout;
8506         }
8507         hdr = (struct scsi_report_supported_opcodes_all *)buf;
8508         avail_len = scsi_4btoul(hdr->length);
8509         avail_len += sizeof(hdr->length);
8510         /*
8511          * Take the lesser of the amount of data the drive claims is
8512          * available, and the amount of data the HBA says was returned.
8513          */
8514         avail_len = MIN(avail_len, valid_len);
8515
8516         used_len = sizeof(hdr->length);
8517
8518         printf("%-6s %4s %8s ",
8519                "Opcode", "SA", "CDB len" );
8520
8521         if (td_req != 0)
8522                 printf("%5s %6s %6s ", "CS", "Nom", "Rec");
8523         printf(" Description\n");
8524
8525         while ((avail_len - used_len) > sizeof(*desc)) {
8526                 struct scsi_report_supported_opcodes_timeout *td;
8527                 uint32_t td_len;
8528                 const char *op_desc = NULL;
8529
8530                 cur_ptr = &buf[used_len];
8531                 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
8532
8533                 op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
8534                 if (op_desc == NULL)
8535                         op_desc = "UNKNOWN";
8536
8537                 printf("0x%02x   %#4x %8u ", desc->opcode,
8538                        scsi_2btoul(desc->service_action),
8539                        scsi_2btoul(desc->cdb_length));
8540
8541                 used_len += sizeof(*desc);
8542
8543                 if ((desc->flags & RSO_CTDP) == 0) {
8544                         printf(" %s\n", op_desc);
8545                         continue;
8546                 }
8547
8548                 /*
8549                  * If we don't have enough space to fit a timeout
8550                  * descriptor, then we're done.
8551                  */
8552                 if (avail_len - used_len < sizeof(*td)) {
8553                         used_len = avail_len;
8554                         printf(" %s\n", op_desc);
8555                         continue;
8556                 }
8557                 cur_ptr = &buf[used_len];
8558                 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
8559                 td_len = scsi_2btoul(td->length);
8560                 td_len += sizeof(td->length);
8561
8562                 used_len += td_len;
8563                 /*
8564                  * If the given timeout descriptor length is less than what
8565                  * we understand, skip it.
8566                  */
8567                 if (td_len < sizeof(*td)) {
8568                         printf(" %s\n", op_desc);
8569                         continue;
8570                 }
8571
8572                 printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
8573                        scsi_4btoul(td->nominal_time),
8574                        scsi_4btoul(td->recommended_time), op_desc);
8575         }
8576 bailout:
8577         return (retval);
8578 }
8579
8580 static int
8581 scsiopcodes(struct cam_device *device, int argc, char **argv,
8582             char *combinedopt, int retry_count, int timeout, int verbosemode)
8583 {
8584         int c;
8585         uint32_t opcode = 0, service_action = 0;
8586         int td_set = 0, opcode_set = 0, sa_set = 0;
8587         int show_sa_errors = 1;
8588         uint32_t valid_len = 0;
8589         uint8_t *buf = NULL;
8590         char *endptr;
8591         int retval = 0;
8592
8593         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8594                 switch (c) {
8595                 case 'N':
8596                         show_sa_errors = 0;
8597                         break;
8598                 case 'o':
8599                         opcode = strtoul(optarg, &endptr, 0);
8600                         if (*endptr != '\0') {
8601                                 warnx("Invalid opcode \"%s\", must be a number",
8602                                       optarg);
8603                                 retval = 1;
8604                                 goto bailout;
8605                         }
8606                         if (opcode > 0xff) {
8607                                 warnx("Invalid opcode 0x%#x, must be between"
8608                                       "0 and 0xff inclusive", opcode);
8609                                 retval = 1;
8610                                 goto bailout;
8611                         }
8612                         opcode_set = 1;
8613                         break;
8614                 case 's':
8615                         service_action = strtoul(optarg, &endptr, 0);
8616                         if (*endptr != '\0') {
8617                                 warnx("Invalid service action \"%s\", must "
8618                                       "be a number", optarg);
8619                                 retval = 1;
8620                                 goto bailout;
8621                         }
8622                         if (service_action > 0xffff) {
8623                                 warnx("Invalid service action 0x%#x, must "
8624                                       "be between 0 and 0xffff inclusive",
8625                                       service_action);
8626                                 retval = 1;
8627                         }
8628                         sa_set = 1;
8629                         break;
8630                 case 'T':
8631                         td_set = 1;
8632                         break;
8633                 default:
8634                         break;
8635                 }
8636         }
8637
8638         if ((sa_set != 0)
8639          && (opcode_set == 0)) {
8640                 warnx("You must specify an opcode with -o if a service "
8641                       "action is given");
8642                 retval = 1;
8643                 goto bailout;
8644         }
8645         retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
8646                                 sa_set, service_action, td_set, retry_count,
8647                                 timeout, verbosemode, &valid_len, &buf);
8648         if (retval != 0)
8649                 goto bailout;
8650
8651         if ((opcode_set != 0)
8652          || (sa_set != 0)) {
8653                 retval = scsiprintoneopcode(device, opcode, sa_set,
8654                                             service_action, buf, valid_len);
8655         } else {
8656                 retval = scsiprintopcodes(device, td_set, buf, valid_len);
8657         }
8658
8659 bailout:
8660         free(buf);
8661
8662         return (retval);
8663 }
8664
8665 #endif /* MINIMALISTIC */
8666
8667 static int
8668 scsireprobe(struct cam_device *device)
8669 {
8670         union ccb *ccb;
8671         int retval = 0;
8672
8673         ccb = cam_getccb(device);
8674
8675         if (ccb == NULL) {
8676                 warnx("%s: error allocating ccb", __func__);
8677                 return (1);
8678         }
8679
8680         bzero(&(&ccb->ccb_h)[1],
8681               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
8682
8683         ccb->ccb_h.func_code = XPT_REPROBE_LUN;
8684
8685         if (cam_send_ccb(device, ccb) < 0) {
8686                 warn("error sending XPT_REPROBE_LUN CCB");
8687                 retval = 1;
8688                 goto bailout;
8689         }
8690
8691         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8692                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
8693                 retval = 1;
8694                 goto bailout;
8695         }
8696
8697 bailout:
8698         cam_freeccb(ccb);
8699
8700         return (retval);
8701 }
8702
8703 void
8704 usage(int printlong)
8705 {
8706
8707         fprintf(printlong ? stdout : stderr,
8708 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
8709 "        camcontrol devlist    [-b] [-v]\n"
8710 #ifndef MINIMALISTIC
8711 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8712 "        camcontrol tur        [dev_id][generic args]\n"
8713 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
8714 "        camcontrol identify   [dev_id][generic args] [-v]\n"
8715 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8716 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8717 "                              [-q] [-s]\n"
8718 "        camcontrol start      [dev_id][generic args]\n"
8719 "        camcontrol stop       [dev_id][generic args]\n"
8720 "        camcontrol load       [dev_id][generic args]\n"
8721 "        camcontrol eject      [dev_id][generic args]\n"
8722 "        camcontrol reprobe    [dev_id][generic args]\n"
8723 #endif /* MINIMALISTIC */
8724 "        camcontrol rescan     <all | bus[:target:lun]>\n"
8725 "        camcontrol reset      <all | bus[:target:lun]>\n"
8726 #ifndef MINIMALISTIC
8727 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
8728 "                              [-q][-s][-S offset][-X]\n"
8729 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
8730 "                              [-P pagectl][-e | -b][-d]\n"
8731 "        camcontrol cmd        [dev_id][generic args]\n"
8732 "                              <-a cmd [args] | -c cmd [args]>\n"
8733 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8734 "        camcontrol smpcmd     [dev_id][generic args]\n"
8735 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
8736 "        camcontrol smprg      [dev_id][generic args][-l]\n"
8737 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
8738 "                              [-o operation][-d name][-m rate][-M rate]\n"
8739 "                              [-T pp_timeout][-a enable|disable]\n"
8740 "                              [-A enable|disable][-s enable|disable]\n"
8741 "                              [-S enable|disable]\n"
8742 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8743 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8744 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
8745 "                              <all|bus[:target[:lun]]|off>\n"
8746 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
8747 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
8748 "                              [-D <enable|disable>][-M mode][-O offset]\n"
8749 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
8750 "                              [-U][-W bus_width]\n"
8751 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
8752 "        camcontrol sanitize   [dev_id][generic args]\n"
8753 "                              [-a overwrite|block|crypto|exitfailure]\n"
8754 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8755 "                              [-y]\n"
8756 "        camcontrol idle       [dev_id][generic args][-t time]\n"
8757 "        camcontrol standby    [dev_id][generic args][-t time]\n"
8758 "        camcontrol sleep      [dev_id][generic args]\n"
8759 "        camcontrol apm        [dev_id][generic args][-l level]\n"
8760 "        camcontrol aam        [dev_id][generic args][-l level]\n"
8761 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
8762 "                              [-s][-y]\n"
8763 "        camcontrol security   [dev_id][generic args]\n"
8764 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8765 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8766 "                              [-U <user|master>] [-y]\n"
8767 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8768 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
8769 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
8770 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8771 "                              [-s scope][-S][-T type][-U]\n"
8772 "        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
8773 "                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
8774 "                              [-p part][-s start][-T type][-V vol]\n"
8775 "        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
8776 "                              [-N][-T]\n"
8777 #endif /* MINIMALISTIC */
8778 "        camcontrol help\n");
8779         if (!printlong)
8780                 return;
8781 #ifndef MINIMALISTIC
8782         fprintf(stdout,
8783 "Specify one of the following options:\n"
8784 "devlist     list all CAM devices\n"
8785 "periphlist  list all CAM peripheral drivers attached to a device\n"
8786 "tur         send a test unit ready to the named device\n"
8787 "inquiry     send a SCSI inquiry command to the named device\n"
8788 "identify    send a ATA identify command to the named device\n"
8789 "reportluns  send a SCSI report luns command to the device\n"
8790 "readcap     send a SCSI read capacity command to the device\n"
8791 "start       send a Start Unit command to the device\n"
8792 "stop        send a Stop Unit command to the device\n"
8793 "load        send a Start Unit command to the device with the load bit set\n"
8794 "eject       send a Stop Unit command to the device with the eject bit set\n"
8795 "reprobe     update capacity information of the given device\n"
8796 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
8797 "reset       reset all busses, the given bus, or bus:target:lun\n"
8798 "defects     read the defect list of the specified device\n"
8799 "modepage    display or edit (-e) the given mode page\n"
8800 "cmd         send the given SCSI command, may need -i or -o as well\n"
8801 "smpcmd      send the given SMP command, requires -o and -i\n"
8802 "smprg       send the SMP Report General command\n"
8803 "smppc       send the SMP PHY Control command, requires -p\n"
8804 "smpphylist  display phys attached to a SAS expander\n"
8805 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
8806 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
8807 "tags        report or set the number of transaction slots for a device\n"
8808 "negotiate   report or set device negotiation parameters\n"
8809 "format      send the SCSI FORMAT UNIT command to the named device\n"
8810 "sanitize    send the SCSI SANITIZE command to the named device\n"
8811 "idle        send the ATA IDLE command to the named device\n"
8812 "standby     send the ATA STANDBY command to the named device\n"
8813 "sleep       send the ATA SLEEP command to the named device\n"
8814 "fwdownload  program firmware of the named device with the given image\n"
8815 "security    report or send ATA security commands to the named device\n"
8816 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8817 "attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
8818 "opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
8819 "help        this message\n"
8820 "Device Identifiers:\n"
8821 "bus:target        specify the bus and target, lun defaults to 0\n"
8822 "bus:target:lun    specify the bus, target and lun\n"
8823 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
8824 "Generic arguments:\n"
8825 "-v                be verbose, print out sense information\n"
8826 "-t timeout        command timeout in seconds, overrides default timeout\n"
8827 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
8828 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
8829 "-E                have the kernel attempt to perform SCSI error recovery\n"
8830 "-C count          specify the SCSI command retry count (needs -E to work)\n"
8831 "modepage arguments:\n"
8832 "-l                list all available mode pages\n"
8833 "-m page           specify the mode page to view or edit\n"
8834 "-e                edit the specified mode page\n"
8835 "-b                force view to binary mode\n"
8836 "-d                disable block descriptors for mode sense\n"
8837 "-P pgctl          page control field 0-3\n"
8838 "defects arguments:\n"
8839 "-f format         specify defect list format (block, bfi or phys)\n"
8840 "-G                get the grown defect list\n"
8841 "-P                get the permanent defect list\n"
8842 "inquiry arguments:\n"
8843 "-D                get the standard inquiry data\n"
8844 "-S                get the serial number\n"
8845 "-R                get the transfer rate, etc.\n"
8846 "reportluns arguments:\n"
8847 "-c                only report a count of available LUNs\n"
8848 "-l                only print out luns, and not a count\n"
8849 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
8850 "readcap arguments\n"
8851 "-b                only report the blocksize\n"
8852 "-h                human readable device size, base 2\n"
8853 "-H                human readable device size, base 10\n"
8854 "-N                print the number of blocks instead of last block\n"
8855 "-q                quiet, print numbers only\n"
8856 "-s                only report the last block/device size\n"
8857 "cmd arguments:\n"
8858 "-c cdb [args]     specify the SCSI CDB\n"
8859 "-i len fmt        specify input data and input data format\n"
8860 "-o len fmt [args] specify output data and output data fmt\n"
8861 "smpcmd arguments:\n"
8862 "-r len fmt [args] specify the SMP command to be sent\n"
8863 "-R len fmt [args] specify SMP response format\n"
8864 "smprg arguments:\n"
8865 "-l                specify the long response format\n"
8866 "smppc arguments:\n"
8867 "-p phy            specify the PHY to operate on\n"
8868 "-l                specify the long request/response format\n"
8869 "-o operation      specify the phy control operation\n"
8870 "-d name           set the attached device name\n"
8871 "-m rate           set the minimum physical link rate\n"
8872 "-M rate           set the maximum physical link rate\n"
8873 "-T pp_timeout     set the partial pathway timeout value\n"
8874 "-a enable|disable enable or disable SATA slumber\n"
8875 "-A enable|disable enable or disable SATA partial phy power\n"
8876 "-s enable|disable enable or disable SAS slumber\n"
8877 "-S enable|disable enable or disable SAS partial phy power\n"
8878 "smpphylist arguments:\n"
8879 "-l                specify the long response format\n"
8880 "-q                only print phys with attached devices\n"
8881 "smpmaninfo arguments:\n"
8882 "-l                specify the long response format\n"
8883 "debug arguments:\n"
8884 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
8885 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
8886 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
8887 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
8888 "tags arguments:\n"
8889 "-N tags           specify the number of tags to use for this device\n"
8890 "-q                be quiet, don't report the number of tags\n"
8891 "-v                report a number of tag-related parameters\n"
8892 "negotiate arguments:\n"
8893 "-a                send a test unit ready after negotiation\n"
8894 "-c                report/set current negotiation settings\n"
8895 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
8896 "-M mode           set ATA mode\n"
8897 "-O offset         set command delay offset\n"
8898 "-q                be quiet, don't report anything\n"
8899 "-R syncrate       synchronization rate in MHz\n"
8900 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
8901 "-U                report/set user negotiation settings\n"
8902 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
8903 "-v                also print a Path Inquiry CCB for the controller\n"
8904 "format arguments:\n"
8905 "-q                be quiet, don't print status messages\n"
8906 "-r                run in report only mode\n"
8907 "-w                don't send immediate format command\n"
8908 "-y                don't ask any questions\n"
8909 "sanitize arguments:\n"
8910 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
8911 "-c passes         overwrite passes to perform (1 to 31)\n"
8912 "-I                invert overwrite pattern after each pass\n"
8913 "-P pattern        path to overwrite pattern file\n"
8914 "-q                be quiet, don't print status messages\n"
8915 "-r                run in report only mode\n"
8916 "-U                run operation in unrestricted completion exit mode\n"
8917 "-w                don't send immediate sanitize command\n"
8918 "-y                don't ask any questions\n"
8919 "idle/standby arguments:\n"
8920 "-t <arg>          number of seconds before respective state.\n"
8921 "fwdownload arguments:\n"
8922 "-f fw_image       path to firmware image file\n"
8923 "-q                don't print informational messages, only errors\n"
8924 "-s                run in simulation mode\n"
8925 "-v                print info for every firmware segment sent to device\n"
8926 "-y                don't ask any questions\n"
8927 "security arguments:\n"
8928 "-d pwd            disable security using the given password for the selected\n"
8929 "                  user\n"
8930 "-e pwd            erase the device using the given pwd for the selected user\n"
8931 "-f                freeze the security configuration of the specified device\n"
8932 "-h pwd            enhanced erase the device using the given pwd for the\n"
8933 "                  selected user\n"
8934 "-k pwd            unlock the device using the given pwd for the selected\n"
8935 "                  user\n"
8936 "-l <high|maximum> specifies which security level to set: high or maximum\n"
8937 "-q                be quiet, do not print any status messages\n"
8938 "-s pwd            password the device (enable security) using the given\n"
8939 "                  pwd for the selected user\n"
8940 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
8941 "-U <user|master>  specifies which user to set: user or master\n"
8942 "-y                don't ask any questions\n"
8943 "hpa arguments:\n"
8944 "-f                freeze the HPA configuration of the device\n"
8945 "-l                lock the HPA configuration of the device\n"
8946 "-P                make the HPA max sectors persist\n"
8947 "-p pwd            Set the HPA configuration password required for unlock\n"
8948 "                  calls\n"
8949 "-q                be quiet, do not print any status messages\n"
8950 "-s sectors        configures the maximum user accessible sectors of the\n"
8951 "                  device\n"
8952 "-U pwd            unlock the HPA configuration of the device\n"
8953 "-y                don't ask any questions\n"
8954 "persist arguments:\n"
8955 "-i action         specify read_keys, read_reservation, report_cap, or\n"
8956 "                  read_full_status\n"
8957 "-o action         specify register, register_ignore, reserve, release,\n"
8958 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
8959 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
8960 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8961 "-k key            specify the Reservation Key\n"
8962 "-K sa_key         specify the Service Action Reservation Key\n"
8963 "-p                set the Activate Persist Through Power Loss bit\n"
8964 "-R rtp            specify the Relative Target Port\n"
8965 "-s scope          specify the scope: lun, extent, element or a number\n"
8966 "-S                specify Transport ID for register, requires -I\n"
8967 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8968 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8969 "-U                unregister the current initiator for register_move\n"
8970 "attrib arguments:\n"
8971 "-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
8972 "                  supp_attr\n"
8973 "-w attr           specify an attribute to write, one -w argument per attr\n"
8974 "-a attr_num       only display this attribute number\n"
8975 "-c                get cached attributes\n"
8976 "-e elem_addr      request attributes for the given element in a changer\n"
8977 "-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
8978 "                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
8979 "                  field_none, field_desc, field_num, field_size, field_rw\n"
8980 "-p partition      request attributes for the given partition\n"
8981 "-s start_attr     request attributes starting at the given number\n"
8982 "-T elem_type      specify the element type (used with -e)\n"
8983 "-V logical_vol    specify the logical volume ID\n"
8984 "opcodes arguments:\n"
8985 "-o opcode         specify the individual opcode to list\n"
8986 "-s service_action specify the service action for the opcode\n"
8987 "-N                do not return SCSI error for unsupported SA\n"
8988 "-T                request nominal and recommended timeout values\n"
8989 );
8990 #endif /* MINIMALISTIC */
8991 }
8992
8993 int
8994 main(int argc, char **argv)
8995 {
8996         int c;
8997         char *device = NULL;
8998         int unit = 0;
8999         struct cam_device *cam_dev = NULL;
9000         int timeout = 0, retry_count = 1;
9001         camcontrol_optret optreturn;
9002         char *tstr;
9003         const char *mainopt = "C:En:t:u:v";
9004         const char *subopt = NULL;
9005         char combinedopt[256];
9006         int error = 0, optstart = 2;
9007         int devopen = 1;
9008 #ifndef MINIMALISTIC
9009         path_id_t bus;
9010         target_id_t target;
9011         lun_id_t lun;
9012 #endif /* MINIMALISTIC */
9013
9014         cmdlist = CAM_CMD_NONE;
9015         arglist = CAM_ARG_NONE;
9016
9017         if (argc < 2) {
9018                 usage(0);
9019                 exit(1);
9020         }
9021
9022         /*
9023          * Get the base option.
9024          */
9025         optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
9026
9027         if (optreturn == CC_OR_AMBIGUOUS) {
9028                 warnx("ambiguous option %s", argv[1]);
9029                 usage(0);
9030                 exit(1);
9031         } else if (optreturn == CC_OR_NOT_FOUND) {
9032                 warnx("option %s not found", argv[1]);
9033                 usage(0);
9034                 exit(1);
9035         }
9036
9037         /*
9038          * Ahh, getopt(3) is a pain.
9039          *
9040          * This is a gross hack.  There really aren't many other good
9041          * options (excuse the pun) for parsing options in a situation like
9042          * this.  getopt is kinda braindead, so you end up having to run
9043          * through the options twice, and give each invocation of getopt
9044          * the option string for the other invocation.
9045          *
9046          * You would think that you could just have two groups of options.
9047          * The first group would get parsed by the first invocation of
9048          * getopt, and the second group would get parsed by the second
9049          * invocation of getopt.  It doesn't quite work out that way.  When
9050          * the first invocation of getopt finishes, it leaves optind pointing
9051          * to the argument _after_ the first argument in the second group.
9052          * So when the second invocation of getopt comes around, it doesn't
9053          * recognize the first argument it gets and then bails out.
9054          *
9055          * A nice alternative would be to have a flag for getopt that says
9056          * "just keep parsing arguments even when you encounter an unknown
9057          * argument", but there isn't one.  So there's no real clean way to
9058          * easily parse two sets of arguments without having one invocation
9059          * of getopt know about the other.
9060          *
9061          * Without this hack, the first invocation of getopt would work as
9062          * long as the generic arguments are first, but the second invocation
9063          * (in the subfunction) would fail in one of two ways.  In the case
9064          * where you don't set optreset, it would fail because optind may be
9065          * pointing to the argument after the one it should be pointing at.
9066          * In the case where you do set optreset, and reset optind, it would
9067          * fail because getopt would run into the first set of options, which
9068          * it doesn't understand.
9069          *
9070          * All of this would "sort of" work if you could somehow figure out
9071          * whether optind had been incremented one option too far.  The
9072          * mechanics of that, however, are more daunting than just giving
9073          * both invocations all of the expect options for either invocation.
9074          *
9075          * Needless to say, I wouldn't mind if someone invented a better
9076          * (non-GPL!) command line parsing interface than getopt.  I
9077          * wouldn't mind if someone added more knobs to getopt to make it
9078          * work better.  Who knows, I may talk myself into doing it someday,
9079          * if the standards weenies let me.  As it is, it just leads to
9080          * hackery like this and causes people to avoid it in some cases.
9081          *
9082          * KDM, September 8th, 1998
9083          */
9084         if (subopt != NULL)
9085                 sprintf(combinedopt, "%s%s", mainopt, subopt);
9086         else
9087                 sprintf(combinedopt, "%s", mainopt);
9088
9089         /*
9090          * For these options we do not parse optional device arguments and
9091          * we do not open a passthrough device.
9092          */
9093         if ((cmdlist == CAM_CMD_RESCAN)
9094          || (cmdlist == CAM_CMD_RESET)
9095          || (cmdlist == CAM_CMD_DEVTREE)
9096          || (cmdlist == CAM_CMD_USAGE)
9097          || (cmdlist == CAM_CMD_DEBUG))
9098                 devopen = 0;
9099
9100 #ifndef MINIMALISTIC
9101         if ((devopen == 1)
9102          && (argc > 2 && argv[2][0] != '-')) {
9103                 char name[30];
9104                 int rv;
9105
9106                 if (isdigit(argv[2][0])) {
9107                         /* device specified as bus:target[:lun] */
9108                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9109                         if (rv < 2)
9110                                 errx(1, "numeric device specification must "
9111                                      "be either bus:target, or "
9112                                      "bus:target:lun");
9113                         /* default to 0 if lun was not specified */
9114                         if ((arglist & CAM_ARG_LUN) == 0) {
9115                                 lun = 0;
9116                                 arglist |= CAM_ARG_LUN;
9117                         }
9118                         optstart++;
9119                 } else {
9120                         if (cam_get_device(argv[2], name, sizeof name, &unit)
9121                             == -1)
9122                                 errx(1, "%s", cam_errbuf);
9123                         device = strdup(name);
9124                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9125                         optstart++;
9126                 }
9127         }
9128 #endif /* MINIMALISTIC */
9129         /*
9130          * Start getopt processing at argv[2/3], since we've already
9131          * accepted argv[1..2] as the command name, and as a possible
9132          * device name.
9133          */
9134         optind = optstart;
9135
9136         /*
9137          * Now we run through the argument list looking for generic
9138          * options, and ignoring options that possibly belong to
9139          * subfunctions.
9140          */
9141         while ((c = getopt(argc, argv, combinedopt))!= -1){
9142                 switch(c) {
9143                         case 'C':
9144                                 retry_count = strtol(optarg, NULL, 0);
9145                                 if (retry_count < 0)
9146                                         errx(1, "retry count %d is < 0",
9147                                              retry_count);
9148                                 arglist |= CAM_ARG_RETRIES;
9149                                 break;
9150                         case 'E':
9151                                 arglist |= CAM_ARG_ERR_RECOVER;
9152                                 break;
9153                         case 'n':
9154                                 arglist |= CAM_ARG_DEVICE;
9155                                 tstr = optarg;
9156                                 while (isspace(*tstr) && (*tstr != '\0'))
9157                                         tstr++;
9158                                 device = (char *)strdup(tstr);
9159                                 break;
9160                         case 't':
9161                                 timeout = strtol(optarg, NULL, 0);
9162                                 if (timeout < 0)
9163                                         errx(1, "invalid timeout %d", timeout);
9164                                 /* Convert the timeout from seconds to ms */
9165                                 timeout *= 1000;
9166                                 arglist |= CAM_ARG_TIMEOUT;
9167                                 break;
9168                         case 'u':
9169                                 arglist |= CAM_ARG_UNIT;
9170                                 unit = strtol(optarg, NULL, 0);
9171                                 break;
9172                         case 'v':
9173                                 arglist |= CAM_ARG_VERBOSE;
9174                                 break;
9175                         default:
9176                                 break;
9177                 }
9178         }
9179
9180 #ifndef MINIMALISTIC
9181         /*
9182          * For most commands we'll want to open the passthrough device
9183          * associated with the specified device.  In the case of the rescan
9184          * commands, we don't use a passthrough device at all, just the
9185          * transport layer device.
9186          */
9187         if (devopen == 1) {
9188                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
9189                  && (((arglist & CAM_ARG_DEVICE) == 0)
9190                   || ((arglist & CAM_ARG_UNIT) == 0))) {
9191                         errx(1, "subcommand \"%s\" requires a valid device "
9192                              "identifier", argv[1]);
9193                 }
9194
9195                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
9196                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
9197                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
9198                      == NULL)
9199                         errx(1,"%s", cam_errbuf);
9200         }
9201 #endif /* MINIMALISTIC */
9202
9203         /*
9204          * Reset optind to 2, and reset getopt, so these routines can parse
9205          * the arguments again.
9206          */
9207         optind = optstart;
9208         optreset = 1;
9209
9210         switch(cmdlist) {
9211 #ifndef MINIMALISTIC
9212                 case CAM_CMD_DEVLIST:
9213                         error = getdevlist(cam_dev);
9214                         break;
9215                 case CAM_CMD_HPA:
9216                         error = atahpa(cam_dev, retry_count, timeout,
9217                                        argc, argv, combinedopt);
9218                         break;
9219 #endif /* MINIMALISTIC */
9220                 case CAM_CMD_DEVTREE:
9221                         error = getdevtree(argc, argv, combinedopt);
9222                         break;
9223 #ifndef MINIMALISTIC
9224                 case CAM_CMD_TUR:
9225                         error = testunitready(cam_dev, retry_count, timeout, 0);
9226                         break;
9227                 case CAM_CMD_INQUIRY:
9228                         error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
9229                                               retry_count, timeout);
9230                         break;
9231                 case CAM_CMD_IDENTIFY:
9232                         error = ataidentify(cam_dev, retry_count, timeout);
9233                         break;
9234                 case CAM_CMD_STARTSTOP:
9235                         error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
9236                                           arglist & CAM_ARG_EJECT, retry_count,
9237                                           timeout);
9238                         break;
9239 #endif /* MINIMALISTIC */
9240                 case CAM_CMD_RESCAN:
9241                         error = dorescan_or_reset(argc, argv, 1);
9242                         break;
9243                 case CAM_CMD_RESET:
9244                         error = dorescan_or_reset(argc, argv, 0);
9245                         break;
9246 #ifndef MINIMALISTIC
9247                 case CAM_CMD_READ_DEFECTS:
9248                         error = readdefects(cam_dev, argc, argv, combinedopt,
9249                                             retry_count, timeout);
9250                         break;
9251                 case CAM_CMD_MODE_PAGE:
9252                         modepage(cam_dev, argc, argv, combinedopt,
9253                                  retry_count, timeout);
9254                         break;
9255                 case CAM_CMD_SCSI_CMD:
9256                         error = scsicmd(cam_dev, argc, argv, combinedopt,
9257                                         retry_count, timeout);
9258                         break;
9259                 case CAM_CMD_SMP_CMD:
9260                         error = smpcmd(cam_dev, argc, argv, combinedopt,
9261                                        retry_count, timeout);
9262                         break;
9263                 case CAM_CMD_SMP_RG:
9264                         error = smpreportgeneral(cam_dev, argc, argv,
9265                                                  combinedopt, retry_count,
9266                                                  timeout);
9267                         break;
9268                 case CAM_CMD_SMP_PC:
9269                         error = smpphycontrol(cam_dev, argc, argv, combinedopt, 
9270                                               retry_count, timeout);
9271                         break;
9272                 case CAM_CMD_SMP_PHYLIST:
9273                         error = smpphylist(cam_dev, argc, argv, combinedopt,
9274                                            retry_count, timeout);
9275                         break;
9276                 case CAM_CMD_SMP_MANINFO:
9277                         error = smpmaninfo(cam_dev, argc, argv, combinedopt,
9278                                            retry_count, timeout);
9279                         break;
9280                 case CAM_CMD_DEBUG:
9281                         error = camdebug(argc, argv, combinedopt);
9282                         break;
9283                 case CAM_CMD_TAG:
9284                         error = tagcontrol(cam_dev, argc, argv, combinedopt);
9285                         break;
9286                 case CAM_CMD_RATE:
9287                         error = ratecontrol(cam_dev, retry_count, timeout,
9288                                             argc, argv, combinedopt);
9289                         break;
9290                 case CAM_CMD_FORMAT:
9291                         error = scsiformat(cam_dev, argc, argv,
9292                                            combinedopt, retry_count, timeout);
9293                         break;
9294                 case CAM_CMD_REPORTLUNS:
9295                         error = scsireportluns(cam_dev, argc, argv,
9296                                                combinedopt, retry_count,
9297                                                timeout);
9298                         break;
9299                 case CAM_CMD_READCAP:
9300                         error = scsireadcapacity(cam_dev, argc, argv,
9301                                                  combinedopt, retry_count,
9302                                                  timeout);
9303                         break;
9304                 case CAM_CMD_IDLE:
9305                 case CAM_CMD_STANDBY:
9306                 case CAM_CMD_SLEEP:
9307                         error = atapm(cam_dev, argc, argv,
9308                                       combinedopt, retry_count, timeout);
9309                         break;
9310                 case CAM_CMD_APM:
9311                 case CAM_CMD_AAM:
9312                         error = ataaxm(cam_dev, argc, argv,
9313                                       combinedopt, retry_count, timeout);
9314                         break;
9315                 case CAM_CMD_SECURITY:
9316                         error = atasecurity(cam_dev, retry_count, timeout,
9317                                             argc, argv, combinedopt);
9318                         break;
9319                 case CAM_CMD_DOWNLOAD_FW:
9320                         error = fwdownload(cam_dev, argc, argv, combinedopt,
9321                             arglist & CAM_ARG_VERBOSE, retry_count, timeout);
9322                         break;
9323                 case CAM_CMD_SANITIZE:
9324                         error = scsisanitize(cam_dev, argc, argv,
9325                                              combinedopt, retry_count, timeout);
9326                         break;
9327                 case CAM_CMD_PERSIST:
9328                         error = scsipersist(cam_dev, argc, argv, combinedopt,
9329                             retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9330                             arglist & CAM_ARG_ERR_RECOVER);
9331                         break;
9332                 case CAM_CMD_ATTRIB:
9333                         error = scsiattrib(cam_dev, argc, argv, combinedopt,
9334                             retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9335                             arglist & CAM_ARG_ERR_RECOVER);
9336                         break;
9337                 case CAM_CMD_OPCODES:
9338                         error = scsiopcodes(cam_dev, argc, argv, combinedopt,
9339                             retry_count, timeout, arglist & CAM_ARG_VERBOSE);
9340                         break;
9341                 case CAM_CMD_REPROBE:
9342                         error = scsireprobe(cam_dev);
9343                         break;
9344
9345 #endif /* MINIMALISTIC */
9346                 case CAM_CMD_USAGE:
9347                         usage(1);
9348                         break;
9349                 default:
9350                         usage(0);
9351                         error = 1;
9352                         break;
9353         }
9354
9355         if (cam_dev != NULL)
9356                 cam_close_device(cam_dev);
9357
9358         exit(error);
9359 }