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