]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sbin/camcontrol/camcontrol.c
MFC r315711: Fix printing bits above first eight.
[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 {
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         }
3136
3137         if ((arglist & CAM_ARG_BUS)
3138             && (arglist & CAM_ARG_TARGET)
3139             && (arglist & CAM_ARG_LUN))
3140                 error = scanlun_or_reset_dev(bus, target, lun, rescan);
3141         else
3142                 error = rescan_or_reset_bus(bus, rescan);
3143
3144         return(error);
3145 }
3146
3147 static int
3148 rescan_or_reset_bus(path_id_t bus, int rescan)
3149 {
3150         union ccb *ccb = NULL, *matchccb = NULL;
3151         int fd = -1, retval;
3152         int bufsize;
3153
3154         retval = 0;
3155
3156         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3157                 warnx("error opening transport layer device %s", XPT_DEVICE);
3158                 warn("%s", XPT_DEVICE);
3159                 return(1);
3160         }
3161
3162         ccb = malloc(sizeof(*ccb));
3163         if (ccb == NULL) {
3164                 warn("failed to allocate CCB");
3165                 retval = 1;
3166                 goto bailout;
3167         }
3168         bzero(ccb, sizeof(*ccb));
3169
3170         if (bus != CAM_BUS_WILDCARD) {
3171                 ccb->ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3172                 ccb->ccb_h.path_id = bus;
3173                 ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
3174                 ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
3175                 ccb->crcn.flags = CAM_FLAG_NONE;
3176
3177                 /* run this at a low priority */
3178                 ccb->ccb_h.pinfo.priority = 5;
3179
3180                 if (ioctl(fd, CAMIOCOMMAND, ccb) == -1) {
3181                         warn("CAMIOCOMMAND ioctl failed");
3182                         retval = 1;
3183                         goto bailout;
3184                 }
3185
3186                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3187                         fprintf(stdout, "%s of bus %d was successful\n",
3188                             rescan ? "Re-scan" : "Reset", bus);
3189                 } else {
3190                         fprintf(stdout, "%s of bus %d returned error %#x\n",
3191                                 rescan ? "Re-scan" : "Reset", bus,
3192                                 ccb->ccb_h.status & CAM_STATUS_MASK);
3193                         retval = 1;
3194                 }
3195
3196                 goto bailout;
3197         }
3198
3199
3200         /*
3201          * The right way to handle this is to modify the xpt so that it can
3202          * handle a wildcarded bus in a rescan or reset CCB.  At the moment
3203          * that isn't implemented, so instead we enumerate the busses and
3204          * send the rescan or reset to those busses in the case where the
3205          * given bus is -1 (wildcard).  We don't send a rescan or reset
3206          * to the xpt bus; sending a rescan to the xpt bus is effectively a
3207          * no-op, sending a rescan to the xpt bus would result in a status of
3208          * CAM_REQ_INVALID.
3209          */
3210         matchccb = malloc(sizeof(*matchccb));
3211         if (matchccb == NULL) {
3212                 warn("failed to allocate CCB");
3213                 retval = 1;
3214                 goto bailout;
3215         }
3216         bzero(matchccb, sizeof(*matchccb));
3217         matchccb->ccb_h.func_code = XPT_DEV_MATCH;
3218         matchccb->ccb_h.path_id = CAM_BUS_WILDCARD;
3219         bufsize = sizeof(struct dev_match_result) * 20;
3220         matchccb->cdm.match_buf_len = bufsize;
3221         matchccb->cdm.matches=(struct dev_match_result *)malloc(bufsize);
3222         if (matchccb->cdm.matches == NULL) {
3223                 warnx("can't malloc memory for matches");
3224                 retval = 1;
3225                 goto bailout;
3226         }
3227         matchccb->cdm.num_matches = 0;
3228
3229         matchccb->cdm.num_patterns = 1;
3230         matchccb->cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3231
3232         matchccb->cdm.patterns = (struct dev_match_pattern *)malloc(
3233                 matchccb->cdm.pattern_buf_len);
3234         if (matchccb->cdm.patterns == NULL) {
3235                 warnx("can't malloc memory for patterns");
3236                 retval = 1;
3237                 goto bailout;
3238         }
3239         matchccb->cdm.patterns[0].type = DEV_MATCH_BUS;
3240         matchccb->cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3241
3242         do {
3243                 unsigned int i;
3244
3245                 if (ioctl(fd, CAMIOCOMMAND, matchccb) == -1) {
3246                         warn("CAMIOCOMMAND ioctl failed");
3247                         retval = 1;
3248                         goto bailout;
3249                 }
3250
3251                 if ((matchccb->ccb_h.status != CAM_REQ_CMP)
3252                  || ((matchccb->cdm.status != CAM_DEV_MATCH_LAST)
3253                    && (matchccb->cdm.status != CAM_DEV_MATCH_MORE))) {
3254                         warnx("got CAM error %#x, CDM error %d\n",
3255                               matchccb->ccb_h.status, matchccb->cdm.status);
3256                         retval = 1;
3257                         goto bailout;
3258                 }
3259
3260                 for (i = 0; i < matchccb->cdm.num_matches; i++) {
3261                         struct bus_match_result *bus_result;
3262
3263                         /* This shouldn't happen. */
3264                         if (matchccb->cdm.matches[i].type != DEV_MATCH_BUS)
3265                                 continue;
3266
3267                         bus_result =&matchccb->cdm.matches[i].result.bus_result;
3268
3269                         /*
3270                          * We don't want to rescan or reset the xpt bus.
3271                          * See above.
3272                          */
3273                         if (bus_result->path_id == CAM_XPT_PATH_ID)
3274                                 continue;
3275
3276                         ccb->ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3277                                                        XPT_RESET_BUS;
3278                         ccb->ccb_h.path_id = bus_result->path_id;
3279                         ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
3280                         ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
3281                         ccb->crcn.flags = CAM_FLAG_NONE;
3282
3283                         /* run this at a low priority */
3284                         ccb->ccb_h.pinfo.priority = 5;
3285
3286                         if (ioctl(fd, CAMIOCOMMAND, ccb) == -1) {
3287                                 warn("CAMIOCOMMAND ioctl failed");
3288                                 retval = 1;
3289                                 goto bailout;
3290                         }
3291
3292                         if ((ccb->ccb_h.status & CAM_STATUS_MASK)==CAM_REQ_CMP){
3293                                 fprintf(stdout, "%s of bus %d was successful\n",
3294                                         rescan? "Re-scan" : "Reset",
3295                                         bus_result->path_id);
3296                         } else {
3297                                 /*
3298                                  * Don't bail out just yet, maybe the other
3299                                  * rescan or reset commands will complete
3300                                  * successfully.
3301                                  */
3302                                 fprintf(stderr, "%s of bus %d returned error "
3303                                         "%#x\n", rescan? "Re-scan" : "Reset",
3304                                         bus_result->path_id,
3305                                         ccb->ccb_h.status & CAM_STATUS_MASK);
3306                                 retval = 1;
3307                         }
3308                 }
3309         } while ((matchccb->ccb_h.status == CAM_REQ_CMP)
3310                  && (matchccb->cdm.status == CAM_DEV_MATCH_MORE));
3311
3312 bailout:
3313
3314         if (fd != -1)
3315                 close(fd);
3316
3317         if (matchccb != NULL) {
3318                 free(matchccb->cdm.patterns);
3319                 free(matchccb->cdm.matches);
3320                 free(matchccb);
3321         }
3322         free(ccb);
3323
3324         return(retval);
3325 }
3326
3327 static int
3328 scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3329 {
3330         union ccb ccb;
3331         struct cam_device *device;
3332         int fd;
3333
3334         device = NULL;
3335
3336         if (bus == CAM_BUS_WILDCARD) {
3337                 warnx("invalid bus number %d", bus);
3338                 return(1);
3339         }
3340
3341         if (target == CAM_TARGET_WILDCARD) {
3342                 warnx("invalid target number %d", target);
3343                 return(1);
3344         }
3345
3346         if (lun == CAM_LUN_WILDCARD) {
3347                 warnx("invalid lun number %jx", (uintmax_t)lun);
3348                 return(1);
3349         }
3350
3351         fd = -1;
3352
3353         bzero(&ccb, sizeof(union ccb));
3354
3355         if (scan) {
3356                 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3357                         warnx("error opening transport layer device %s\n",
3358                             XPT_DEVICE);
3359                         warn("%s", XPT_DEVICE);
3360                         return(1);
3361                 }
3362         } else {
3363                 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3364                 if (device == NULL) {
3365                         warnx("%s", cam_errbuf);
3366                         return(1);
3367                 }
3368         }
3369
3370         ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3371         ccb.ccb_h.path_id = bus;
3372         ccb.ccb_h.target_id = target;
3373         ccb.ccb_h.target_lun = lun;
3374         ccb.ccb_h.timeout = 5000;
3375         ccb.crcn.flags = CAM_FLAG_NONE;
3376
3377         /* run this at a low priority */
3378         ccb.ccb_h.pinfo.priority = 5;
3379
3380         if (scan) {
3381                 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3382                         warn("CAMIOCOMMAND ioctl failed");
3383                         close(fd);
3384                         return(1);
3385                 }
3386         } else {
3387                 if (cam_send_ccb(device, &ccb) < 0) {
3388                         warn("error sending XPT_RESET_DEV CCB");
3389                         cam_close_device(device);
3390                         return(1);
3391                 }
3392         }
3393
3394         if (scan)
3395                 close(fd);
3396         else
3397                 cam_close_device(device);
3398
3399         /*
3400          * An error code of CAM_BDR_SENT is normal for a BDR request.
3401          */
3402         if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3403          || ((!scan)
3404           && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3405                 fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3406                     scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3407                 return(0);
3408         } else {
3409                 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3410                     scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3411                     ccb.ccb_h.status & CAM_STATUS_MASK);
3412                 return(1);
3413         }
3414 }
3415
3416 #ifndef MINIMALISTIC
3417
3418 static struct scsi_nv defect_list_type_map[] = {
3419         { "block", SRDD10_BLOCK_FORMAT },
3420         { "extbfi", SRDD10_EXT_BFI_FORMAT },
3421         { "extphys", SRDD10_EXT_PHYS_FORMAT },
3422         { "longblock", SRDD10_LONG_BLOCK_FORMAT },
3423         { "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3424         { "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3425 };
3426
3427 static int
3428 readdefects(struct cam_device *device, int argc, char **argv,
3429             char *combinedopt, int task_attr, int retry_count, int timeout)
3430 {
3431         union ccb *ccb = NULL;
3432         struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3433         struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3434         size_t hdr_size = 0, entry_size = 0;
3435         int use_12byte = 0;
3436         int hex_format = 0;
3437         u_int8_t *defect_list = NULL;
3438         u_int8_t list_format = 0;
3439         int list_type_set = 0;
3440         u_int32_t dlist_length = 0;
3441         u_int32_t returned_length = 0, valid_len = 0;
3442         u_int32_t num_returned = 0, num_valid = 0;
3443         u_int32_t max_possible_size = 0, hdr_max = 0;
3444         u_int32_t starting_offset = 0;
3445         u_int8_t returned_format, returned_type;
3446         unsigned int i;
3447         int summary = 0, quiet = 0;
3448         int c, error = 0;
3449         int lists_specified = 0;
3450         int get_length = 1, first_pass = 1;
3451         int mads = 0;
3452
3453         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3454                 switch(c){
3455                 case 'f':
3456                 {
3457                         scsi_nv_status status;
3458                         int entry_num = 0;
3459
3460                         status = scsi_get_nv(defect_list_type_map,
3461                             sizeof(defect_list_type_map) /
3462                             sizeof(defect_list_type_map[0]), optarg,
3463                             &entry_num, SCSI_NV_FLAG_IG_CASE);
3464
3465                         if (status == SCSI_NV_FOUND) {
3466                                 list_format = defect_list_type_map[
3467                                     entry_num].value;
3468                                 list_type_set = 1;
3469                         } else {
3470                                 warnx("%s: %s %s option %s", __func__,
3471                                     (status == SCSI_NV_AMBIGUOUS) ?
3472                                     "ambiguous" : "invalid", "defect list type",
3473                                     optarg);
3474                                 error = 1;
3475                                 goto defect_bailout;
3476                         }
3477                         break;
3478                 }
3479                 case 'G':
3480                         arglist |= CAM_ARG_GLIST;
3481                         break;
3482                 case 'P':
3483                         arglist |= CAM_ARG_PLIST;
3484                         break;
3485                 case 'q':
3486                         quiet = 1;
3487                         break;
3488                 case 's':
3489                         summary = 1;
3490                         break;
3491                 case 'S': {
3492                         char *endptr;
3493
3494                         starting_offset = strtoul(optarg, &endptr, 0);
3495                         if (*endptr != '\0') {
3496                                 error = 1;
3497                                 warnx("invalid starting offset %s", optarg);
3498                                 goto defect_bailout;
3499                         }
3500                         break;
3501                 }
3502                 case 'X':
3503                         hex_format = 1;
3504                         break;
3505                 default:
3506                         break;
3507                 }
3508         }
3509
3510         if (list_type_set == 0) {
3511                 error = 1;
3512                 warnx("no defect list format specified");
3513                 goto defect_bailout;
3514         }
3515
3516         if (arglist & CAM_ARG_PLIST) {
3517                 list_format |= SRDD10_PLIST;
3518                 lists_specified++;
3519         }
3520
3521         if (arglist & CAM_ARG_GLIST) {
3522                 list_format |= SRDD10_GLIST;
3523                 lists_specified++;
3524         }
3525
3526         /*
3527          * This implies a summary, and was the previous behavior.
3528          */
3529         if (lists_specified == 0)
3530                 summary = 1;
3531
3532         ccb = cam_getccb(device);
3533
3534 retry_12byte:
3535
3536         /*
3537          * We start off asking for just the header to determine how much
3538          * defect data is available.  Some Hitachi drives return an error
3539          * if you ask for more data than the drive has.  Once we know the
3540          * length, we retry the command with the returned length.
3541          */
3542         if (use_12byte == 0)
3543                 dlist_length = sizeof(*hdr10);
3544         else
3545                 dlist_length = sizeof(*hdr12);
3546
3547 retry:
3548         if (defect_list != NULL) {
3549                 free(defect_list);
3550                 defect_list = NULL;
3551         }
3552         defect_list = malloc(dlist_length);
3553         if (defect_list == NULL) {
3554                 warnx("can't malloc memory for defect list");
3555                 error = 1;
3556                 goto defect_bailout;
3557         }
3558
3559 next_batch:
3560         bzero(defect_list, dlist_length);
3561
3562         /*
3563          * cam_getccb() zeros the CCB header only.  So we need to zero the
3564          * payload portion of the ccb.
3565          */
3566         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
3567
3568         scsi_read_defects(&ccb->csio,
3569                           /*retries*/ retry_count,
3570                           /*cbfcnp*/ NULL,
3571                           /*tag_action*/ task_attr,
3572                           /*list_format*/ list_format,
3573                           /*addr_desc_index*/ starting_offset,
3574                           /*data_ptr*/ defect_list,
3575                           /*dxfer_len*/ dlist_length,
3576                           /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3577                           /*sense_len*/ SSD_FULL_SIZE,
3578                           /*timeout*/ timeout ? timeout : 5000);
3579
3580         /* Disable freezing the device queue */
3581         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3582
3583         if (cam_send_ccb(device, ccb) < 0) {
3584                 perror("error reading defect list");
3585
3586                 if (arglist & CAM_ARG_VERBOSE) {
3587                         cam_error_print(device, ccb, CAM_ESF_ALL,
3588                                         CAM_EPF_ALL, stderr);
3589                 }
3590
3591                 error = 1;
3592                 goto defect_bailout;
3593         }
3594
3595         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3596
3597         if (use_12byte == 0) {
3598                 hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3599                 hdr_size = sizeof(*hdr10);
3600                 hdr_max = SRDDH10_MAX_LENGTH;
3601
3602                 if (valid_len >= hdr_size) {
3603                         returned_length = scsi_2btoul(hdr10->length);
3604                         returned_format = hdr10->format;
3605                 } else {
3606                         returned_length = 0;
3607                         returned_format = 0;
3608                 }
3609         } else {
3610                 hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3611                 hdr_size = sizeof(*hdr12);
3612                 hdr_max = SRDDH12_MAX_LENGTH;
3613
3614                 if (valid_len >= hdr_size) {
3615                         returned_length = scsi_4btoul(hdr12->length);
3616                         returned_format = hdr12->format;
3617                 } else {
3618                         returned_length = 0;
3619                         returned_format = 0;
3620                 }
3621         }
3622
3623         returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3624         switch (returned_type) {
3625         case SRDD10_BLOCK_FORMAT:
3626                 entry_size = sizeof(struct scsi_defect_desc_block);
3627                 break;
3628         case SRDD10_LONG_BLOCK_FORMAT:
3629                 entry_size = sizeof(struct scsi_defect_desc_long_block);
3630                 break;
3631         case SRDD10_EXT_PHYS_FORMAT:
3632         case SRDD10_PHYSICAL_SECTOR_FORMAT:
3633                 entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3634                 break;
3635         case SRDD10_EXT_BFI_FORMAT:
3636         case SRDD10_BYTES_FROM_INDEX_FORMAT:
3637                 entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3638                 break;
3639         default:
3640                 warnx("Unknown defect format 0x%x\n", returned_type);
3641                 error = 1;
3642                 goto defect_bailout;
3643                 break;
3644         } 
3645
3646         max_possible_size = (hdr_max / entry_size) * entry_size;
3647         num_returned = returned_length / entry_size;
3648         num_valid = min(returned_length, valid_len - hdr_size);
3649         num_valid /= entry_size;
3650
3651         if (get_length != 0) {
3652                 get_length = 0;
3653
3654                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3655                      CAM_SCSI_STATUS_ERROR) {
3656                         struct scsi_sense_data *sense;
3657                         int error_code, sense_key, asc, ascq;
3658
3659                         sense = &ccb->csio.sense_data;
3660                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
3661                             ccb->csio.sense_resid, &error_code, &sense_key,
3662                             &asc, &ascq, /*show_errors*/ 1);
3663
3664                         /*
3665                          * If the drive is reporting that it just doesn't
3666                          * support the defect list format, go ahead and use
3667                          * the length it reported.  Otherwise, the length
3668                          * may not be valid, so use the maximum.
3669                          */
3670                         if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3671                          && (asc == 0x1c) && (ascq == 0x00)
3672                          && (returned_length > 0)) {
3673                                 if ((use_12byte == 0)
3674                                  && (returned_length >= max_possible_size)) {
3675                                         get_length = 1;
3676                                         use_12byte = 1;
3677                                         goto retry_12byte;
3678                                 }
3679                                 dlist_length = returned_length + hdr_size;
3680                         } else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3681                                 && (asc == 0x1f) && (ascq == 0x00)
3682                                 && (returned_length > 0)) {
3683                                 /* Partial defect list transfer */
3684                                 /*
3685                                  * Hitachi drives return this error
3686                                  * along with a partial defect list if they
3687                                  * have more defects than the 10 byte
3688                                  * command can support.  Retry with the 12
3689                                  * byte command.
3690                                  */
3691                                 if (use_12byte == 0) {
3692                                         get_length = 1;
3693                                         use_12byte = 1;
3694                                         goto retry_12byte;
3695                                 }
3696                                 dlist_length = returned_length + hdr_size;
3697                         } else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3698                                 && (asc == 0x24) && (ascq == 0x00)) {
3699                                 /* Invalid field in CDB */
3700                                 /*
3701                                  * SBC-3 says that if the drive has more
3702                                  * defects than can be reported with the
3703                                  * 10 byte command, it should return this
3704                                  * error and no data.  Retry with the 12
3705                                  * byte command.
3706                                  */
3707                                 if (use_12byte == 0) {
3708                                         get_length = 1;
3709                                         use_12byte = 1;
3710                                         goto retry_12byte;
3711                                 }
3712                                 dlist_length = returned_length + hdr_size;
3713                         } else {
3714                                 /*
3715                                  * If we got a SCSI error and no valid length,
3716                                  * just use the 10 byte maximum.  The 12
3717                                  * byte maximum is too large.
3718                                  */
3719                                 if (returned_length == 0)
3720                                         dlist_length = SRDD10_MAX_LENGTH;
3721                                 else {
3722                                         if ((use_12byte == 0)
3723                                          && (returned_length >=
3724                                              max_possible_size)) {
3725                                                 get_length = 1;
3726                                                 use_12byte = 1;
3727                                                 goto retry_12byte;
3728                                         }
3729                                         dlist_length = returned_length +
3730                                             hdr_size;
3731                                 }
3732                         }
3733                 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3734                             CAM_REQ_CMP){
3735                         error = 1;
3736                         warnx("Error reading defect header");
3737                         if (arglist & CAM_ARG_VERBOSE)
3738                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3739                                                 CAM_EPF_ALL, stderr);
3740                         goto defect_bailout;
3741                 } else {
3742                         if ((use_12byte == 0)
3743                          && (returned_length >= max_possible_size)) {
3744                                 get_length = 1;
3745                                 use_12byte = 1;
3746                                 goto retry_12byte;
3747                         }
3748                         dlist_length = returned_length + hdr_size;
3749                 }
3750                 if (summary != 0) {
3751                         fprintf(stdout, "%u", num_returned);
3752                         if (quiet == 0) {
3753                                 fprintf(stdout, " defect%s",
3754                                         (num_returned != 1) ? "s" : "");
3755                         }
3756                         fprintf(stdout, "\n");
3757
3758                         goto defect_bailout;
3759                 }
3760
3761                 /*
3762                  * We always limit the list length to the 10-byte maximum
3763                  * length (0xffff).  The reason is that some controllers
3764                  * can't handle larger I/Os, and we can transfer the entire
3765                  * 10 byte list in one shot.  For drives that support the 12
3766                  * byte read defects command, we'll step through the list
3767                  * by specifying a starting offset.  For drives that don't
3768                  * support the 12 byte command's starting offset, we'll
3769                  * just display the first 64K.
3770                  */
3771                 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3772
3773                 goto retry;
3774         }
3775
3776
3777         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3778          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3779          && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3780                 struct scsi_sense_data *sense;
3781                 int error_code, sense_key, asc, ascq;
3782
3783                 sense = &ccb->csio.sense_data;
3784                 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3785                     ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3786                     &ascq, /*show_errors*/ 1);
3787
3788                 /*
3789                  * According to the SCSI spec, if the disk doesn't support
3790                  * the requested format, it will generally return a sense
3791                  * key of RECOVERED ERROR, and an additional sense code
3792                  * of "DEFECT LIST NOT FOUND".  HGST drives also return
3793                  * Primary/Grown defect list not found errors.  So just
3794                  * check for an ASC of 0x1c.
3795                  */
3796                 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3797                  && (asc == 0x1c)) {
3798                         const char *format_str;
3799
3800                         format_str = scsi_nv_to_str(defect_list_type_map,
3801                             sizeof(defect_list_type_map) /
3802                             sizeof(defect_list_type_map[0]),
3803                             list_format & SRDD10_DLIST_FORMAT_MASK);
3804                         warnx("requested defect format %s not available",
3805                             format_str ? format_str : "unknown");
3806
3807                         format_str = scsi_nv_to_str(defect_list_type_map,
3808                             sizeof(defect_list_type_map) /
3809                             sizeof(defect_list_type_map[0]), returned_type);
3810                         if (format_str != NULL) {
3811                                 warnx("Device returned %s format",
3812                                     format_str);
3813                         } else {
3814                                 error = 1;
3815                                 warnx("Device returned unknown defect"
3816                                      " data format %#x", returned_type);
3817                                 goto defect_bailout;
3818                         }
3819                 } else {
3820                         error = 1;
3821                         warnx("Error returned from read defect data command");
3822                         if (arglist & CAM_ARG_VERBOSE)
3823                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3824                                                 CAM_EPF_ALL, stderr);
3825                         goto defect_bailout;
3826                 }
3827         } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3828                 error = 1;
3829                 warnx("Error returned from read defect data command");
3830                 if (arglist & CAM_ARG_VERBOSE)
3831                         cam_error_print(device, ccb, CAM_ESF_ALL,
3832                                         CAM_EPF_ALL, stderr);
3833                 goto defect_bailout;
3834         }
3835
3836         if (first_pass != 0) {
3837                 fprintf(stderr, "Got %d defect", num_returned);
3838
3839                 if ((lists_specified == 0) || (num_returned == 0)) {
3840                         fprintf(stderr, "s.\n");
3841                         goto defect_bailout;
3842                 } else if (num_returned == 1)
3843                         fprintf(stderr, ":\n");
3844                 else
3845                         fprintf(stderr, "s:\n");
3846
3847                 first_pass = 0;
3848         }
3849
3850         /*
3851          * XXX KDM  I should probably clean up the printout format for the
3852          * disk defects.
3853          */
3854         switch (returned_type) {
3855         case SRDD10_PHYSICAL_SECTOR_FORMAT:
3856         case SRDD10_EXT_PHYS_FORMAT:
3857         {
3858                 struct scsi_defect_desc_phys_sector *dlist;
3859
3860                 dlist = (struct scsi_defect_desc_phys_sector *)
3861                         (defect_list + hdr_size);
3862
3863                 for (i = 0; i < num_valid; i++) {
3864                         uint32_t sector;
3865
3866                         sector = scsi_4btoul(dlist[i].sector);
3867                         if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
3868                                 mads = (sector & SDD_EXT_PHYS_MADS) ?
3869                                        0 : 1;
3870                                 sector &= ~SDD_EXT_PHYS_FLAG_MASK;
3871                         }
3872                         if (hex_format == 0)
3873                                 fprintf(stdout, "%d:%d:%d%s",
3874                                         scsi_3btoul(dlist[i].cylinder),
3875                                         dlist[i].head,
3876                                         scsi_4btoul(dlist[i].sector),
3877                                         mads ? " - " : "\n");
3878                         else
3879                                 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3880                                         scsi_3btoul(dlist[i].cylinder),
3881                                         dlist[i].head,
3882                                         scsi_4btoul(dlist[i].sector),
3883                                         mads ? " - " : "\n");
3884                         mads = 0;
3885                 }
3886                 if (num_valid < num_returned) {
3887                         starting_offset += num_valid;
3888                         goto next_batch;
3889                 }
3890                 break;
3891         }
3892         case SRDD10_BYTES_FROM_INDEX_FORMAT:
3893         case SRDD10_EXT_BFI_FORMAT:
3894         {
3895                 struct scsi_defect_desc_bytes_from_index *dlist;
3896
3897                 dlist = (struct scsi_defect_desc_bytes_from_index *)
3898                         (defect_list + hdr_size);
3899
3900                 for (i = 0; i < num_valid; i++) {
3901                         uint32_t bfi;
3902
3903                         bfi = scsi_4btoul(dlist[i].bytes_from_index);
3904                         if (returned_type == SRDD10_EXT_BFI_FORMAT) {
3905                                 mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
3906                                 bfi &= ~SDD_EXT_BFI_FLAG_MASK;
3907                         }
3908                         if (hex_format == 0)
3909                                 fprintf(stdout, "%d:%d:%d%s",
3910                                         scsi_3btoul(dlist[i].cylinder),
3911                                         dlist[i].head,
3912                                         scsi_4btoul(dlist[i].bytes_from_index),
3913                                         mads ? " - " : "\n");
3914                         else
3915                                 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3916                                         scsi_3btoul(dlist[i].cylinder),
3917                                         dlist[i].head,
3918                                         scsi_4btoul(dlist[i].bytes_from_index),
3919                                         mads ? " - " : "\n");
3920
3921                         mads = 0;
3922                 }
3923                 if (num_valid < num_returned) {
3924                         starting_offset += num_valid;
3925                         goto next_batch;
3926                 }
3927                 break;
3928         }
3929         case SRDDH10_BLOCK_FORMAT:
3930         {
3931                 struct scsi_defect_desc_block *dlist;
3932
3933                 dlist = (struct scsi_defect_desc_block *)
3934                         (defect_list + hdr_size);
3935
3936                 for (i = 0; i < num_valid; i++) {
3937                         if (hex_format == 0)
3938                                 fprintf(stdout, "%u\n",
3939                                         scsi_4btoul(dlist[i].address));
3940                         else
3941                                 fprintf(stdout, "0x%x\n",
3942                                         scsi_4btoul(dlist[i].address));
3943                 }
3944
3945                 if (num_valid < num_returned) {
3946                         starting_offset += num_valid;
3947                         goto next_batch;
3948                 }
3949
3950                 break;
3951         }
3952         case SRDD10_LONG_BLOCK_FORMAT:
3953         {
3954                 struct scsi_defect_desc_long_block *dlist;
3955
3956                 dlist = (struct scsi_defect_desc_long_block *)
3957                         (defect_list + hdr_size);
3958
3959                 for (i = 0; i < num_valid; i++) {
3960                         if (hex_format == 0)
3961                                 fprintf(stdout, "%ju\n",
3962                                         (uintmax_t)scsi_8btou64(
3963                                         dlist[i].address));
3964                         else
3965                                 fprintf(stdout, "0x%jx\n",
3966                                         (uintmax_t)scsi_8btou64(
3967                                         dlist[i].address));
3968                 }
3969
3970                 if (num_valid < num_returned) {
3971                         starting_offset += num_valid;
3972                         goto next_batch;
3973                 }
3974                 break;
3975         }
3976         default:
3977                 fprintf(stderr, "Unknown defect format 0x%x\n",
3978                         returned_type);
3979                 error = 1;
3980                 break;
3981         }
3982 defect_bailout:
3983
3984         if (defect_list != NULL)
3985                 free(defect_list);
3986
3987         if (ccb != NULL)
3988                 cam_freeccb(ccb);
3989
3990         return(error);
3991 }
3992 #endif /* MINIMALISTIC */
3993
3994 #if 0
3995 void
3996 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3997 {
3998         union ccb *ccb;
3999
4000         ccb = cam_getccb(device);
4001
4002         cam_freeccb(ccb);
4003 }
4004 #endif
4005
4006 #ifndef MINIMALISTIC
4007 void
4008 mode_sense(struct cam_device *device, int dbd, int pc, int page, int subpage,
4009            int task_attr, int retry_count, int timeout, u_int8_t *data,
4010            int datalen)
4011 {
4012         union ccb *ccb;
4013         int retval;
4014
4015         ccb = cam_getccb(device);
4016
4017         if (ccb == NULL)
4018                 errx(1, "mode_sense: couldn't allocate CCB");
4019
4020         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
4021
4022         scsi_mode_sense_subpage(&ccb->csio,
4023                         /* retries */ retry_count,
4024                         /* cbfcnp */ NULL,
4025                         /* tag_action */ task_attr,
4026                         /* dbd */ dbd,
4027                         /* pc */ pc << 6,
4028                         /* page */ page,
4029                         /* subpage */ subpage,
4030                         /* param_buf */ data,
4031                         /* param_len */ datalen,
4032                         /* minimum_cmd_size */ 0,
4033                         /* sense_len */ SSD_FULL_SIZE,
4034                         /* timeout */ timeout ? timeout : 5000);
4035
4036         if (arglist & CAM_ARG_ERR_RECOVER)
4037                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4038
4039         /* Disable freezing the device queue */
4040         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4041
4042         if (((retval = cam_send_ccb(device, ccb)) < 0)
4043          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4044                 if (arglist & CAM_ARG_VERBOSE) {
4045                         cam_error_print(device, ccb, CAM_ESF_ALL,
4046                                         CAM_EPF_ALL, stderr);
4047                 }
4048                 cam_freeccb(ccb);
4049                 cam_close_device(device);
4050                 if (retval < 0)
4051                         err(1, "error sending mode sense command");
4052                 else
4053                         errx(1, "error sending mode sense command");
4054         }
4055
4056         cam_freeccb(ccb);
4057 }
4058
4059 void
4060 mode_select(struct cam_device *device, int save_pages, int task_attr,
4061             int retry_count, int timeout, u_int8_t *data, int datalen)
4062 {
4063         union ccb *ccb;
4064         int retval;
4065
4066         ccb = cam_getccb(device);
4067
4068         if (ccb == NULL)
4069                 errx(1, "mode_select: couldn't allocate CCB");
4070
4071         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
4072
4073         scsi_mode_select(&ccb->csio,
4074                          /* retries */ retry_count,
4075                          /* cbfcnp */ NULL,
4076                          /* tag_action */ task_attr,
4077                          /* scsi_page_fmt */ 1,
4078                          /* save_pages */ save_pages,
4079                          /* param_buf */ data,
4080                          /* param_len */ datalen,
4081                          /* sense_len */ SSD_FULL_SIZE,
4082                          /* timeout */ timeout ? timeout : 5000);
4083
4084         if (arglist & CAM_ARG_ERR_RECOVER)
4085                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4086
4087         /* Disable freezing the device queue */
4088         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4089
4090         if (((retval = cam_send_ccb(device, ccb)) < 0)
4091          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4092                 if (arglist & CAM_ARG_VERBOSE) {
4093                         cam_error_print(device, ccb, CAM_ESF_ALL,
4094                                         CAM_EPF_ALL, stderr);
4095                 }
4096                 cam_freeccb(ccb);
4097                 cam_close_device(device);
4098
4099                 if (retval < 0)
4100                         err(1, "error sending mode select command");
4101                 else
4102                         errx(1, "error sending mode select command");
4103
4104         }
4105
4106         cam_freeccb(ccb);
4107 }
4108
4109 void
4110 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4111          int task_attr, int retry_count, int timeout)
4112 {
4113         char *str_subpage;
4114         int c, page = -1, subpage = -1, pc = 0;
4115         int binary = 0, dbd = 0, edit = 0, list = 0;
4116
4117         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4118                 switch(c) {
4119                 case 'b':
4120                         binary = 1;
4121                         break;
4122                 case 'd':
4123                         dbd = 1;
4124                         break;
4125                 case 'e':
4126                         edit = 1;
4127                         break;
4128                 case 'l':
4129                         list++;
4130                         break;
4131                 case 'm':
4132                         str_subpage = optarg;
4133                         strsep(&str_subpage, ",");
4134                         page = strtol(optarg, NULL, 0);
4135                         if (str_subpage)
4136                             subpage = strtol(str_subpage, NULL, 0);
4137                         else
4138                             subpage = 0;
4139                         if (page < 0)
4140                                 errx(1, "invalid mode page %d", page);
4141                         if (subpage < 0)
4142                                 errx(1, "invalid mode subpage %d", subpage);
4143                         break;
4144                 case 'P':
4145                         pc = strtol(optarg, NULL, 0);
4146                         if ((pc < 0) || (pc > 3))
4147                                 errx(1, "invalid page control field %d", pc);
4148                         break;
4149                 default:
4150                         break;
4151                 }
4152         }
4153
4154         if (page == -1 && list == 0)
4155                 errx(1, "you must specify a mode page!");
4156
4157         if (list != 0) {
4158                 mode_list(device, dbd, pc, list > 1, task_attr, retry_count,
4159                           timeout);
4160         } else {
4161                 mode_edit(device, dbd, pc, page, subpage, edit, binary,
4162                     task_attr, retry_count, timeout);
4163         }
4164 }
4165
4166 static int
4167 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4168         int task_attr, int retry_count, int timeout)
4169 {
4170         union ccb *ccb;
4171         u_int32_t flags = CAM_DIR_NONE;
4172         u_int8_t *data_ptr = NULL;
4173         u_int8_t cdb[20];
4174         u_int8_t atacmd[12];
4175         struct get_hook hook;
4176         int c, data_bytes = 0, valid_bytes;
4177         int cdb_len = 0;
4178         int atacmd_len = 0;
4179         int dmacmd = 0;
4180         int fpdmacmd = 0;
4181         int need_res = 0;
4182         char *datastr = NULL, *tstr, *resstr = NULL;
4183         int error = 0;
4184         int fd_data = 0, fd_res = 0;
4185         int retval;
4186
4187         ccb = cam_getccb(device);
4188
4189         if (ccb == NULL) {
4190                 warnx("scsicmd: error allocating ccb");
4191                 return(1);
4192         }
4193
4194         CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
4195
4196         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4197                 switch(c) {
4198                 case 'a':
4199                         tstr = optarg;
4200                         while (isspace(*tstr) && (*tstr != '\0'))
4201                                 tstr++;
4202                         hook.argc = argc - optind;
4203                         hook.argv = argv + optind;
4204                         hook.got = 0;
4205                         atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4206                                                     iget, &hook);
4207                         /*
4208                          * Increment optind by the number of arguments the
4209                          * encoding routine processed.  After each call to
4210                          * getopt(3), optind points to the argument that
4211                          * getopt should process _next_.  In this case,
4212                          * that means it points to the first command string
4213                          * argument, if there is one.  Once we increment
4214                          * this, it should point to either the next command
4215                          * line argument, or it should be past the end of
4216                          * the list.
4217                          */
4218                         optind += hook.got;
4219                         break;
4220                 case 'c':
4221                         tstr = optarg;
4222                         while (isspace(*tstr) && (*tstr != '\0'))
4223                                 tstr++;
4224                         hook.argc = argc - optind;
4225                         hook.argv = argv + optind;
4226                         hook.got = 0;
4227                         cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4228                                                     iget, &hook);
4229                         /*
4230                          * Increment optind by the number of arguments the
4231                          * encoding routine processed.  After each call to
4232                          * getopt(3), optind points to the argument that
4233                          * getopt should process _next_.  In this case,
4234                          * that means it points to the first command string
4235                          * argument, if there is one.  Once we increment
4236                          * this, it should point to either the next command
4237                          * line argument, or it should be past the end of
4238                          * the list.
4239                          */
4240                         optind += hook.got;
4241                         break;
4242                 case 'd':
4243                         dmacmd = 1;
4244                         break;
4245                 case 'f':
4246                         fpdmacmd = 1;
4247                         break;
4248                 case 'i':
4249                         if (arglist & CAM_ARG_CMD_OUT) {
4250                                 warnx("command must either be "
4251                                       "read or write, not both");
4252                                 error = 1;
4253                                 goto scsicmd_bailout;
4254                         }
4255                         arglist |= CAM_ARG_CMD_IN;
4256                         flags = CAM_DIR_IN;
4257                         data_bytes = strtol(optarg, NULL, 0);
4258                         if (data_bytes <= 0) {
4259                                 warnx("invalid number of input bytes %d",
4260                                       data_bytes);
4261                                 error = 1;
4262                                 goto scsicmd_bailout;
4263                         }
4264                         hook.argc = argc - optind;
4265                         hook.argv = argv + optind;
4266                         hook.got = 0;
4267                         optind++;
4268                         datastr = cget(&hook, NULL);
4269                         /*
4270                          * If the user supplied "-" instead of a format, he
4271                          * wants the data to be written to stdout.
4272                          */
4273                         if ((datastr != NULL)
4274                          && (datastr[0] == '-'))
4275                                 fd_data = 1;
4276
4277                         data_ptr = (u_int8_t *)malloc(data_bytes);
4278                         if (data_ptr == NULL) {
4279                                 warnx("can't malloc memory for data_ptr");
4280                                 error = 1;
4281                                 goto scsicmd_bailout;
4282                         }
4283                         break;
4284                 case 'o':
4285                         if (arglist & CAM_ARG_CMD_IN) {
4286                                 warnx("command must either be "
4287                                       "read or write, not both");
4288                                 error = 1;
4289                                 goto scsicmd_bailout;
4290                         }
4291                         arglist |= CAM_ARG_CMD_OUT;
4292                         flags = CAM_DIR_OUT;
4293                         data_bytes = strtol(optarg, NULL, 0);
4294                         if (data_bytes <= 0) {
4295                                 warnx("invalid number of output bytes %d",
4296                                       data_bytes);
4297                                 error = 1;
4298                                 goto scsicmd_bailout;
4299                         }
4300                         hook.argc = argc - optind;
4301                         hook.argv = argv + optind;
4302                         hook.got = 0;
4303                         datastr = cget(&hook, NULL);
4304                         data_ptr = (u_int8_t *)malloc(data_bytes);
4305                         if (data_ptr == NULL) {
4306                                 warnx("can't malloc memory for data_ptr");
4307                                 error = 1;
4308                                 goto scsicmd_bailout;
4309                         }
4310                         bzero(data_ptr, data_bytes);
4311                         /*
4312                          * If the user supplied "-" instead of a format, he
4313                          * wants the data to be read from stdin.
4314                          */
4315                         if ((datastr != NULL)
4316                          && (datastr[0] == '-'))
4317                                 fd_data = 1;
4318                         else
4319                                 buff_encode_visit(data_ptr, data_bytes, datastr,
4320                                                   iget, &hook);
4321                         optind += hook.got;
4322                         break;
4323                 case 'r':
4324                         need_res = 1;
4325                         hook.argc = argc - optind;
4326                         hook.argv = argv + optind;
4327                         hook.got = 0;
4328                         resstr = cget(&hook, NULL);
4329                         if ((resstr != NULL) && (resstr[0] == '-'))
4330                                 fd_res = 1;
4331                         optind += hook.got;
4332                         break;
4333                 default:
4334                         break;
4335                 }
4336         }
4337
4338         /*
4339          * If fd_data is set, and we're writing to the device, we need to
4340          * read the data the user wants written from stdin.
4341          */
4342         if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4343                 ssize_t amt_read;
4344                 int amt_to_read = data_bytes;
4345                 u_int8_t *buf_ptr = data_ptr;
4346
4347                 for (amt_read = 0; amt_to_read > 0;
4348                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4349                         if (amt_read == -1) {
4350                                 warn("error reading data from stdin");
4351                                 error = 1;
4352                                 goto scsicmd_bailout;
4353                         }
4354                         amt_to_read -= amt_read;
4355                         buf_ptr += amt_read;
4356                 }
4357         }
4358
4359         if (arglist & CAM_ARG_ERR_RECOVER)
4360                 flags |= CAM_PASS_ERR_RECOVER;
4361
4362         /* Disable freezing the device queue */
4363         flags |= CAM_DEV_QFRZDIS;
4364
4365         if (cdb_len) {
4366                 /*
4367                  * This is taken from the SCSI-3 draft spec.
4368                  * (T10/1157D revision 0.3)
4369                  * The top 3 bits of an opcode are the group code.
4370                  * The next 5 bits are the command code.
4371                  * Group 0:  six byte commands
4372                  * Group 1:  ten byte commands
4373                  * Group 2:  ten byte commands
4374                  * Group 3:  reserved
4375                  * Group 4:  sixteen byte commands
4376                  * Group 5:  twelve byte commands
4377                  * Group 6:  vendor specific
4378                  * Group 7:  vendor specific
4379                  */
4380                 switch((cdb[0] >> 5) & 0x7) {
4381                         case 0:
4382                                 cdb_len = 6;
4383                                 break;
4384                         case 1:
4385                         case 2:
4386                                 cdb_len = 10;
4387                                 break;
4388                         case 3:
4389                         case 6:
4390                         case 7:
4391                                 /* computed by buff_encode_visit */
4392                                 break;
4393                         case 4:
4394                                 cdb_len = 16;
4395                                 break;
4396                         case 5:
4397                                 cdb_len = 12;
4398                                 break;
4399                 }
4400
4401                 /*
4402                  * We should probably use csio_build_visit or something like that
4403                  * here, but it's easier to encode arguments as you go.  The
4404                  * alternative would be skipping the CDB argument and then encoding
4405                  * it here, since we've got the data buffer argument by now.
4406                  */
4407                 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4408
4409                 cam_fill_csio(&ccb->csio,
4410                       /*retries*/ retry_count,
4411                       /*cbfcnp*/ NULL,
4412                       /*flags*/ flags,
4413                       /*tag_action*/ task_attr,
4414                       /*data_ptr*/ data_ptr,
4415                       /*dxfer_len*/ data_bytes,
4416                       /*sense_len*/ SSD_FULL_SIZE,
4417                       /*cdb_len*/ cdb_len,
4418                       /*timeout*/ timeout ? timeout : 5000);
4419         } else {
4420                 atacmd_len = 12;
4421                 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4422                 if (need_res)
4423                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4424                 if (dmacmd)
4425                         ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4426                 if (fpdmacmd)
4427                         ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4428
4429                 cam_fill_ataio(&ccb->ataio,
4430                       /*retries*/ retry_count,
4431                       /*cbfcnp*/ NULL,
4432                       /*flags*/ flags,
4433                       /*tag_action*/ 0,
4434                       /*data_ptr*/ data_ptr,
4435                       /*dxfer_len*/ data_bytes,
4436                       /*timeout*/ timeout ? timeout : 5000);
4437         }
4438
4439         if (((retval = cam_send_ccb(device, ccb)) < 0)
4440          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4441                 const char warnstr[] = "error sending command";
4442
4443                 if (retval < 0)
4444                         warn(warnstr);
4445                 else
4446                         warnx(warnstr);
4447
4448                 if (arglist & CAM_ARG_VERBOSE) {
4449                         cam_error_print(device, ccb, CAM_ESF_ALL,
4450                                         CAM_EPF_ALL, stderr);
4451                 }
4452
4453                 error = 1;
4454                 goto scsicmd_bailout;
4455         }
4456
4457         if (atacmd_len && need_res) {
4458                 if (fd_res == 0) {
4459                         buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4460                                           arg_put, NULL);
4461                         fprintf(stdout, "\n");
4462                 } else {
4463                         fprintf(stdout,
4464                             "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4465                             ccb->ataio.res.status,
4466                             ccb->ataio.res.error,
4467                             ccb->ataio.res.lba_low,
4468                             ccb->ataio.res.lba_mid,
4469                             ccb->ataio.res.lba_high,
4470                             ccb->ataio.res.device,
4471                             ccb->ataio.res.lba_low_exp,
4472                             ccb->ataio.res.lba_mid_exp,
4473                             ccb->ataio.res.lba_high_exp,
4474                             ccb->ataio.res.sector_count,
4475                             ccb->ataio.res.sector_count_exp);
4476                         fflush(stdout);
4477                 }
4478         }
4479
4480         if (cdb_len)
4481                 valid_bytes = ccb->csio.dxfer_len - ccb->csio.resid;
4482         else
4483                 valid_bytes = ccb->ataio.dxfer_len - ccb->ataio.resid;
4484         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4485          && (arglist & CAM_ARG_CMD_IN)
4486          && (valid_bytes > 0)) {
4487                 if (fd_data == 0) {
4488                         buff_decode_visit(data_ptr, valid_bytes, datastr,
4489                                           arg_put, NULL);
4490                         fprintf(stdout, "\n");
4491                 } else {
4492                         ssize_t amt_written;
4493                         int amt_to_write = valid_bytes;
4494                         u_int8_t *buf_ptr = data_ptr;
4495
4496                         for (amt_written = 0; (amt_to_write > 0) &&
4497                              (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4498                                 amt_to_write -= amt_written;
4499                                 buf_ptr += amt_written;
4500                         }
4501                         if (amt_written == -1) {
4502                                 warn("error writing data to stdout");
4503                                 error = 1;
4504                                 goto scsicmd_bailout;
4505                         } else if ((amt_written == 0)
4506                                 && (amt_to_write > 0)) {
4507                                 warnx("only wrote %u bytes out of %u",
4508                                       valid_bytes - amt_to_write, valid_bytes);
4509                         }
4510                 }
4511         }
4512
4513 scsicmd_bailout:
4514
4515         if ((data_bytes > 0) && (data_ptr != NULL))
4516                 free(data_ptr);
4517
4518         cam_freeccb(ccb);
4519
4520         return(error);
4521 }
4522
4523 static int
4524 camdebug(int argc, char **argv, char *combinedopt)
4525 {
4526         int c, fd;
4527         path_id_t bus = CAM_BUS_WILDCARD;
4528         target_id_t target = CAM_TARGET_WILDCARD;
4529         lun_id_t lun = CAM_LUN_WILDCARD;
4530         char *tstr, *tmpstr = NULL;
4531         union ccb ccb;
4532         int error = 0;
4533
4534         bzero(&ccb, sizeof(union ccb));
4535
4536         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4537                 switch(c) {
4538                 case 'I':
4539                         arglist |= CAM_ARG_DEBUG_INFO;
4540                         ccb.cdbg.flags |= CAM_DEBUG_INFO;
4541                         break;
4542                 case 'P':
4543                         arglist |= CAM_ARG_DEBUG_PERIPH;
4544                         ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4545                         break;
4546                 case 'S':
4547                         arglist |= CAM_ARG_DEBUG_SUBTRACE;
4548                         ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4549                         break;
4550                 case 'T':
4551                         arglist |= CAM_ARG_DEBUG_TRACE;
4552                         ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4553                         break;
4554                 case 'X':
4555                         arglist |= CAM_ARG_DEBUG_XPT;
4556                         ccb.cdbg.flags |= CAM_DEBUG_XPT;
4557                         break;
4558                 case 'c':
4559                         arglist |= CAM_ARG_DEBUG_CDB;
4560                         ccb.cdbg.flags |= CAM_DEBUG_CDB;
4561                         break;
4562                 case 'p':
4563                         arglist |= CAM_ARG_DEBUG_PROBE;
4564                         ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4565                         break;
4566                 default:
4567                         break;
4568                 }
4569         }
4570
4571         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4572                 warnx("error opening transport layer device %s", XPT_DEVICE);
4573                 warn("%s", XPT_DEVICE);
4574                 return(1);
4575         }
4576         argc -= optind;
4577         argv += optind;
4578
4579         if (argc <= 0) {
4580                 warnx("you must specify \"off\", \"all\" or a bus,");
4581                 warnx("bus:target, or bus:target:lun");
4582                 close(fd);
4583                 return(1);
4584         }
4585
4586         tstr = *argv;
4587
4588         while (isspace(*tstr) && (*tstr != '\0'))
4589                 tstr++;
4590
4591         if (strncmp(tstr, "off", 3) == 0) {
4592                 ccb.cdbg.flags = CAM_DEBUG_NONE;
4593                 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4594                              CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4595                              CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4596         } else if (strncmp(tstr, "all", 3) != 0) {
4597                 tmpstr = (char *)strtok(tstr, ":");
4598                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4599                         bus = strtol(tmpstr, NULL, 0);
4600                         arglist |= CAM_ARG_BUS;
4601                         tmpstr = (char *)strtok(NULL, ":");
4602                         if ((tmpstr != NULL) && (*tmpstr != '\0')){
4603                                 target = strtol(tmpstr, NULL, 0);
4604                                 arglist |= CAM_ARG_TARGET;
4605                                 tmpstr = (char *)strtok(NULL, ":");
4606                                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4607                                         lun = strtol(tmpstr, NULL, 0);
4608                                         arglist |= CAM_ARG_LUN;
4609                                 }
4610                         }
4611                 } else {
4612                         error = 1;
4613                         warnx("you must specify \"all\", \"off\", or a bus,");
4614                         warnx("bus:target, or bus:target:lun to debug");
4615                 }
4616         }
4617
4618         if (error == 0) {
4619
4620                 ccb.ccb_h.func_code = XPT_DEBUG;
4621                 ccb.ccb_h.path_id = bus;
4622                 ccb.ccb_h.target_id = target;
4623                 ccb.ccb_h.target_lun = lun;
4624
4625                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4626                         warn("CAMIOCOMMAND ioctl failed");
4627                         error = 1;
4628                 }
4629
4630                 if (error == 0) {
4631                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4632                              CAM_FUNC_NOTAVAIL) {
4633                                 warnx("CAM debugging not available");
4634                                 warnx("you need to put options CAMDEBUG in"
4635                                       " your kernel config file!");
4636                                 error = 1;
4637                         } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4638                                     CAM_REQ_CMP) {
4639                                 warnx("XPT_DEBUG CCB failed with status %#x",
4640                                       ccb.ccb_h.status);
4641                                 error = 1;
4642                         } else {
4643                                 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4644                                         fprintf(stderr,
4645                                                 "Debugging turned off\n");
4646                                 } else {
4647                                         fprintf(stderr,
4648                                                 "Debugging enabled for "
4649                                                 "%d:%d:%jx\n",
4650                                                 bus, target, (uintmax_t)lun);
4651                                 }
4652                         }
4653                 }
4654                 close(fd);
4655         }
4656
4657         return(error);
4658 }
4659
4660 static int
4661 tagcontrol(struct cam_device *device, int argc, char **argv,
4662            char *combinedopt)
4663 {
4664         int c;
4665         union ccb *ccb;
4666         int numtags = -1;
4667         int retval = 0;
4668         int quiet = 0;
4669         char pathstr[1024];
4670
4671         ccb = cam_getccb(device);
4672
4673         if (ccb == NULL) {
4674                 warnx("tagcontrol: error allocating ccb");
4675                 return(1);
4676         }
4677
4678         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4679                 switch(c) {
4680                 case 'N':
4681                         numtags = strtol(optarg, NULL, 0);
4682                         if (numtags < 0) {
4683                                 warnx("tag count %d is < 0", numtags);
4684                                 retval = 1;
4685                                 goto tagcontrol_bailout;
4686                         }
4687                         break;
4688                 case 'q':
4689                         quiet++;
4690                         break;
4691                 default:
4692                         break;
4693                 }
4694         }
4695
4696         cam_path_string(device, pathstr, sizeof(pathstr));
4697
4698         if (numtags >= 0) {
4699                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->crs);
4700                 ccb->ccb_h.func_code = XPT_REL_SIMQ;
4701                 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4702                 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4703                 ccb->crs.openings = numtags;
4704
4705
4706                 if (cam_send_ccb(device, ccb) < 0) {
4707                         perror("error sending XPT_REL_SIMQ CCB");
4708                         retval = 1;
4709                         goto tagcontrol_bailout;
4710                 }
4711
4712                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4713                         warnx("XPT_REL_SIMQ CCB failed");
4714                         cam_error_print(device, ccb, CAM_ESF_ALL,
4715                                         CAM_EPF_ALL, stderr);
4716                         retval = 1;
4717                         goto tagcontrol_bailout;
4718                 }
4719
4720
4721                 if (quiet == 0)
4722                         fprintf(stdout, "%stagged openings now %d\n",
4723                                 pathstr, ccb->crs.openings);
4724         }
4725
4726         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgds);
4727
4728         ccb->ccb_h.func_code = XPT_GDEV_STATS;
4729
4730         if (cam_send_ccb(device, ccb) < 0) {
4731                 perror("error sending XPT_GDEV_STATS CCB");
4732                 retval = 1;
4733                 goto tagcontrol_bailout;
4734         }
4735
4736         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4737                 warnx("XPT_GDEV_STATS CCB failed");
4738                 cam_error_print(device, ccb, CAM_ESF_ALL,
4739                                 CAM_EPF_ALL, stderr);
4740                 retval = 1;
4741                 goto tagcontrol_bailout;
4742         }
4743
4744         if (arglist & CAM_ARG_VERBOSE) {
4745                 fprintf(stdout, "%s", pathstr);
4746                 fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4747                 fprintf(stdout, "%s", pathstr);
4748                 fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4749                 fprintf(stdout, "%s", pathstr);
4750                 fprintf(stdout, "allocated     %d\n", ccb->cgds.allocated);
4751                 fprintf(stdout, "%s", pathstr);
4752                 fprintf(stdout, "queued        %d\n", ccb->cgds.queued);
4753                 fprintf(stdout, "%s", pathstr);
4754                 fprintf(stdout, "held          %d\n", ccb->cgds.held);
4755                 fprintf(stdout, "%s", pathstr);
4756                 fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4757                 fprintf(stdout, "%s", pathstr);
4758                 fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4759         } else {
4760                 if (quiet == 0) {
4761                         fprintf(stdout, "%s", pathstr);
4762                         fprintf(stdout, "device openings: ");
4763                 }
4764                 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4765                         ccb->cgds.dev_active);
4766         }
4767
4768 tagcontrol_bailout:
4769
4770         cam_freeccb(ccb);
4771         return(retval);
4772 }
4773
4774 static void
4775 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4776 {
4777         char pathstr[1024];
4778
4779         cam_path_string(device, pathstr, sizeof(pathstr));
4780
4781         if (cts->transport == XPORT_SPI) {
4782                 struct ccb_trans_settings_spi *spi =
4783                     &cts->xport_specific.spi;
4784
4785                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4786
4787                         fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4788                                 spi->sync_period);
4789
4790                         if (spi->sync_offset != 0) {
4791                                 u_int freq;
4792
4793                                 freq = scsi_calc_syncsrate(spi->sync_period);
4794                                 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4795                                         pathstr, freq / 1000, freq % 1000);
4796                         }
4797                 }
4798
4799                 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4800                         fprintf(stdout, "%soffset: %d\n", pathstr,
4801                             spi->sync_offset);
4802                 }
4803
4804                 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4805                         fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4806                                 (0x01 << spi->bus_width) * 8);
4807                 }
4808
4809                 if (spi->valid & CTS_SPI_VALID_DISC) {
4810                         fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4811                                 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4812                                 "enabled" : "disabled");
4813                 }
4814         }
4815         if (cts->transport == XPORT_FC) {
4816                 struct ccb_trans_settings_fc *fc =
4817                     &cts->xport_specific.fc;
4818
4819                 if (fc->valid & CTS_FC_VALID_WWNN)
4820                         fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4821                             (long long) fc->wwnn);
4822                 if (fc->valid & CTS_FC_VALID_WWPN)
4823                         fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4824                             (long long) fc->wwpn);
4825                 if (fc->valid & CTS_FC_VALID_PORT)
4826                         fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4827                 if (fc->valid & CTS_FC_VALID_SPEED)
4828                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4829                             pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4830         }
4831         if (cts->transport == XPORT_SAS) {
4832                 struct ccb_trans_settings_sas *sas =
4833                     &cts->xport_specific.sas;
4834
4835                 if (sas->valid & CTS_SAS_VALID_SPEED)
4836                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4837                             pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4838         }
4839         if (cts->transport == XPORT_ATA) {
4840                 struct ccb_trans_settings_pata *pata =
4841                     &cts->xport_specific.ata;
4842
4843                 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4844                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4845                                 ata_mode2string(pata->mode));
4846                 }
4847                 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4848                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4849                                 pata->atapi);
4850                 }
4851                 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4852                         fprintf(stdout, "%sPIO transaction length: %d\n",
4853                                 pathstr, pata->bytecount);
4854                 }
4855         }
4856         if (cts->transport == XPORT_SATA) {
4857                 struct ccb_trans_settings_sata *sata =
4858                     &cts->xport_specific.sata;
4859
4860                 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4861                         fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4862                                 sata->revision);
4863                 }
4864                 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4865                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4866                                 ata_mode2string(sata->mode));
4867                 }
4868                 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4869                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4870                                 sata->atapi);
4871                 }
4872                 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4873                         fprintf(stdout, "%sPIO transaction length: %d\n",
4874                                 pathstr, sata->bytecount);
4875                 }
4876                 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4877                         fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4878                                 sata->pm_present);
4879                 }
4880                 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4881                         fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4882                                 sata->tags);
4883                 }
4884                 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4885                         fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4886                                 sata->caps);
4887                 }
4888         }
4889         if (cts->protocol == PROTO_ATA) {
4890                 struct ccb_trans_settings_ata *ata=
4891                     &cts->proto_specific.ata;
4892
4893                 if (ata->valid & CTS_ATA_VALID_TQ) {
4894                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4895                                 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4896                                 "enabled" : "disabled");
4897                 }
4898         }
4899         if (cts->protocol == PROTO_SCSI) {
4900                 struct ccb_trans_settings_scsi *scsi=
4901                     &cts->proto_specific.scsi;
4902
4903                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
4904                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4905                                 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4906                                 "enabled" : "disabled");
4907                 }
4908         }
4909
4910 }
4911
4912 /*
4913  * Get a path inquiry CCB for the specified device.
4914  */
4915 static int
4916 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4917 {
4918         union ccb *ccb;
4919         int retval = 0;
4920
4921         ccb = cam_getccb(device);
4922         if (ccb == NULL) {
4923                 warnx("get_cpi: couldn't allocate CCB");
4924                 return(1);
4925         }
4926         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
4927         ccb->ccb_h.func_code = XPT_PATH_INQ;
4928         if (cam_send_ccb(device, ccb) < 0) {
4929                 warn("get_cpi: error sending Path Inquiry CCB");
4930                 if (arglist & CAM_ARG_VERBOSE)
4931                         cam_error_print(device, ccb, CAM_ESF_ALL,
4932                                         CAM_EPF_ALL, stderr);
4933                 retval = 1;
4934                 goto get_cpi_bailout;
4935         }
4936         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4937                 if (arglist & CAM_ARG_VERBOSE)
4938                         cam_error_print(device, ccb, CAM_ESF_ALL,
4939                                         CAM_EPF_ALL, stderr);
4940                 retval = 1;
4941                 goto get_cpi_bailout;
4942         }
4943         bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4944
4945 get_cpi_bailout:
4946         cam_freeccb(ccb);
4947         return(retval);
4948 }
4949
4950 /*
4951  * Get a get device CCB for the specified device.
4952  */
4953 static int
4954 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4955 {
4956         union ccb *ccb;
4957         int retval = 0;
4958
4959         ccb = cam_getccb(device);
4960         if (ccb == NULL) {
4961                 warnx("get_cgd: couldn't allocate CCB");
4962                 return(1);
4963         }
4964         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgd);
4965         ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4966         if (cam_send_ccb(device, ccb) < 0) {
4967                 warn("get_cgd: error sending Path Inquiry CCB");
4968                 if (arglist & CAM_ARG_VERBOSE)
4969                         cam_error_print(device, ccb, CAM_ESF_ALL,
4970                                         CAM_EPF_ALL, stderr);
4971                 retval = 1;
4972                 goto get_cgd_bailout;
4973         }
4974         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4975                 if (arglist & CAM_ARG_VERBOSE)
4976                         cam_error_print(device, ccb, CAM_ESF_ALL,
4977                                         CAM_EPF_ALL, stderr);
4978                 retval = 1;
4979                 goto get_cgd_bailout;
4980         }
4981         bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4982
4983 get_cgd_bailout:
4984         cam_freeccb(ccb);
4985         return(retval);
4986 }
4987
4988 /*
4989  * Returns 1 if the device has the VPD page, 0 if it does not, and -1 on an
4990  * error.
4991  */
4992 int
4993 dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count,
4994                  int timeout, int verbosemode)
4995 {
4996         union ccb *ccb = NULL;
4997         struct scsi_vpd_supported_page_list sup_pages;
4998         int i;
4999         int retval = 0;
5000
5001         ccb = cam_getccb(dev);
5002         if (ccb == NULL) {
5003                 warn("Unable to allocate CCB");
5004                 retval = -1;
5005                 goto bailout;
5006         }
5007         
5008         /* cam_getccb cleans up the header, caller has to zero the payload */
5009         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5010
5011         bzero(&sup_pages, sizeof(sup_pages));
5012
5013         scsi_inquiry(&ccb->csio,
5014                      /*retries*/ retry_count,
5015                      /*cbfcnp*/ NULL,
5016                      /* tag_action */ MSG_SIMPLE_Q_TAG,
5017                      /* inq_buf */ (u_int8_t *)&sup_pages,
5018                      /* inq_len */ sizeof(sup_pages),
5019                      /* evpd */ 1,
5020                      /* page_code */ SVPD_SUPPORTED_PAGE_LIST,
5021                      /* sense_len */ SSD_FULL_SIZE,
5022                      /* timeout */ timeout ? timeout : 5000);
5023
5024         /* Disable freezing the device queue */
5025         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5026
5027         if (retry_count != 0)
5028                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5029
5030         if (cam_send_ccb(dev, ccb) < 0) {
5031                 cam_freeccb(ccb);
5032                 ccb = NULL;
5033                 retval = -1;
5034                 goto bailout;
5035         }
5036
5037         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5038                 if (verbosemode != 0)
5039                         cam_error_print(dev, ccb, CAM_ESF_ALL,
5040                                         CAM_EPF_ALL, stderr);
5041                 retval = -1;
5042                 goto bailout;
5043         }
5044
5045         for (i = 0; i < sup_pages.length; i++) {
5046                 if (sup_pages.list[i] == page_id) {
5047                         retval = 1;
5048                         goto bailout;
5049                 }
5050         }
5051 bailout:
5052         if (ccb != NULL)
5053                 cam_freeccb(ccb);
5054         
5055         return (retval);
5056 }
5057
5058 /*
5059  * devtype is filled in with the type of device.
5060  * Returns 0 for success, non-zero for failure.
5061  */
5062 int
5063 get_device_type(struct cam_device *dev, int retry_count, int timeout,
5064                     int verbosemode, camcontrol_devtype *devtype)
5065 {
5066         struct ccb_getdev cgd;
5067         int retval = 0;
5068
5069         retval = get_cgd(dev, &cgd);
5070         if (retval != 0)
5071                 goto bailout;
5072
5073         switch (cgd.protocol) {
5074         case PROTO_SCSI:
5075                 break;
5076         case PROTO_ATA:
5077         case PROTO_ATAPI:
5078         case PROTO_SATAPM:
5079                 *devtype = CC_DT_ATA;
5080                 goto bailout;
5081                 break; /*NOTREACHED*/
5082         default:
5083                 *devtype = CC_DT_UNKNOWN;
5084                 goto bailout; 
5085                 break; /*NOTREACHED*/
5086         }
5087
5088         /*
5089          * Check for the ATA Information VPD page (0x89).  If this is an
5090          * ATA device behind a SCSI to ATA translation layer, this VPD page
5091          * should be present.
5092          *
5093          * If that VPD page isn't present, or we get an error back from the
5094          * INQUIRY command, we'll just treat it as a normal SCSI device.
5095          */
5096         retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5097                                   timeout, verbosemode);
5098         if (retval == 1)
5099                 *devtype = CC_DT_ATA_BEHIND_SCSI;
5100         else
5101                 *devtype = CC_DT_SCSI;
5102
5103         retval = 0;
5104
5105 bailout:
5106         return (retval);
5107 }
5108
5109 void
5110 build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5111     uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5112     uint16_t sector_count, uint64_t lba, uint8_t command, uint8_t *data_ptr,
5113     uint16_t dxfer_len, uint8_t sense_len, uint32_t timeout,
5114     int is48bit, camcontrol_devtype devtype)
5115 {
5116         if (devtype == CC_DT_ATA) {
5117                 cam_fill_ataio(&ccb->ataio,
5118                     /*retries*/ retry_count,
5119                     /*cbfcnp*/ NULL,
5120                     /*flags*/ flags,
5121                     /*tag_action*/ tag_action,
5122                     /*data_ptr*/ data_ptr,
5123                     /*dxfer_len*/ dxfer_len,
5124                     /*timeout*/ timeout);
5125                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5126                         ata_48bit_cmd(&ccb->ataio, command, features, lba,
5127                             sector_count);
5128                 else
5129                         ata_28bit_cmd(&ccb->ataio, command, features, lba,
5130                             sector_count);
5131         } else {
5132                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5133                         protocol |= AP_EXTEND;
5134
5135                 scsi_ata_pass_16(&ccb->csio,
5136                     /*retries*/ retry_count,
5137                     /*cbfcnp*/ NULL,
5138                     /*flags*/ flags,
5139                     /*tag_action*/ tag_action,
5140                     /*protocol*/ protocol,
5141                     /*ata_flags*/ ata_flags,
5142                     /*features*/ features,
5143                     /*sector_count*/ sector_count, 
5144                     /*lba*/ lba,
5145                     /*command*/ command,
5146                     /*control*/ 0,
5147                     /*data_ptr*/ data_ptr,
5148                     /*dxfer_len*/ dxfer_len,
5149                     /*sense_len*/ sense_len,
5150                     /*timeout*/ timeout);
5151         }
5152 }
5153
5154
5155 static void
5156 cpi_print(struct ccb_pathinq *cpi)
5157 {
5158         char adapter_str[1024];
5159         uint64_t i;
5160
5161         snprintf(adapter_str, sizeof(adapter_str),
5162                  "%s%d:", cpi->dev_name, cpi->unit_number);
5163
5164         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5165                 cpi->version_num);
5166
5167         for (i = 1; i < UINT8_MAX; i = i << 1) {
5168                 const char *str;
5169
5170                 if ((i & cpi->hba_inquiry) == 0)
5171                         continue;
5172
5173                 fprintf(stdout, "%s supports ", adapter_str);
5174
5175                 switch(i) {
5176                 case PI_MDP_ABLE:
5177                         str = "MDP message";
5178                         break;
5179                 case PI_WIDE_32:
5180                         str = "32 bit wide SCSI";
5181                         break;
5182                 case PI_WIDE_16:
5183                         str = "16 bit wide SCSI";
5184                         break;
5185                 case PI_SDTR_ABLE:
5186                         str = "SDTR message";
5187                         break;
5188                 case PI_LINKED_CDB:
5189                         str = "linked CDBs";
5190                         break;
5191                 case PI_TAG_ABLE:
5192                         str = "tag queue messages";
5193                         break;
5194                 case PI_SOFT_RST:
5195                         str = "soft reset alternative";
5196                         break;
5197                 case PI_SATAPM:
5198                         str = "SATA Port Multiplier";
5199                         break;
5200                 default:
5201                         str = "unknown PI bit set";
5202                         break;
5203                 }
5204                 fprintf(stdout, "%s\n", str);
5205         }
5206
5207         for (i = 1; i < UINT32_MAX; i = i << 1) {
5208                 const char *str;
5209
5210                 if ((i & cpi->hba_misc) == 0)
5211                         continue;
5212
5213                 fprintf(stdout, "%s ", adapter_str);
5214
5215                 switch(i) {
5216                 case PIM_SCANHILO:
5217                         str = "bus scans from high ID to low ID";
5218                         break;
5219                 case PIM_NOREMOVE:
5220                         str = "removable devices not included in scan";
5221                         break;
5222                 case PIM_NOINITIATOR:
5223                         str = "initiator role not supported";
5224                         break;
5225                 case PIM_NOBUSRESET:
5226                         str = "user has disabled initial BUS RESET or"
5227                               " controller is in target/mixed mode";
5228                         break;
5229                 case PIM_NO_6_BYTE:
5230                         str = "do not send 6-byte commands";
5231                         break;
5232                 case PIM_SEQSCAN:
5233                         str = "scan bus sequentially";
5234                         break;
5235                 default:
5236                         str = "unknown PIM bit set";
5237                         break;
5238                 }
5239                 fprintf(stdout, "%s\n", str);
5240         }
5241
5242         for (i = 1; i < UINT16_MAX; i = i << 1) {
5243                 const char *str;
5244
5245                 if ((i & cpi->target_sprt) == 0)
5246                         continue;
5247
5248                 fprintf(stdout, "%s supports ", adapter_str);
5249                 switch(i) {
5250                 case PIT_PROCESSOR:
5251                         str = "target mode processor mode";
5252                         break;
5253                 case PIT_PHASE:
5254                         str = "target mode phase cog. mode";
5255                         break;
5256                 case PIT_DISCONNECT:
5257                         str = "disconnects in target mode";
5258                         break;
5259                 case PIT_TERM_IO:
5260                         str = "terminate I/O message in target mode";
5261                         break;
5262                 case PIT_GRP_6:
5263                         str = "group 6 commands in target mode";
5264                         break;
5265                 case PIT_GRP_7:
5266                         str = "group 7 commands in target mode";
5267                         break;
5268                 default:
5269                         str = "unknown PIT bit set";
5270                         break;
5271                 }
5272
5273                 fprintf(stdout, "%s\n", str);
5274         }
5275         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5276                 cpi->hba_eng_cnt);
5277         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5278                 cpi->max_target);
5279         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5280                 cpi->max_lun);
5281         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5282                 adapter_str, cpi->hpath_id);
5283         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5284                 cpi->initiator_id);
5285         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5286         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5287         fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5288             adapter_str, cpi->hba_vendor);
5289         fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5290             adapter_str, cpi->hba_device);
5291         fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5292             adapter_str, cpi->hba_subvendor);
5293         fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5294             adapter_str, cpi->hba_subdevice);
5295         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5296         fprintf(stdout, "%s base transfer speed: ", adapter_str);
5297         if (cpi->base_transfer_speed > 1000)
5298                 fprintf(stdout, "%d.%03dMB/sec\n",
5299                         cpi->base_transfer_speed / 1000,
5300                         cpi->base_transfer_speed % 1000);
5301         else
5302                 fprintf(stdout, "%dKB/sec\n",
5303                         (cpi->base_transfer_speed % 1000) * 1000);
5304         fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5305             adapter_str, cpi->maxio);
5306 }
5307
5308 static int
5309 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5310               struct ccb_trans_settings *cts)
5311 {
5312         int retval;
5313         union ccb *ccb;
5314
5315         retval = 0;
5316         ccb = cam_getccb(device);
5317
5318         if (ccb == NULL) {
5319                 warnx("get_print_cts: error allocating ccb");
5320                 return(1);
5321         }
5322
5323         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5324
5325         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5326
5327         if (user_settings == 0)
5328                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5329         else
5330                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5331
5332         if (cam_send_ccb(device, ccb) < 0) {
5333                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5334                 if (arglist & CAM_ARG_VERBOSE)
5335                         cam_error_print(device, ccb, CAM_ESF_ALL,
5336                                         CAM_EPF_ALL, stderr);
5337                 retval = 1;
5338                 goto get_print_cts_bailout;
5339         }
5340
5341         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5342                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5343                 if (arglist & CAM_ARG_VERBOSE)
5344                         cam_error_print(device, ccb, CAM_ESF_ALL,
5345                                         CAM_EPF_ALL, stderr);
5346                 retval = 1;
5347                 goto get_print_cts_bailout;
5348         }
5349
5350         if (quiet == 0)
5351                 cts_print(device, &ccb->cts);
5352
5353         if (cts != NULL)
5354                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5355
5356 get_print_cts_bailout:
5357
5358         cam_freeccb(ccb);
5359
5360         return(retval);
5361 }
5362
5363 static int
5364 ratecontrol(struct cam_device *device, int task_attr, int retry_count,
5365             int timeout, int argc, char **argv, char *combinedopt)
5366 {
5367         int c;
5368         union ccb *ccb;
5369         int user_settings = 0;
5370         int retval = 0;
5371         int disc_enable = -1, tag_enable = -1;
5372         int mode = -1;
5373         int offset = -1;
5374         double syncrate = -1;
5375         int bus_width = -1;
5376         int quiet = 0;
5377         int change_settings = 0, send_tur = 0;
5378         struct ccb_pathinq cpi;
5379
5380         ccb = cam_getccb(device);
5381         if (ccb == NULL) {
5382                 warnx("ratecontrol: error allocating ccb");
5383                 return(1);
5384         }
5385         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5386                 switch(c){
5387                 case 'a':
5388                         send_tur = 1;
5389                         break;
5390                 case 'c':
5391                         user_settings = 0;
5392                         break;
5393                 case 'D':
5394                         if (strncasecmp(optarg, "enable", 6) == 0)
5395                                 disc_enable = 1;
5396                         else if (strncasecmp(optarg, "disable", 7) == 0)
5397                                 disc_enable = 0;
5398                         else {
5399                                 warnx("-D argument \"%s\" is unknown", optarg);
5400                                 retval = 1;
5401                                 goto ratecontrol_bailout;
5402                         }
5403                         change_settings = 1;
5404                         break;
5405                 case 'M':
5406                         mode = ata_string2mode(optarg);
5407                         if (mode < 0) {
5408                                 warnx("unknown mode '%s'", optarg);
5409                                 retval = 1;
5410                                 goto ratecontrol_bailout;
5411                         }
5412                         change_settings = 1;
5413                         break;
5414                 case 'O':
5415                         offset = strtol(optarg, NULL, 0);
5416                         if (offset < 0) {
5417                                 warnx("offset value %d is < 0", offset);
5418                                 retval = 1;
5419                                 goto ratecontrol_bailout;
5420                         }
5421                         change_settings = 1;
5422                         break;
5423                 case 'q':
5424                         quiet++;
5425                         break;
5426                 case 'R':
5427                         syncrate = atof(optarg);
5428                         if (syncrate < 0) {
5429                                 warnx("sync rate %f is < 0", syncrate);
5430                                 retval = 1;
5431                                 goto ratecontrol_bailout;
5432                         }
5433                         change_settings = 1;
5434                         break;
5435                 case 'T':
5436                         if (strncasecmp(optarg, "enable", 6) == 0)
5437                                 tag_enable = 1;
5438                         else if (strncasecmp(optarg, "disable", 7) == 0)
5439                                 tag_enable = 0;
5440                         else {
5441                                 warnx("-T argument \"%s\" is unknown", optarg);
5442                                 retval = 1;
5443                                 goto ratecontrol_bailout;
5444                         }
5445                         change_settings = 1;
5446                         break;
5447                 case 'U':
5448                         user_settings = 1;
5449                         break;
5450                 case 'W':
5451                         bus_width = strtol(optarg, NULL, 0);
5452                         if (bus_width < 0) {
5453                                 warnx("bus width %d is < 0", bus_width);
5454                                 retval = 1;
5455                                 goto ratecontrol_bailout;
5456                         }
5457                         change_settings = 1;
5458                         break;
5459                 default:
5460                         break;
5461                 }
5462         }
5463         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
5464         /*
5465          * Grab path inquiry information, so we can determine whether
5466          * or not the initiator is capable of the things that the user
5467          * requests.
5468          */
5469         ccb->ccb_h.func_code = XPT_PATH_INQ;
5470         if (cam_send_ccb(device, ccb) < 0) {
5471                 perror("error sending XPT_PATH_INQ CCB");
5472                 if (arglist & CAM_ARG_VERBOSE) {
5473                         cam_error_print(device, ccb, CAM_ESF_ALL,
5474                                         CAM_EPF_ALL, stderr);
5475                 }
5476                 retval = 1;
5477                 goto ratecontrol_bailout;
5478         }
5479         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5480                 warnx("XPT_PATH_INQ CCB failed");
5481                 if (arglist & CAM_ARG_VERBOSE) {
5482                         cam_error_print(device, ccb, CAM_ESF_ALL,
5483                                         CAM_EPF_ALL, stderr);
5484                 }
5485                 retval = 1;
5486                 goto ratecontrol_bailout;
5487         }
5488         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5489         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5490         if (quiet == 0) {
5491                 fprintf(stdout, "%s parameters:\n",
5492                     user_settings ? "User" : "Current");
5493         }
5494         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5495         if (retval != 0)
5496                 goto ratecontrol_bailout;
5497
5498         if (arglist & CAM_ARG_VERBOSE)
5499                 cpi_print(&cpi);
5500
5501         if (change_settings) {
5502                 int didsettings = 0;
5503                 struct ccb_trans_settings_spi *spi = NULL;
5504                 struct ccb_trans_settings_pata *pata = NULL;
5505                 struct ccb_trans_settings_sata *sata = NULL;
5506                 struct ccb_trans_settings_ata *ata = NULL;
5507                 struct ccb_trans_settings_scsi *scsi = NULL;
5508
5509                 if (ccb->cts.transport == XPORT_SPI)
5510                         spi = &ccb->cts.xport_specific.spi;
5511                 if (ccb->cts.transport == XPORT_ATA)
5512                         pata = &ccb->cts.xport_specific.ata;
5513                 if (ccb->cts.transport == XPORT_SATA)
5514                         sata = &ccb->cts.xport_specific.sata;
5515                 if (ccb->cts.protocol == PROTO_ATA)
5516                         ata = &ccb->cts.proto_specific.ata;
5517                 if (ccb->cts.protocol == PROTO_SCSI)
5518                         scsi = &ccb->cts.proto_specific.scsi;
5519                 ccb->cts.xport_specific.valid = 0;
5520                 ccb->cts.proto_specific.valid = 0;
5521                 if (spi && disc_enable != -1) {
5522                         spi->valid |= CTS_SPI_VALID_DISC;
5523                         if (disc_enable == 0)
5524                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5525                         else
5526                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5527                         didsettings++;
5528                 }
5529                 if (tag_enable != -1) {
5530                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5531                                 warnx("HBA does not support tagged queueing, "
5532                                       "so you cannot modify tag settings");
5533                                 retval = 1;
5534                                 goto ratecontrol_bailout;
5535                         }
5536                         if (ata) {
5537                                 ata->valid |= CTS_SCSI_VALID_TQ;
5538                                 if (tag_enable == 0)
5539                                         ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5540                                 else
5541                                         ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5542                                 didsettings++;
5543                         } else if (scsi) {
5544                                 scsi->valid |= CTS_SCSI_VALID_TQ;
5545                                 if (tag_enable == 0)
5546                                         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5547                                 else
5548                                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5549                                 didsettings++;
5550                         }
5551                 }
5552                 if (spi && offset != -1) {
5553                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5554                                 warnx("HBA is not capable of changing offset");
5555                                 retval = 1;
5556                                 goto ratecontrol_bailout;
5557                         }
5558                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5559                         spi->sync_offset = offset;
5560                         didsettings++;
5561                 }
5562                 if (spi && syncrate != -1) {
5563                         int prelim_sync_period;
5564
5565                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5566                                 warnx("HBA is not capable of changing "
5567                                       "transfer rates");
5568                                 retval = 1;
5569                                 goto ratecontrol_bailout;
5570                         }
5571                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5572                         /*
5573                          * The sync rate the user gives us is in MHz.
5574                          * We need to translate it into KHz for this
5575                          * calculation.
5576                          */
5577                         syncrate *= 1000;
5578                         /*
5579                          * Next, we calculate a "preliminary" sync period
5580                          * in tenths of a nanosecond.
5581                          */
5582                         if (syncrate == 0)
5583                                 prelim_sync_period = 0;
5584                         else
5585                                 prelim_sync_period = 10000000 / syncrate;
5586                         spi->sync_period =
5587                                 scsi_calc_syncparam(prelim_sync_period);
5588                         didsettings++;
5589                 }
5590                 if (sata && syncrate != -1) {
5591                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5592                                 warnx("HBA is not capable of changing "
5593                                       "transfer rates");
5594                                 retval = 1;
5595                                 goto ratecontrol_bailout;
5596                         }
5597                         if  (!user_settings) {
5598                                 warnx("You can modify only user rate "
5599                                     "settings for SATA");
5600                                 retval = 1;
5601                                 goto ratecontrol_bailout;
5602                         }
5603                         sata->revision = ata_speed2revision(syncrate * 100);
5604                         if (sata->revision < 0) {
5605                                 warnx("Invalid rate %f", syncrate);
5606                                 retval = 1;
5607                                 goto ratecontrol_bailout;
5608                         }
5609                         sata->valid |= CTS_SATA_VALID_REVISION;
5610                         didsettings++;
5611                 }
5612                 if ((pata || sata) && mode != -1) {
5613                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5614                                 warnx("HBA is not capable of changing "
5615                                       "transfer rates");
5616                                 retval = 1;
5617                                 goto ratecontrol_bailout;
5618                         }
5619                         if  (!user_settings) {
5620                                 warnx("You can modify only user mode "
5621                                     "settings for ATA/SATA");
5622                                 retval = 1;
5623                                 goto ratecontrol_bailout;
5624                         }
5625                         if (pata) {
5626                                 pata->mode = mode;
5627                                 pata->valid |= CTS_ATA_VALID_MODE;
5628                         } else {
5629                                 sata->mode = mode;
5630                                 sata->valid |= CTS_SATA_VALID_MODE;
5631                         }
5632                         didsettings++;
5633                 }
5634                 /*
5635                  * The bus_width argument goes like this:
5636                  * 0 == 8 bit
5637                  * 1 == 16 bit
5638                  * 2 == 32 bit
5639                  * Therefore, if you shift the number of bits given on the
5640                  * command line right by 4, you should get the correct
5641                  * number.
5642                  */
5643                 if (spi && bus_width != -1) {
5644                         /*
5645                          * We might as well validate things here with a
5646                          * decipherable error message, rather than what
5647                          * will probably be an indecipherable error message
5648                          * by the time it gets back to us.
5649                          */
5650                         if ((bus_width == 16)
5651                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5652                                 warnx("HBA does not support 16 bit bus width");
5653                                 retval = 1;
5654                                 goto ratecontrol_bailout;
5655                         } else if ((bus_width == 32)
5656                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5657                                 warnx("HBA does not support 32 bit bus width");
5658                                 retval = 1;
5659                                 goto ratecontrol_bailout;
5660                         } else if ((bus_width != 8)
5661                                 && (bus_width != 16)
5662                                 && (bus_width != 32)) {
5663                                 warnx("Invalid bus width %d", bus_width);
5664                                 retval = 1;
5665                                 goto ratecontrol_bailout;
5666                         }
5667                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5668                         spi->bus_width = bus_width >> 4;
5669                         didsettings++;
5670                 }
5671                 if  (didsettings == 0) {
5672                         goto ratecontrol_bailout;
5673                 }
5674                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5675                 if (cam_send_ccb(device, ccb) < 0) {
5676                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5677                         if (arglist & CAM_ARG_VERBOSE) {
5678                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5679                                                 CAM_EPF_ALL, stderr);
5680                         }
5681                         retval = 1;
5682                         goto ratecontrol_bailout;
5683                 }
5684                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5685                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5686                         if (arglist & CAM_ARG_VERBOSE) {
5687                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5688                                                 CAM_EPF_ALL, stderr);
5689                         }
5690                         retval = 1;
5691                         goto ratecontrol_bailout;
5692                 }
5693         }
5694         if (send_tur) {
5695                 retval = testunitready(device, task_attr, retry_count, timeout,
5696                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5697                 /*
5698                  * If the TUR didn't succeed, just bail.
5699                  */
5700                 if (retval != 0) {
5701                         if (quiet == 0)
5702                                 fprintf(stderr, "Test Unit Ready failed\n");
5703                         goto ratecontrol_bailout;
5704                 }
5705         }
5706         if ((change_settings || send_tur) && !quiet &&
5707             (ccb->cts.transport == XPORT_ATA ||
5708              ccb->cts.transport == XPORT_SATA || send_tur)) {
5709                 fprintf(stdout, "New parameters:\n");
5710                 retval = get_print_cts(device, user_settings, 0, NULL);
5711         }
5712
5713 ratecontrol_bailout:
5714         cam_freeccb(ccb);
5715         return(retval);
5716 }
5717
5718 static int
5719 scsiformat(struct cam_device *device, int argc, char **argv,
5720            char *combinedopt, int task_attr, int retry_count, int timeout)
5721 {
5722         union ccb *ccb;
5723         int c;
5724         int ycount = 0, quiet = 0;
5725         int error = 0, retval = 0;
5726         int use_timeout = 10800 * 1000;
5727         int immediate = 1;
5728         struct format_defect_list_header fh;
5729         u_int8_t *data_ptr = NULL;
5730         u_int32_t dxfer_len = 0;
5731         u_int8_t byte2 = 0;
5732         int num_warnings = 0;
5733         int reportonly = 0;
5734
5735         ccb = cam_getccb(device);
5736
5737         if (ccb == NULL) {
5738                 warnx("scsiformat: error allocating ccb");
5739                 return(1);
5740         }
5741
5742         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5743
5744         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5745                 switch(c) {
5746                 case 'q':
5747                         quiet++;
5748                         break;
5749                 case 'r':
5750                         reportonly = 1;
5751                         break;
5752                 case 'w':
5753                         immediate = 0;
5754                         break;
5755                 case 'y':
5756                         ycount++;
5757                         break;
5758                 }
5759         }
5760
5761         if (reportonly)
5762                 goto doreport;
5763
5764         if (quiet == 0) {
5765                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5766                         "following device:\n");
5767
5768                 error = scsidoinquiry(device, argc, argv, combinedopt,
5769                                       task_attr, retry_count, timeout);
5770
5771                 if (error != 0) {
5772                         warnx("scsiformat: error sending inquiry");
5773                         goto scsiformat_bailout;
5774                 }
5775         }
5776
5777         if (ycount == 0) {
5778                 if (!get_confirmation()) {
5779                         error = 1;
5780                         goto scsiformat_bailout;
5781                 }
5782         }
5783
5784         if (timeout != 0)
5785                 use_timeout = timeout;
5786
5787         if (quiet == 0) {
5788                 fprintf(stdout, "Current format timeout is %d seconds\n",
5789                         use_timeout / 1000);
5790         }
5791
5792         /*
5793          * If the user hasn't disabled questions and didn't specify a
5794          * timeout on the command line, ask them if they want the current
5795          * timeout.
5796          */
5797         if ((ycount == 0)
5798          && (timeout == 0)) {
5799                 char str[1024];
5800                 int new_timeout = 0;
5801
5802                 fprintf(stdout, "Enter new timeout in seconds or press\n"
5803                         "return to keep the current timeout [%d] ",
5804                         use_timeout / 1000);
5805
5806                 if (fgets(str, sizeof(str), stdin) != NULL) {
5807                         if (str[0] != '\0')
5808                                 new_timeout = atoi(str);
5809                 }
5810
5811                 if (new_timeout != 0) {
5812                         use_timeout = new_timeout * 1000;
5813                         fprintf(stdout, "Using new timeout value %d\n",
5814                                 use_timeout / 1000);
5815                 }
5816         }
5817
5818         /*
5819          * Keep this outside the if block below to silence any unused
5820          * variable warnings.
5821          */
5822         bzero(&fh, sizeof(fh));
5823
5824         /*
5825          * If we're in immediate mode, we've got to include the format
5826          * header
5827          */
5828         if (immediate != 0) {
5829                 fh.byte2 = FU_DLH_IMMED;
5830                 data_ptr = (u_int8_t *)&fh;
5831                 dxfer_len = sizeof(fh);
5832                 byte2 = FU_FMT_DATA;
5833         } else if (quiet == 0) {
5834                 fprintf(stdout, "Formatting...");
5835                 fflush(stdout);
5836         }
5837
5838         scsi_format_unit(&ccb->csio,
5839                          /* retries */ retry_count,
5840                          /* cbfcnp */ NULL,
5841                          /* tag_action */ task_attr,
5842                          /* byte2 */ byte2,
5843                          /* ileave */ 0,
5844                          /* data_ptr */ data_ptr,
5845                          /* dxfer_len */ dxfer_len,
5846                          /* sense_len */ SSD_FULL_SIZE,
5847                          /* timeout */ use_timeout);
5848
5849         /* Disable freezing the device queue */
5850         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5851
5852         if (arglist & CAM_ARG_ERR_RECOVER)
5853                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5854
5855         if (((retval = cam_send_ccb(device, ccb)) < 0)
5856          || ((immediate == 0)
5857            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5858                 const char errstr[] = "error sending format command";
5859
5860                 if (retval < 0)
5861                         warn(errstr);
5862                 else
5863                         warnx(errstr);
5864
5865                 if (arglist & CAM_ARG_VERBOSE) {
5866                         cam_error_print(device, ccb, CAM_ESF_ALL,
5867                                         CAM_EPF_ALL, stderr);
5868                 }
5869                 error = 1;
5870                 goto scsiformat_bailout;
5871         }
5872
5873         /*
5874          * If we ran in non-immediate mode, we already checked for errors
5875          * above and printed out any necessary information.  If we're in
5876          * immediate mode, we need to loop through and get status
5877          * information periodically.
5878          */
5879         if (immediate == 0) {
5880                 if (quiet == 0) {
5881                         fprintf(stdout, "Format Complete\n");
5882                 }
5883                 goto scsiformat_bailout;
5884         }
5885
5886 doreport:
5887         do {
5888                 cam_status status;
5889
5890                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5891
5892                 /*
5893                  * There's really no need to do error recovery or
5894                  * retries here, since we're just going to sit in a
5895                  * loop and wait for the device to finish formatting.
5896                  */
5897                 scsi_test_unit_ready(&ccb->csio,
5898                                      /* retries */ 0,
5899                                      /* cbfcnp */ NULL,
5900                                      /* tag_action */ task_attr,
5901                                      /* sense_len */ SSD_FULL_SIZE,
5902                                      /* timeout */ 5000);
5903
5904                 /* Disable freezing the device queue */
5905                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5906
5907                 retval = cam_send_ccb(device, ccb);
5908
5909                 /*
5910                  * If we get an error from the ioctl, bail out.  SCSI
5911                  * errors are expected.
5912                  */
5913                 if (retval < 0) {
5914                         warn("error sending CAMIOCOMMAND ioctl");
5915                         if (arglist & CAM_ARG_VERBOSE) {
5916                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5917                                                 CAM_EPF_ALL, stderr);
5918                         }
5919                         error = 1;
5920                         goto scsiformat_bailout;
5921                 }
5922
5923                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5924
5925                 if ((status != CAM_REQ_CMP)
5926                  && (status == CAM_SCSI_STATUS_ERROR)
5927                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5928                         struct scsi_sense_data *sense;
5929                         int error_code, sense_key, asc, ascq;
5930
5931                         sense = &ccb->csio.sense_data;
5932                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
5933                             ccb->csio.sense_resid, &error_code, &sense_key,
5934                             &asc, &ascq, /*show_errors*/ 1);
5935
5936                         /*
5937                          * According to the SCSI-2 and SCSI-3 specs, a
5938                          * drive that is in the middle of a format should
5939                          * return NOT READY with an ASC of "logical unit
5940                          * not ready, format in progress".  The sense key
5941                          * specific bytes will then be a progress indicator.
5942                          */
5943                         if ((sense_key == SSD_KEY_NOT_READY)
5944                          && (asc == 0x04) && (ascq == 0x04)) {
5945                                 uint8_t sks[3];
5946
5947                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5948                                      ccb->csio.sense_resid, sks) == 0)
5949                                  && (quiet == 0)) {
5950                                         int val;
5951                                         u_int64_t percentage;
5952
5953                                         val = scsi_2btoul(&sks[1]);
5954                                         percentage = 10000 * val;
5955
5956                                         fprintf(stdout,
5957                                                 "\rFormatting:  %ju.%02u %% "
5958                                                 "(%d/%d) done",
5959                                                 (uintmax_t)(percentage /
5960                                                 (0x10000 * 100)),
5961                                                 (unsigned)((percentage /
5962                                                 0x10000) % 100),
5963                                                 val, 0x10000);
5964                                         fflush(stdout);
5965                                 } else if ((quiet == 0)
5966                                         && (++num_warnings <= 1)) {
5967                                         warnx("Unexpected SCSI Sense Key "
5968                                               "Specific value returned "
5969                                               "during format:");
5970                                         scsi_sense_print(device, &ccb->csio,
5971                                                          stderr);
5972                                         warnx("Unable to print status "
5973                                               "information, but format will "
5974                                               "proceed.");
5975                                         warnx("will exit when format is "
5976                                               "complete");
5977                                 }
5978                                 sleep(1);
5979                         } else {
5980                                 warnx("Unexpected SCSI error during format");
5981                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5982                                                 CAM_EPF_ALL, stderr);
5983                                 error = 1;
5984                                 goto scsiformat_bailout;
5985                         }
5986
5987                 } else if (status != CAM_REQ_CMP) {
5988                         warnx("Unexpected CAM status %#x", status);
5989                         if (arglist & CAM_ARG_VERBOSE)
5990                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5991                                                 CAM_EPF_ALL, stderr);
5992                         error = 1;
5993                         goto scsiformat_bailout;
5994                 }
5995
5996         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5997
5998         if (quiet == 0)
5999                 fprintf(stdout, "\nFormat Complete\n");
6000
6001 scsiformat_bailout:
6002
6003         cam_freeccb(ccb);
6004
6005         return(error);
6006 }
6007
6008 static int
6009 scsisanitize(struct cam_device *device, int argc, char **argv,
6010              char *combinedopt, int task_attr, int retry_count, int timeout)
6011 {
6012         union ccb *ccb;
6013         u_int8_t action = 0;
6014         int c;
6015         int ycount = 0, quiet = 0;
6016         int error = 0, retval = 0;
6017         int use_timeout = 10800 * 1000;
6018         int immediate = 1;
6019         int invert = 0;
6020         int passes = 0;
6021         int ause = 0;
6022         int fd = -1;
6023         const char *pattern = NULL;
6024         u_int8_t *data_ptr = NULL;
6025         u_int32_t dxfer_len = 0;
6026         u_int8_t byte2 = 0;
6027         int num_warnings = 0;
6028         int reportonly = 0;
6029
6030         ccb = cam_getccb(device);
6031
6032         if (ccb == NULL) {
6033                 warnx("scsisanitize: error allocating ccb");
6034                 return(1);
6035         }
6036
6037         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6038
6039         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6040                 switch(c) {
6041                 case 'a':
6042                         if (strcasecmp(optarg, "overwrite") == 0)
6043                                 action = SSZ_SERVICE_ACTION_OVERWRITE;
6044                         else if (strcasecmp(optarg, "block") == 0)
6045                                 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6046                         else if (strcasecmp(optarg, "crypto") == 0)
6047                                 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6048                         else if (strcasecmp(optarg, "exitfailure") == 0)
6049                                 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6050                         else {
6051                                 warnx("invalid service operation \"%s\"",
6052                                       optarg);
6053                                 error = 1;
6054                                 goto scsisanitize_bailout;
6055                         }
6056                         break;
6057                 case 'c':
6058                         passes = strtol(optarg, NULL, 0);
6059                         if (passes < 1 || passes > 31) {
6060                                 warnx("invalid passes value %d", passes);
6061                                 error = 1;
6062                                 goto scsisanitize_bailout;
6063                         }
6064                         break;
6065                 case 'I':
6066                         invert = 1;
6067                         break;
6068                 case 'P':
6069                         pattern = optarg;
6070                         break;
6071                 case 'q':
6072                         quiet++;
6073                         break;
6074                 case 'U':
6075                         ause = 1;
6076                         break;
6077                 case 'r':
6078                         reportonly = 1;
6079                         break;
6080                 case 'w':
6081                         immediate = 0;
6082                         break;
6083                 case 'y':
6084                         ycount++;
6085                         break;
6086                 }
6087         }
6088
6089         if (reportonly)
6090                 goto doreport;
6091
6092         if (action == 0) {
6093                 warnx("an action is required");
6094                 error = 1;
6095                 goto scsisanitize_bailout;
6096         } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6097                 struct scsi_sanitize_parameter_list *pl;
6098                 struct stat sb;
6099                 ssize_t sz, amt;
6100
6101                 if (pattern == NULL) {
6102                         warnx("overwrite action requires -P argument");
6103                         error = 1;
6104                         goto scsisanitize_bailout;
6105                 }
6106                 fd = open(pattern, O_RDONLY);
6107                 if (fd < 0) {
6108                         warn("cannot open pattern file %s", pattern);
6109                         error = 1;
6110                         goto scsisanitize_bailout;
6111                 }
6112                 if (fstat(fd, &sb) < 0) {
6113                         warn("cannot stat pattern file %s", pattern);
6114                         error = 1;
6115                         goto scsisanitize_bailout;
6116                 }
6117                 sz = sb.st_size;
6118                 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6119                         warnx("pattern file size exceeds maximum value %d",
6120                               SSZPL_MAX_PATTERN_LENGTH);
6121                         error = 1;
6122                         goto scsisanitize_bailout;
6123                 }
6124                 dxfer_len = sizeof(*pl) + sz;
6125                 data_ptr = calloc(1, dxfer_len);
6126                 if (data_ptr == NULL) {
6127                         warnx("cannot allocate parameter list buffer");
6128                         error = 1;
6129                         goto scsisanitize_bailout;
6130                 }
6131
6132                 amt = read(fd, data_ptr + sizeof(*pl), sz);
6133                 if (amt < 0) {
6134                         warn("cannot read pattern file");
6135                         error = 1;
6136                         goto scsisanitize_bailout;
6137                 } else if (amt != sz) {
6138                         warnx("short pattern file read");
6139                         error = 1;
6140                         goto scsisanitize_bailout;
6141                 }
6142
6143                 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6144                 if (passes == 0)
6145                         pl->byte1 = 1;
6146                 else
6147                         pl->byte1 = passes;
6148                 if (invert != 0)
6149                         pl->byte1 |= SSZPL_INVERT;
6150                 scsi_ulto2b(sz, pl->length);
6151         } else {
6152                 const char *arg;
6153
6154                 if (passes != 0)
6155                         arg = "-c";
6156                 else if (invert != 0)
6157                         arg = "-I";
6158                 else if (pattern != NULL)
6159                         arg = "-P";
6160                 else
6161                         arg = NULL;
6162                 if (arg != NULL) {
6163                         warnx("%s argument only valid with overwrite "
6164                               "operation", arg);
6165                         error = 1;
6166                         goto scsisanitize_bailout;
6167                 }
6168         }
6169
6170         if (quiet == 0) {
6171                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6172                         "following device:\n");
6173
6174                 error = scsidoinquiry(device, argc, argv, combinedopt,
6175                                       task_attr, retry_count, timeout);
6176
6177                 if (error != 0) {
6178                         warnx("scsisanitize: error sending inquiry");
6179                         goto scsisanitize_bailout;
6180                 }
6181         }
6182
6183         if (ycount == 0) {
6184                 if (!get_confirmation()) {
6185                         error = 1;
6186                         goto scsisanitize_bailout;
6187                 }
6188         }
6189
6190         if (timeout != 0)
6191                 use_timeout = timeout;
6192
6193         if (quiet == 0) {
6194                 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6195                         use_timeout / 1000);
6196         }
6197
6198         /*
6199          * If the user hasn't disabled questions and didn't specify a
6200          * timeout on the command line, ask them if they want the current
6201          * timeout.
6202          */
6203         if ((ycount == 0)
6204          && (timeout == 0)) {
6205                 char str[1024];
6206                 int new_timeout = 0;
6207
6208                 fprintf(stdout, "Enter new timeout in seconds or press\n"
6209                         "return to keep the current timeout [%d] ",
6210                         use_timeout / 1000);
6211
6212                 if (fgets(str, sizeof(str), stdin) != NULL) {
6213                         if (str[0] != '\0')
6214                                 new_timeout = atoi(str);
6215                 }
6216
6217                 if (new_timeout != 0) {
6218                         use_timeout = new_timeout * 1000;
6219                         fprintf(stdout, "Using new timeout value %d\n",
6220                                 use_timeout / 1000);
6221                 }
6222         }
6223
6224         byte2 = action;
6225         if (ause != 0)
6226                 byte2 |= SSZ_UNRESTRICTED_EXIT;
6227         if (immediate != 0)
6228                 byte2 |= SSZ_IMMED;
6229
6230         scsi_sanitize(&ccb->csio,
6231                       /* retries */ retry_count,
6232                       /* cbfcnp */ NULL,
6233                       /* tag_action */ task_attr,
6234                       /* byte2 */ byte2,
6235                       /* control */ 0,
6236                       /* data_ptr */ data_ptr,
6237                       /* dxfer_len */ dxfer_len,
6238                       /* sense_len */ SSD_FULL_SIZE,
6239                       /* timeout */ use_timeout);
6240
6241         /* Disable freezing the device queue */
6242         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6243
6244         if (arglist & CAM_ARG_ERR_RECOVER)
6245                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6246
6247         if (cam_send_ccb(device, ccb) < 0) {
6248                 warn("error sending sanitize command");
6249                 error = 1;
6250                 goto scsisanitize_bailout;
6251         }
6252
6253         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6254                 struct scsi_sense_data *sense;
6255                 int error_code, sense_key, asc, ascq;
6256
6257                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6258                     CAM_SCSI_STATUS_ERROR) {
6259                         sense = &ccb->csio.sense_data;
6260                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6261                             ccb->csio.sense_resid, &error_code, &sense_key,
6262                             &asc, &ascq, /*show_errors*/ 1);
6263
6264                         if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6265                             asc == 0x20 && ascq == 0x00)
6266                                 warnx("sanitize is not supported by "
6267                                       "this device");
6268                         else
6269                                 warnx("error sanitizing this device");
6270                 } else
6271                         warnx("error sanitizing this device");
6272
6273                 if (arglist & CAM_ARG_VERBOSE) {
6274                         cam_error_print(device, ccb, CAM_ESF_ALL,
6275                                         CAM_EPF_ALL, stderr);
6276                 }
6277                 error = 1;
6278                 goto scsisanitize_bailout;
6279         }
6280
6281         /*
6282          * If we ran in non-immediate mode, we already checked for errors
6283          * above and printed out any necessary information.  If we're in
6284          * immediate mode, we need to loop through and get status
6285          * information periodically.
6286          */
6287         if (immediate == 0) {
6288                 if (quiet == 0) {
6289                         fprintf(stdout, "Sanitize Complete\n");
6290                 }
6291                 goto scsisanitize_bailout;
6292         }
6293
6294 doreport:
6295         do {
6296                 cam_status status;
6297
6298                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6299
6300                 /*
6301                  * There's really no need to do error recovery or
6302                  * retries here, since we're just going to sit in a
6303                  * loop and wait for the device to finish sanitizing.
6304                  */
6305                 scsi_test_unit_ready(&ccb->csio,
6306                                      /* retries */ 0,
6307                                      /* cbfcnp */ NULL,
6308                                      /* tag_action */ task_attr,
6309                                      /* sense_len */ SSD_FULL_SIZE,
6310                                      /* timeout */ 5000);
6311
6312                 /* Disable freezing the device queue */
6313                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6314
6315                 retval = cam_send_ccb(device, ccb);
6316
6317                 /*
6318                  * If we get an error from the ioctl, bail out.  SCSI
6319                  * errors are expected.
6320                  */
6321                 if (retval < 0) {
6322                         warn("error sending CAMIOCOMMAND ioctl");
6323                         if (arglist & CAM_ARG_VERBOSE) {
6324                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6325                                                 CAM_EPF_ALL, stderr);
6326                         }
6327                         error = 1;
6328                         goto scsisanitize_bailout;
6329                 }
6330
6331                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6332
6333                 if ((status != CAM_REQ_CMP)
6334                  && (status == CAM_SCSI_STATUS_ERROR)
6335                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6336                         struct scsi_sense_data *sense;
6337                         int error_code, sense_key, asc, ascq;
6338
6339                         sense = &ccb->csio.sense_data;
6340                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6341                             ccb->csio.sense_resid, &error_code, &sense_key,
6342                             &asc, &ascq, /*show_errors*/ 1);
6343
6344                         /*
6345                          * According to the SCSI-3 spec, a drive that is in the
6346                          * middle of a sanitize should return NOT READY with an
6347                          * ASC of "logical unit not ready, sanitize in
6348                          * progress". The sense key specific bytes will then
6349                          * be a progress indicator.
6350                          */
6351                         if ((sense_key == SSD_KEY_NOT_READY)
6352                          && (asc == 0x04) && (ascq == 0x1b)) {
6353                                 uint8_t sks[3];
6354
6355                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6356                                      ccb->csio.sense_resid, sks) == 0)
6357                                  && (quiet == 0)) {
6358                                         int val;
6359                                         u_int64_t percentage;
6360
6361                                         val = scsi_2btoul(&sks[1]);
6362                                         percentage = 10000 * val;
6363
6364                                         fprintf(stdout,
6365                                                 "\rSanitizing:  %ju.%02u %% "
6366                                                 "(%d/%d) done",
6367                                                 (uintmax_t)(percentage /
6368                                                 (0x10000 * 100)),
6369                                                 (unsigned)((percentage /
6370                                                 0x10000) % 100),
6371                                                 val, 0x10000);
6372                                         fflush(stdout);
6373                                 } else if ((quiet == 0)
6374                                         && (++num_warnings <= 1)) {
6375                                         warnx("Unexpected SCSI Sense Key "
6376                                               "Specific value returned "
6377                                               "during sanitize:");
6378                                         scsi_sense_print(device, &ccb->csio,
6379                                                          stderr);
6380                                         warnx("Unable to print status "
6381                                               "information, but sanitze will "
6382                                               "proceed.");
6383                                         warnx("will exit when sanitize is "
6384                                               "complete");
6385                                 }
6386                                 sleep(1);
6387                         } else {
6388                                 warnx("Unexpected SCSI error during sanitize");
6389                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6390                                                 CAM_EPF_ALL, stderr);
6391                                 error = 1;
6392                                 goto scsisanitize_bailout;
6393                         }
6394
6395                 } else if (status != CAM_REQ_CMP) {
6396                         warnx("Unexpected CAM status %#x", status);
6397                         if (arglist & CAM_ARG_VERBOSE)
6398                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6399                                                 CAM_EPF_ALL, stderr);
6400                         error = 1;
6401                         goto scsisanitize_bailout;
6402                 }
6403         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6404
6405         if (quiet == 0)
6406                 fprintf(stdout, "\nSanitize Complete\n");
6407
6408 scsisanitize_bailout:
6409         if (fd >= 0)
6410                 close(fd);
6411         if (data_ptr != NULL)
6412                 free(data_ptr);
6413         cam_freeccb(ccb);
6414
6415         return(error);
6416 }
6417
6418 static int
6419 scsireportluns(struct cam_device *device, int argc, char **argv,
6420                char *combinedopt, int task_attr, int retry_count, int timeout)
6421 {
6422         union ccb *ccb;
6423         int c, countonly, lunsonly;
6424         struct scsi_report_luns_data *lundata;
6425         int alloc_len;
6426         uint8_t report_type;
6427         uint32_t list_len, i, j;
6428         int retval;
6429
6430         retval = 0;
6431         lundata = NULL;
6432         report_type = RPL_REPORT_DEFAULT;
6433         ccb = cam_getccb(device);
6434
6435         if (ccb == NULL) {
6436                 warnx("%s: error allocating ccb", __func__);
6437                 return (1);
6438         }
6439
6440         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6441
6442         countonly = 0;
6443         lunsonly = 0;
6444
6445         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6446                 switch (c) {
6447                 case 'c':
6448                         countonly++;
6449                         break;
6450                 case 'l':
6451                         lunsonly++;
6452                         break;
6453                 case 'r':
6454                         if (strcasecmp(optarg, "default") == 0)
6455                                 report_type = RPL_REPORT_DEFAULT;
6456                         else if (strcasecmp(optarg, "wellknown") == 0)
6457                                 report_type = RPL_REPORT_WELLKNOWN;
6458                         else if (strcasecmp(optarg, "all") == 0)
6459                                 report_type = RPL_REPORT_ALL;
6460                         else {
6461                                 warnx("%s: invalid report type \"%s\"",
6462                                       __func__, optarg);
6463                                 retval = 1;
6464                                 goto bailout;
6465                         }
6466                         break;
6467                 default:
6468                         break;
6469                 }
6470         }
6471
6472         if ((countonly != 0)
6473          && (lunsonly != 0)) {
6474                 warnx("%s: you can only specify one of -c or -l", __func__);
6475                 retval = 1;
6476                 goto bailout;
6477         }
6478         /*
6479          * According to SPC-4, the allocation length must be at least 16
6480          * bytes -- enough for the header and one LUN.
6481          */
6482         alloc_len = sizeof(*lundata) + 8;
6483
6484 retry:
6485
6486         lundata = malloc(alloc_len);
6487
6488         if (lundata == NULL) {
6489                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6490                 retval = 1;
6491                 goto bailout;
6492         }
6493
6494         scsi_report_luns(&ccb->csio,
6495                          /*retries*/ retry_count,
6496                          /*cbfcnp*/ NULL,
6497                          /*tag_action*/ task_attr,
6498                          /*select_report*/ report_type,
6499                          /*rpl_buf*/ lundata,
6500                          /*alloc_len*/ alloc_len,
6501                          /*sense_len*/ SSD_FULL_SIZE,
6502                          /*timeout*/ timeout ? timeout : 5000);
6503
6504         /* Disable freezing the device queue */
6505         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6506
6507         if (arglist & CAM_ARG_ERR_RECOVER)
6508                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6509
6510         if (cam_send_ccb(device, ccb) < 0) {
6511                 warn("error sending REPORT LUNS command");
6512
6513                 if (arglist & CAM_ARG_VERBOSE)
6514                         cam_error_print(device, ccb, CAM_ESF_ALL,
6515                                         CAM_EPF_ALL, stderr);
6516
6517                 retval = 1;
6518                 goto bailout;
6519         }
6520
6521         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6522                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6523                 retval = 1;
6524                 goto bailout;
6525         }
6526
6527
6528         list_len = scsi_4btoul(lundata->length);
6529
6530         /*
6531          * If we need to list the LUNs, and our allocation
6532          * length was too short, reallocate and retry.
6533          */
6534         if ((countonly == 0)
6535          && (list_len > (alloc_len - sizeof(*lundata)))) {
6536                 alloc_len = list_len + sizeof(*lundata);
6537                 free(lundata);
6538                 goto retry;
6539         }
6540
6541         if (lunsonly == 0)
6542                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6543                         ((list_len / 8) > 1) ? "s" : "");
6544
6545         if (countonly != 0)
6546                 goto bailout;
6547
6548         for (i = 0; i < (list_len / 8); i++) {
6549                 int no_more;
6550
6551                 no_more = 0;
6552                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6553                         if (j != 0)
6554                                 fprintf(stdout, ",");
6555                         switch (lundata->luns[i].lundata[j] &
6556                                 RPL_LUNDATA_ATYP_MASK) {
6557                         case RPL_LUNDATA_ATYP_PERIPH:
6558                                 if ((lundata->luns[i].lundata[j] &
6559                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6560                                         fprintf(stdout, "%d:",
6561                                                 lundata->luns[i].lundata[j] &
6562                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
6563                                 else if ((j == 0)
6564                                       && ((lundata->luns[i].lundata[j+2] &
6565                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6566                                         no_more = 1;
6567
6568                                 fprintf(stdout, "%d",
6569                                         lundata->luns[i].lundata[j+1]);
6570                                 break;
6571                         case RPL_LUNDATA_ATYP_FLAT: {
6572                                 uint8_t tmplun[2];
6573                                 tmplun[0] = lundata->luns[i].lundata[j] &
6574                                         RPL_LUNDATA_FLAT_LUN_MASK;
6575                                 tmplun[1] = lundata->luns[i].lundata[j+1];
6576
6577                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6578                                 no_more = 1;
6579                                 break;
6580                         }
6581                         case RPL_LUNDATA_ATYP_LUN:
6582                                 fprintf(stdout, "%d:%d:%d",
6583                                         (lundata->luns[i].lundata[j+1] &
6584                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6585                                         lundata->luns[i].lundata[j] &
6586                                         RPL_LUNDATA_LUN_TARG_MASK,
6587                                         lundata->luns[i].lundata[j+1] &
6588                                         RPL_LUNDATA_LUN_LUN_MASK);
6589                                 break;
6590                         case RPL_LUNDATA_ATYP_EXTLUN: {
6591                                 int field_len_code, eam_code;
6592
6593                                 eam_code = lundata->luns[i].lundata[j] &
6594                                         RPL_LUNDATA_EXT_EAM_MASK;
6595                                 field_len_code = (lundata->luns[i].lundata[j] &
6596                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6597
6598                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6599                                  && (field_len_code == 0x00)) {
6600                                         fprintf(stdout, "%d",
6601                                                 lundata->luns[i].lundata[j+1]);
6602                                 } else if ((eam_code ==
6603                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6604                                         && (field_len_code == 0x03)) {
6605                                         uint8_t tmp_lun[8];
6606
6607                                         /*
6608                                          * This format takes up all 8 bytes.
6609                                          * If we aren't starting at offset 0,
6610                                          * that's a bug.
6611                                          */
6612                                         if (j != 0) {
6613                                                 fprintf(stdout, "Invalid "
6614                                                         "offset %d for "
6615                                                         "Extended LUN not "
6616                                                         "specified format", j);
6617                                                 no_more = 1;
6618                                                 break;
6619                                         }
6620                                         bzero(tmp_lun, sizeof(tmp_lun));
6621                                         bcopy(&lundata->luns[i].lundata[j+1],
6622                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
6623                                         fprintf(stdout, "%#jx",
6624                                                (intmax_t)scsi_8btou64(tmp_lun));
6625                                         no_more = 1;
6626                                 } else {
6627                                         fprintf(stderr, "Unknown Extended LUN"
6628                                                 "Address method %#x, length "
6629                                                 "code %#x", eam_code,
6630                                                 field_len_code);
6631                                         no_more = 1;
6632                                 }
6633                                 break;
6634                         }
6635                         default:
6636                                 fprintf(stderr, "Unknown LUN address method "
6637                                         "%#x\n", lundata->luns[i].lundata[0] &
6638                                         RPL_LUNDATA_ATYP_MASK);
6639                                 break;
6640                         }
6641                         /*
6642                          * For the flat addressing method, there are no
6643                          * other levels after it.
6644                          */
6645                         if (no_more != 0)
6646                                 break;
6647                 }
6648                 fprintf(stdout, "\n");
6649         }
6650
6651 bailout:
6652
6653         cam_freeccb(ccb);
6654
6655         free(lundata);
6656
6657         return (retval);
6658 }
6659
6660 static int
6661 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6662                  char *combinedopt, int task_attr, int retry_count, int timeout)
6663 {
6664         union ccb *ccb;
6665         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6666         struct scsi_read_capacity_data rcap;
6667         struct scsi_read_capacity_data_long rcaplong;
6668         uint64_t maxsector;
6669         uint32_t block_len;
6670         int retval;
6671         int c;
6672
6673         blocksizeonly = 0;
6674         humanize = 0;
6675         numblocks = 0;
6676         quiet = 0;
6677         sizeonly = 0;
6678         baseten = 0;
6679         retval = 0;
6680
6681         ccb = cam_getccb(device);
6682
6683         if (ccb == NULL) {
6684                 warnx("%s: error allocating ccb", __func__);
6685                 return (1);
6686         }
6687
6688         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6689
6690         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6691                 switch (c) {
6692                 case 'b':
6693                         blocksizeonly++;
6694                         break;
6695                 case 'h':
6696                         humanize++;
6697                         baseten = 0;
6698                         break;
6699                 case 'H':
6700                         humanize++;
6701                         baseten++;
6702                         break;
6703                 case 'N':
6704                         numblocks++;
6705                         break;
6706                 case 'q':
6707                         quiet++;
6708                         break;
6709                 case 's':
6710                         sizeonly++;
6711                         break;
6712                 default:
6713                         break;
6714                 }
6715         }
6716
6717         if ((blocksizeonly != 0)
6718          && (numblocks != 0)) {
6719                 warnx("%s: you can only specify one of -b or -N", __func__);
6720                 retval = 1;
6721                 goto bailout;
6722         }
6723
6724         if ((blocksizeonly != 0)
6725          && (sizeonly != 0)) {
6726                 warnx("%s: you can only specify one of -b or -s", __func__);
6727                 retval = 1;
6728                 goto bailout;
6729         }
6730
6731         if ((humanize != 0)
6732          && (quiet != 0)) {
6733                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6734                 retval = 1;
6735                 goto bailout;
6736         }
6737
6738         if ((humanize != 0)
6739          && (blocksizeonly != 0)) {
6740                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6741                 retval = 1;
6742                 goto bailout;
6743         }
6744
6745         scsi_read_capacity(&ccb->csio,
6746                            /*retries*/ retry_count,
6747                            /*cbfcnp*/ NULL,
6748                            /*tag_action*/ task_attr,
6749                            &rcap,
6750                            SSD_FULL_SIZE,
6751                            /*timeout*/ timeout ? timeout : 5000);
6752
6753         /* Disable freezing the device queue */
6754         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6755
6756         if (arglist & CAM_ARG_ERR_RECOVER)
6757                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6758
6759         if (cam_send_ccb(device, ccb) < 0) {
6760                 warn("error sending READ CAPACITY command");
6761
6762                 if (arglist & CAM_ARG_VERBOSE)
6763                         cam_error_print(device, ccb, CAM_ESF_ALL,
6764                                         CAM_EPF_ALL, stderr);
6765
6766                 retval = 1;
6767                 goto bailout;
6768         }
6769
6770         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6771                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6772                 retval = 1;
6773                 goto bailout;
6774         }
6775
6776         maxsector = scsi_4btoul(rcap.addr);
6777         block_len = scsi_4btoul(rcap.length);
6778
6779         /*
6780          * A last block of 2^32-1 means that the true capacity is over 2TB,
6781          * and we need to issue the long READ CAPACITY to get the real
6782          * capacity.  Otherwise, we're all set.
6783          */
6784         if (maxsector != 0xffffffff)
6785                 goto do_print;
6786
6787         scsi_read_capacity_16(&ccb->csio,
6788                               /*retries*/ retry_count,
6789                               /*cbfcnp*/ NULL,
6790                               /*tag_action*/ task_attr,
6791                               /*lba*/ 0,
6792                               /*reladdr*/ 0,
6793                               /*pmi*/ 0,
6794                               /*rcap_buf*/ (uint8_t *)&rcaplong,
6795                               /*rcap_buf_len*/ sizeof(rcaplong),
6796                               /*sense_len*/ SSD_FULL_SIZE,
6797                               /*timeout*/ timeout ? timeout : 5000);
6798
6799         /* Disable freezing the device queue */
6800         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6801
6802         if (arglist & CAM_ARG_ERR_RECOVER)
6803                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6804
6805         if (cam_send_ccb(device, ccb) < 0) {
6806                 warn("error sending READ CAPACITY (16) command");
6807
6808                 if (arglist & CAM_ARG_VERBOSE)
6809                         cam_error_print(device, ccb, CAM_ESF_ALL,
6810                                         CAM_EPF_ALL, stderr);
6811
6812                 retval = 1;
6813                 goto bailout;
6814         }
6815
6816         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6817                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6818                 retval = 1;
6819                 goto bailout;
6820         }
6821
6822         maxsector = scsi_8btou64(rcaplong.addr);
6823         block_len = scsi_4btoul(rcaplong.length);
6824
6825 do_print:
6826         if (blocksizeonly == 0) {
6827                 /*
6828                  * Humanize implies !quiet, and also implies numblocks.
6829                  */
6830                 if (humanize != 0) {
6831                         char tmpstr[6];
6832                         int64_t tmpbytes;
6833                         int ret;
6834
6835                         tmpbytes = (maxsector + 1) * block_len;
6836                         ret = humanize_number(tmpstr, sizeof(tmpstr),
6837                                               tmpbytes, "", HN_AUTOSCALE,
6838                                               HN_B | HN_DECIMAL |
6839                                               ((baseten != 0) ?
6840                                               HN_DIVISOR_1000 : 0));
6841                         if (ret == -1) {
6842                                 warnx("%s: humanize_number failed!", __func__);
6843                                 retval = 1;
6844                                 goto bailout;
6845                         }
6846                         fprintf(stdout, "Device Size: %s%s", tmpstr,
6847                                 (sizeonly == 0) ?  ", " : "\n");
6848                 } else if (numblocks != 0) {
6849                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6850                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
6851                                 (sizeonly == 0) ? ", " : "\n");
6852                 } else {
6853                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6854                                 "Last Block: " : "", (uintmax_t)maxsector,
6855                                 (sizeonly == 0) ? ", " : "\n");
6856                 }
6857         }
6858         if (sizeonly == 0)
6859                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6860                         "Block Length: " : "", block_len, (quiet == 0) ?
6861                         " bytes" : "");
6862 bailout:
6863         cam_freeccb(ccb);
6864
6865         return (retval);
6866 }
6867
6868 static int
6869 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6870        int retry_count, int timeout)
6871 {
6872         int c, error = 0;
6873         union ccb *ccb;
6874         uint8_t *smp_request = NULL, *smp_response = NULL;
6875         int request_size = 0, response_size = 0;
6876         int fd_request = 0, fd_response = 0;
6877         char *datastr = NULL;
6878         struct get_hook hook;
6879         int retval;
6880         int flags = 0;
6881
6882         /*
6883          * Note that at the moment we don't support sending SMP CCBs to
6884          * devices that aren't probed by CAM.
6885          */
6886         ccb = cam_getccb(device);
6887         if (ccb == NULL) {
6888                 warnx("%s: error allocating CCB", __func__);
6889                 return (1);
6890         }
6891
6892         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
6893
6894         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6895                 switch (c) {
6896                 case 'R':
6897                         arglist |= CAM_ARG_CMD_IN;
6898                         response_size = strtol(optarg, NULL, 0);
6899                         if (response_size <= 0) {
6900                                 warnx("invalid number of response bytes %d",
6901                                       response_size);
6902                                 error = 1;
6903                                 goto smpcmd_bailout;
6904                         }
6905                         hook.argc = argc - optind;
6906                         hook.argv = argv + optind;
6907                         hook.got = 0;
6908                         optind++;
6909                         datastr = cget(&hook, NULL);
6910                         /*
6911                          * If the user supplied "-" instead of a format, he
6912                          * wants the data to be written to stdout.
6913                          */
6914                         if ((datastr != NULL)
6915                          && (datastr[0] == '-'))
6916                                 fd_response = 1;
6917
6918                         smp_response = (u_int8_t *)malloc(response_size);
6919                         if (smp_response == NULL) {
6920                                 warn("can't malloc memory for SMP response");
6921                                 error = 1;
6922                                 goto smpcmd_bailout;
6923                         }
6924                         break;
6925                 case 'r':
6926                         arglist |= CAM_ARG_CMD_OUT;
6927                         request_size = strtol(optarg, NULL, 0);
6928                         if (request_size <= 0) {
6929                                 warnx("invalid number of request bytes %d",
6930                                       request_size);
6931                                 error = 1;
6932                                 goto smpcmd_bailout;
6933                         }
6934                         hook.argc = argc - optind;
6935                         hook.argv = argv + optind;
6936                         hook.got = 0;
6937                         datastr = cget(&hook, NULL);
6938                         smp_request = (u_int8_t *)malloc(request_size);
6939                         if (smp_request == NULL) {
6940                                 warn("can't malloc memory for SMP request");
6941                                 error = 1;
6942                                 goto smpcmd_bailout;
6943                         }
6944                         bzero(smp_request, request_size);
6945                         /*
6946                          * If the user supplied "-" instead of a format, he
6947                          * wants the data to be read from stdin.
6948                          */
6949                         if ((datastr != NULL)
6950                          && (datastr[0] == '-'))
6951                                 fd_request = 1;
6952                         else
6953                                 buff_encode_visit(smp_request, request_size,
6954                                                   datastr,
6955                                                   iget, &hook);
6956                         optind += hook.got;
6957                         break;
6958                 default:
6959                         break;
6960                 }
6961         }
6962
6963         /*
6964          * If fd_data is set, and we're writing to the device, we need to
6965          * read the data the user wants written from stdin.
6966          */
6967         if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6968                 ssize_t amt_read;
6969                 int amt_to_read = request_size;
6970                 u_int8_t *buf_ptr = smp_request;
6971
6972                 for (amt_read = 0; amt_to_read > 0;
6973                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6974                         if (amt_read == -1) {
6975                                 warn("error reading data from stdin");
6976                                 error = 1;
6977                                 goto smpcmd_bailout;
6978                         }
6979                         amt_to_read -= amt_read;
6980                         buf_ptr += amt_read;
6981                 }
6982         }
6983
6984         if (((arglist & CAM_ARG_CMD_IN) == 0)
6985          || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6986                 warnx("%s: need both the request (-r) and response (-R) "
6987                       "arguments", __func__);
6988                 error = 1;
6989                 goto smpcmd_bailout;
6990         }
6991
6992         flags |= CAM_DEV_QFRZDIS;
6993
6994         cam_fill_smpio(&ccb->smpio,
6995                        /*retries*/ retry_count,
6996                        /*cbfcnp*/ NULL,
6997                        /*flags*/ flags,
6998                        /*smp_request*/ smp_request,
6999                        /*smp_request_len*/ request_size,
7000                        /*smp_response*/ smp_response,
7001                        /*smp_response_len*/ response_size,
7002                        /*timeout*/ timeout ? timeout : 5000);
7003
7004         ccb->smpio.flags = SMP_FLAG_NONE;
7005
7006         if (((retval = cam_send_ccb(device, ccb)) < 0)
7007          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7008                 const char warnstr[] = "error sending command";
7009
7010                 if (retval < 0)
7011                         warn(warnstr);
7012                 else
7013                         warnx(warnstr);
7014
7015                 if (arglist & CAM_ARG_VERBOSE) {
7016                         cam_error_print(device, ccb, CAM_ESF_ALL,
7017                                         CAM_EPF_ALL, stderr);
7018                 }
7019         }
7020
7021         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
7022          && (response_size > 0)) {
7023                 if (fd_response == 0) {
7024                         buff_decode_visit(smp_response, response_size,
7025                                           datastr, arg_put, NULL);
7026                         fprintf(stdout, "\n");
7027                 } else {
7028                         ssize_t amt_written;
7029                         int amt_to_write = response_size;
7030                         u_int8_t *buf_ptr = smp_response;
7031
7032                         for (amt_written = 0; (amt_to_write > 0) &&
7033                              (amt_written = write(STDOUT_FILENO, buf_ptr,
7034                                                   amt_to_write)) > 0;){
7035                                 amt_to_write -= amt_written;
7036                                 buf_ptr += amt_written;
7037                         }
7038                         if (amt_written == -1) {
7039                                 warn("error writing data to stdout");
7040                                 error = 1;
7041                                 goto smpcmd_bailout;
7042                         } else if ((amt_written == 0)
7043                                 && (amt_to_write > 0)) {
7044                                 warnx("only wrote %u bytes out of %u",
7045                                       response_size - amt_to_write, 
7046                                       response_size);
7047                         }
7048                 }
7049         }
7050 smpcmd_bailout:
7051         if (ccb != NULL)
7052                 cam_freeccb(ccb);
7053
7054         if (smp_request != NULL)
7055                 free(smp_request);
7056
7057         if (smp_response != NULL)
7058                 free(smp_response);
7059
7060         return (error);
7061 }
7062
7063 static int
7064 smpreportgeneral(struct cam_device *device, int argc, char **argv,
7065                  char *combinedopt, int retry_count, int timeout)
7066 {
7067         union ccb *ccb;
7068         struct smp_report_general_request *request = NULL;
7069         struct smp_report_general_response *response = NULL;
7070         struct sbuf *sb = NULL;
7071         int error = 0;
7072         int c, long_response = 0;
7073         int retval;
7074
7075         /*
7076          * Note that at the moment we don't support sending SMP CCBs to
7077          * devices that aren't probed by CAM.
7078          */
7079         ccb = cam_getccb(device);
7080         if (ccb == NULL) {
7081                 warnx("%s: error allocating CCB", __func__);
7082                 return (1);
7083         }
7084
7085         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7086
7087         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7088                 switch (c) {
7089                 case 'l':
7090                         long_response = 1;
7091                         break;
7092                 default:
7093                         break;
7094                 }
7095         }
7096         request = malloc(sizeof(*request));
7097         if (request == NULL) {
7098                 warn("%s: unable to allocate %zd bytes", __func__,
7099                      sizeof(*request));
7100                 error = 1;
7101                 goto bailout;
7102         }
7103
7104         response = malloc(sizeof(*response));
7105         if (response == NULL) {
7106                 warn("%s: unable to allocate %zd bytes", __func__,
7107                      sizeof(*response));
7108                 error = 1;
7109                 goto bailout;
7110         }
7111
7112 try_long:
7113         smp_report_general(&ccb->smpio,
7114                            retry_count,
7115                            /*cbfcnp*/ NULL,
7116                            request,
7117                            /*request_len*/ sizeof(*request),
7118                            (uint8_t *)response,
7119                            /*response_len*/ sizeof(*response),
7120                            /*long_response*/ long_response,
7121                            timeout);
7122
7123         if (((retval = cam_send_ccb(device, ccb)) < 0)
7124          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7125                 const char warnstr[] = "error sending command";
7126
7127                 if (retval < 0)
7128                         warn(warnstr);
7129                 else
7130                         warnx(warnstr);
7131
7132                 if (arglist & CAM_ARG_VERBOSE) {
7133                         cam_error_print(device, ccb, CAM_ESF_ALL,
7134                                         CAM_EPF_ALL, stderr);
7135                 }
7136                 error = 1;
7137                 goto bailout;
7138         }
7139
7140         /*
7141          * If the device supports the long response bit, try again and see
7142          * if we can get all of the data.
7143          */
7144         if ((response->long_response & SMP_RG_LONG_RESPONSE)
7145          && (long_response == 0)) {
7146                 ccb->ccb_h.status = CAM_REQ_INPROG;
7147                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7148                 long_response = 1;
7149                 goto try_long;
7150         }
7151
7152         /*
7153          * XXX KDM detect and decode SMP errors here.
7154          */
7155         sb = sbuf_new_auto();
7156         if (sb == NULL) {
7157                 warnx("%s: error allocating sbuf", __func__);
7158                 goto bailout;
7159         }
7160
7161         smp_report_general_sbuf(response, sizeof(*response), sb);
7162
7163         if (sbuf_finish(sb) != 0) {
7164                 warnx("%s: sbuf_finish", __func__);
7165                 goto bailout;
7166         }
7167
7168         printf("%s", sbuf_data(sb));
7169
7170 bailout:
7171         if (ccb != NULL)
7172                 cam_freeccb(ccb);
7173
7174         if (request != NULL)
7175                 free(request);
7176
7177         if (response != NULL)
7178                 free(response);
7179
7180         if (sb != NULL)
7181                 sbuf_delete(sb);
7182
7183         return (error);
7184 }
7185
7186 static struct camcontrol_opts phy_ops[] = {
7187         {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7188         {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7189         {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7190         {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7191         {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7192         {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7193         {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7194         {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7195         {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7196         {NULL, 0, 0, NULL}
7197 };
7198
7199 static int
7200 smpphycontrol(struct cam_device *device, int argc, char **argv,
7201               char *combinedopt, int retry_count, int timeout)
7202 {
7203         union ccb *ccb;
7204         struct smp_phy_control_request *request = NULL;
7205         struct smp_phy_control_response *response = NULL;
7206         int long_response = 0;
7207         int retval = 0;
7208         int phy = -1;
7209         uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7210         int phy_op_set = 0;
7211         uint64_t attached_dev_name = 0;
7212         int dev_name_set = 0;
7213         uint32_t min_plr = 0, max_plr = 0;
7214         uint32_t pp_timeout_val = 0;
7215         int slumber_partial = 0;
7216         int set_pp_timeout_val = 0;
7217         int c;
7218
7219         /*
7220          * Note that at the moment we don't support sending SMP CCBs to
7221          * devices that aren't probed by CAM.
7222          */
7223         ccb = cam_getccb(device);
7224         if (ccb == NULL) {
7225                 warnx("%s: error allocating CCB", __func__);
7226                 return (1);
7227         }
7228
7229         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7230
7231         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7232                 switch (c) {
7233                 case 'a':
7234                 case 'A':
7235                 case 's':
7236                 case 'S': {
7237                         int enable = -1;
7238
7239                         if (strcasecmp(optarg, "enable") == 0)
7240                                 enable = 1;
7241                         else if (strcasecmp(optarg, "disable") == 0)
7242                                 enable = 2;
7243                         else {
7244                                 warnx("%s: Invalid argument %s", __func__,
7245                                       optarg);
7246                                 retval = 1;
7247                                 goto bailout;
7248                         }
7249                         switch (c) {
7250                         case 's':
7251                                 slumber_partial |= enable <<
7252                                                    SMP_PC_SAS_SLUMBER_SHIFT;
7253                                 break;
7254                         case 'S':
7255                                 slumber_partial |= enable <<
7256                                                    SMP_PC_SAS_PARTIAL_SHIFT;
7257                                 break;
7258                         case 'a':
7259                                 slumber_partial |= enable <<
7260                                                    SMP_PC_SATA_SLUMBER_SHIFT;
7261                                 break;
7262                         case 'A':
7263                                 slumber_partial |= enable <<
7264                                                    SMP_PC_SATA_PARTIAL_SHIFT;
7265                                 break;
7266                         default:
7267                                 warnx("%s: programmer error", __func__);
7268                                 retval = 1;
7269                                 goto bailout;
7270                                 break; /*NOTREACHED*/
7271                         }
7272                         break;
7273                 }
7274                 case 'd':
7275                         attached_dev_name = (uintmax_t)strtoumax(optarg,
7276                                                                  NULL,0);
7277                         dev_name_set = 1;
7278                         break;
7279                 case 'l':
7280                         long_response = 1;
7281                         break;
7282                 case 'm':
7283                         /*
7284                          * We don't do extensive checking here, so this
7285                          * will continue to work when new speeds come out.
7286                          */
7287                         min_plr = strtoul(optarg, NULL, 0);
7288                         if ((min_plr == 0)
7289                          || (min_plr > 0xf)) {
7290                                 warnx("%s: invalid link rate %x",
7291                                       __func__, min_plr);
7292                                 retval = 1;
7293                                 goto bailout;
7294                         }
7295                         break;
7296                 case 'M':
7297                         /*
7298                          * We don't do extensive checking here, so this
7299                          * will continue to work when new speeds come out.
7300                          */
7301                         max_plr = strtoul(optarg, NULL, 0);
7302                         if ((max_plr == 0)
7303                          || (max_plr > 0xf)) {
7304                                 warnx("%s: invalid link rate %x",
7305                                       __func__, max_plr);
7306                                 retval = 1;
7307                                 goto bailout;
7308                         }
7309                         break;
7310                 case 'o': {
7311                         camcontrol_optret optreturn;
7312                         cam_argmask argnums;
7313                         const char *subopt;
7314
7315                         if (phy_op_set != 0) {
7316                                 warnx("%s: only one phy operation argument "
7317                                       "(-o) allowed", __func__);
7318                                 retval = 1;
7319                                 goto bailout;
7320                         }
7321
7322                         phy_op_set = 1;
7323
7324                         /*
7325                          * Allow the user to specify the phy operation
7326                          * numerically, as well as with a name.  This will
7327                          * future-proof it a bit, so options that are added
7328                          * in future specs can be used.
7329                          */
7330                         if (isdigit(optarg[0])) {
7331                                 phy_operation = strtoul(optarg, NULL, 0);
7332                                 if ((phy_operation == 0)
7333                                  || (phy_operation > 0xff)) {
7334                                         warnx("%s: invalid phy operation %#x",
7335                                               __func__, phy_operation);
7336                                         retval = 1;
7337                                         goto bailout;
7338                                 }
7339                                 break;
7340                         }
7341                         optreturn = getoption(phy_ops, optarg, &phy_operation,
7342                                               &argnums, &subopt);
7343
7344                         if (optreturn == CC_OR_AMBIGUOUS) {
7345                                 warnx("%s: ambiguous option %s", __func__,
7346                                       optarg);
7347                                 usage(0);
7348                                 retval = 1;
7349                                 goto bailout;
7350                         } else if (optreturn == CC_OR_NOT_FOUND) {
7351                                 warnx("%s: option %s not found", __func__,
7352                                       optarg);
7353                                 usage(0);
7354                                 retval = 1;
7355                                 goto bailout;
7356                         }
7357                         break;
7358                 }
7359                 case 'p':
7360                         phy = atoi(optarg);
7361                         break;
7362                 case 'T':
7363                         pp_timeout_val = strtoul(optarg, NULL, 0);
7364                         if (pp_timeout_val > 15) {
7365                                 warnx("%s: invalid partial pathway timeout "
7366                                       "value %u, need a value less than 16",
7367                                       __func__, pp_timeout_val);
7368                                 retval = 1;
7369                                 goto bailout;
7370                         }
7371                         set_pp_timeout_val = 1;
7372                         break;
7373                 default:
7374                         break;
7375                 }
7376         }
7377
7378         if (phy == -1) {
7379                 warnx("%s: a PHY (-p phy) argument is required",__func__);
7380                 retval = 1;
7381                 goto bailout;
7382         }
7383
7384         if (((dev_name_set != 0)
7385           && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7386          || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7387           && (dev_name_set == 0))) {
7388                 warnx("%s: -d name and -o setdevname arguments both "
7389                       "required to set device name", __func__);
7390                 retval = 1;
7391                 goto bailout;
7392         }
7393
7394         request = malloc(sizeof(*request));
7395         if (request == NULL) {
7396                 warn("%s: unable to allocate %zd bytes", __func__,
7397                      sizeof(*request));
7398                 retval = 1;
7399                 goto bailout;
7400         }
7401
7402         response = malloc(sizeof(*response));
7403         if (response == NULL) {
7404                 warn("%s: unable to allocate %zd bytes", __func__,
7405                      sizeof(*response));
7406                 retval = 1;
7407                 goto bailout;
7408         }
7409
7410         smp_phy_control(&ccb->smpio,
7411                         retry_count,
7412                         /*cbfcnp*/ NULL,
7413                         request,
7414                         sizeof(*request),
7415                         (uint8_t *)response,
7416                         sizeof(*response),
7417                         long_response,
7418                         /*expected_exp_change_count*/ 0,
7419                         phy,
7420                         phy_operation,
7421                         (set_pp_timeout_val != 0) ? 1 : 0,
7422                         attached_dev_name,
7423                         min_plr,
7424                         max_plr,
7425                         slumber_partial,
7426                         pp_timeout_val,
7427                         timeout);
7428
7429         if (((retval = cam_send_ccb(device, ccb)) < 0)
7430          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7431                 const char warnstr[] = "error sending command";
7432
7433                 if (retval < 0)
7434                         warn(warnstr);
7435                 else
7436                         warnx(warnstr);
7437
7438                 if (arglist & CAM_ARG_VERBOSE) {
7439                         /*
7440                          * Use CAM_EPF_NORMAL so we only get one line of
7441                          * SMP command decoding.
7442                          */
7443                         cam_error_print(device, ccb, CAM_ESF_ALL,
7444                                         CAM_EPF_NORMAL, stderr);
7445                 }
7446                 retval = 1;
7447                 goto bailout;
7448         }
7449
7450         /* XXX KDM print out something here for success? */
7451 bailout:
7452         if (ccb != NULL)
7453                 cam_freeccb(ccb);
7454
7455         if (request != NULL)
7456                 free(request);
7457
7458         if (response != NULL)
7459                 free(response);
7460
7461         return (retval);
7462 }
7463
7464 static int
7465 smpmaninfo(struct cam_device *device, int argc, char **argv,
7466            char *combinedopt, int retry_count, int timeout)
7467 {
7468         union ccb *ccb;
7469         struct smp_report_manuf_info_request request;
7470         struct smp_report_manuf_info_response response;
7471         struct sbuf *sb = NULL;
7472         int long_response = 0;
7473         int retval = 0;
7474         int c;
7475
7476         /*
7477          * Note that at the moment we don't support sending SMP CCBs to
7478          * devices that aren't probed by CAM.
7479          */
7480         ccb = cam_getccb(device);
7481         if (ccb == NULL) {
7482                 warnx("%s: error allocating CCB", __func__);
7483                 return (1);
7484         }
7485
7486         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7487
7488         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7489                 switch (c) {
7490                 case 'l':
7491                         long_response = 1;
7492                         break;
7493                 default:
7494                         break;
7495                 }
7496         }
7497         bzero(&request, sizeof(request));
7498         bzero(&response, sizeof(response));
7499
7500         smp_report_manuf_info(&ccb->smpio,
7501                               retry_count,
7502                               /*cbfcnp*/ NULL,
7503                               &request,
7504                               sizeof(request),
7505                               (uint8_t *)&response,
7506                               sizeof(response),
7507                               long_response,
7508                               timeout);
7509
7510         if (((retval = cam_send_ccb(device, ccb)) < 0)
7511          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7512                 const char warnstr[] = "error sending command";
7513
7514                 if (retval < 0)
7515                         warn(warnstr);
7516                 else
7517                         warnx(warnstr);
7518
7519                 if (arglist & CAM_ARG_VERBOSE) {
7520                         cam_error_print(device, ccb, CAM_ESF_ALL,
7521                                         CAM_EPF_ALL, stderr);
7522                 }
7523                 retval = 1;
7524                 goto bailout;
7525         }
7526
7527         sb = sbuf_new_auto();
7528         if (sb == NULL) {
7529                 warnx("%s: error allocating sbuf", __func__);
7530                 goto bailout;
7531         }
7532
7533         smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7534
7535         if (sbuf_finish(sb) != 0) {
7536                 warnx("%s: sbuf_finish", __func__);
7537                 goto bailout;
7538         }
7539
7540         printf("%s", sbuf_data(sb));
7541
7542 bailout:
7543
7544         if (ccb != NULL)
7545                 cam_freeccb(ccb);
7546
7547         if (sb != NULL)
7548                 sbuf_delete(sb);
7549
7550         return (retval);
7551 }
7552
7553 static int
7554 getdevid(struct cam_devitem *item)
7555 {
7556         int retval = 0;
7557         union ccb *ccb = NULL;
7558
7559         struct cam_device *dev;
7560
7561         dev = cam_open_btl(item->dev_match.path_id,
7562                            item->dev_match.target_id,
7563                            item->dev_match.target_lun, O_RDWR, NULL);
7564
7565         if (dev == NULL) {
7566                 warnx("%s", cam_errbuf);
7567                 retval = 1;
7568                 goto bailout;
7569         }
7570
7571         item->device_id_len = 0;
7572
7573         ccb = cam_getccb(dev);
7574         if (ccb == NULL) {
7575                 warnx("%s: error allocating CCB", __func__);
7576                 retval = 1;
7577                 goto bailout;
7578         }
7579
7580         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai);
7581
7582         /*
7583          * On the first try, we just probe for the size of the data, and
7584          * then allocate that much memory and try again.
7585          */
7586 retry:
7587         ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7588         ccb->ccb_h.flags = CAM_DIR_IN;
7589         ccb->cdai.flags = CDAI_FLAG_NONE;
7590         ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7591         ccb->cdai.bufsiz = item->device_id_len;
7592         if (item->device_id_len != 0)
7593                 ccb->cdai.buf = (uint8_t *)item->device_id;
7594
7595         if (cam_send_ccb(dev, ccb) < 0) {
7596                 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7597                 retval = 1;
7598                 goto bailout;
7599         }
7600
7601         if (ccb->ccb_h.status != CAM_REQ_CMP) {
7602                 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7603                 retval = 1;
7604                 goto bailout;
7605         }
7606
7607         if (item->device_id_len == 0) {
7608                 /*
7609                  * This is our first time through.  Allocate the buffer,
7610                  * and then go back to get the data.
7611                  */
7612                 if (ccb->cdai.provsiz == 0) {
7613                         warnx("%s: invalid .provsiz field returned with "
7614                              "XPT_GDEV_ADVINFO CCB", __func__);
7615                         retval = 1;
7616                         goto bailout;
7617                 }
7618                 item->device_id_len = ccb->cdai.provsiz;
7619                 item->device_id = malloc(item->device_id_len);
7620                 if (item->device_id == NULL) {
7621                         warn("%s: unable to allocate %d bytes", __func__,
7622                              item->device_id_len);
7623                         retval = 1;
7624                         goto bailout;
7625                 }
7626                 ccb->ccb_h.status = CAM_REQ_INPROG;
7627                 goto retry;
7628         }
7629
7630 bailout:
7631         if (dev != NULL)
7632                 cam_close_device(dev);
7633
7634         if (ccb != NULL)
7635                 cam_freeccb(ccb);
7636
7637         return (retval);
7638 }
7639
7640 /*
7641  * XXX KDM merge this code with getdevtree()?
7642  */
7643 static int
7644 buildbusdevlist(struct cam_devlist *devlist)
7645 {
7646         union ccb ccb;
7647         int bufsize, fd = -1;
7648         struct dev_match_pattern *patterns;
7649         struct cam_devitem *item = NULL;
7650         int skip_device = 0;
7651         int retval = 0;
7652
7653         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7654                 warn("couldn't open %s", XPT_DEVICE);
7655                 return(1);
7656         }
7657
7658         bzero(&ccb, sizeof(union ccb));
7659
7660         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7661         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7662         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7663
7664         ccb.ccb_h.func_code = XPT_DEV_MATCH;
7665         bufsize = sizeof(struct dev_match_result) * 100;
7666         ccb.cdm.match_buf_len = bufsize;
7667         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7668         if (ccb.cdm.matches == NULL) {
7669                 warnx("can't malloc memory for matches");
7670                 close(fd);
7671                 return(1);
7672         }
7673         ccb.cdm.num_matches = 0;
7674         ccb.cdm.num_patterns = 2;
7675         ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7676                 ccb.cdm.num_patterns;
7677
7678         patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7679         if (patterns == NULL) {
7680                 warnx("can't malloc memory for patterns");
7681                 retval = 1;
7682                 goto bailout;
7683         }
7684
7685         ccb.cdm.patterns = patterns;
7686         bzero(patterns, ccb.cdm.pattern_buf_len);
7687
7688         patterns[0].type = DEV_MATCH_DEVICE;
7689         patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7690         patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7691         patterns[1].type = DEV_MATCH_PERIPH;
7692         patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7693         patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7694
7695         /*
7696          * We do the ioctl multiple times if necessary, in case there are
7697          * more than 100 nodes in the EDT.
7698          */
7699         do {
7700                 unsigned int i;
7701
7702                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7703                         warn("error sending CAMIOCOMMAND ioctl");
7704                         retval = 1;
7705                         goto bailout;
7706                 }
7707
7708                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7709                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7710                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7711                         warnx("got CAM error %#x, CDM error %d\n",
7712                               ccb.ccb_h.status, ccb.cdm.status);
7713                         retval = 1;
7714                         goto bailout;
7715                 }
7716
7717                 for (i = 0; i < ccb.cdm.num_matches; i++) {
7718                         switch (ccb.cdm.matches[i].type) {
7719                         case DEV_MATCH_DEVICE: {
7720                                 struct device_match_result *dev_result;
7721
7722                                 dev_result = 
7723                                      &ccb.cdm.matches[i].result.device_result;
7724
7725                                 if (dev_result->flags &
7726                                     DEV_RESULT_UNCONFIGURED) {
7727                                         skip_device = 1;
7728                                         break;
7729                                 } else
7730                                         skip_device = 0;
7731
7732                                 item = malloc(sizeof(*item));
7733                                 if (item == NULL) {
7734                                         warn("%s: unable to allocate %zd bytes",
7735                                              __func__, sizeof(*item));
7736                                         retval = 1;
7737                                         goto bailout;
7738                                 }
7739                                 bzero(item, sizeof(*item));
7740                                 bcopy(dev_result, &item->dev_match,
7741                                       sizeof(*dev_result));
7742                                 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7743                                                    links);
7744
7745                                 if (getdevid(item) != 0) {
7746                                         retval = 1;
7747                                         goto bailout;
7748                                 }
7749                                 break;
7750                         }
7751                         case DEV_MATCH_PERIPH: {
7752                                 struct periph_match_result *periph_result;
7753
7754                                 periph_result =
7755                                       &ccb.cdm.matches[i].result.periph_result;
7756
7757                                 if (skip_device != 0)
7758                                         break;
7759                                 item->num_periphs++;
7760                                 item->periph_matches = realloc(
7761                                         item->periph_matches,
7762                                         item->num_periphs *
7763                                         sizeof(struct periph_match_result));
7764                                 if (item->periph_matches == NULL) {
7765                                         warn("%s: error allocating periph "
7766                                              "list", __func__);
7767                                         retval = 1;
7768                                         goto bailout;
7769                                 }
7770                                 bcopy(periph_result, &item->periph_matches[
7771                                       item->num_periphs - 1],
7772                                       sizeof(*periph_result));
7773                                 break;
7774                         }
7775                         default:
7776                                 fprintf(stderr, "%s: unexpected match "
7777                                         "type %d\n", __func__,
7778                                         ccb.cdm.matches[i].type);
7779                                 retval = 1;
7780                                 goto bailout;
7781                                 break; /*NOTREACHED*/
7782                         }
7783                 }
7784         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7785                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7786 bailout:
7787
7788         if (fd != -1)
7789                 close(fd);
7790
7791         free(patterns);
7792
7793         free(ccb.cdm.matches);
7794
7795         if (retval != 0)
7796                 freebusdevlist(devlist);
7797
7798         return (retval);
7799 }
7800
7801 static void
7802 freebusdevlist(struct cam_devlist *devlist)
7803 {
7804         struct cam_devitem *item, *item2;
7805
7806         STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7807                 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7808                               links);
7809                 free(item->device_id);
7810                 free(item->periph_matches);
7811                 free(item);
7812         }
7813 }
7814
7815 static struct cam_devitem *
7816 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7817 {
7818         struct cam_devitem *item;
7819
7820         STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7821                 struct scsi_vpd_id_descriptor *idd;
7822
7823                 /*
7824                  * XXX KDM look for LUN IDs as well?
7825                  */
7826                 idd = scsi_get_devid(item->device_id,
7827                                            item->device_id_len,
7828                                            scsi_devid_is_sas_target);
7829                 if (idd == NULL)
7830                         continue;
7831
7832                 if (scsi_8btou64(idd->identifier) == sasaddr)
7833                         return (item);
7834         }
7835
7836         return (NULL);
7837 }
7838
7839 static int
7840 smpphylist(struct cam_device *device, int argc, char **argv,
7841            char *combinedopt, int retry_count, int timeout)
7842 {
7843         struct smp_report_general_request *rgrequest = NULL;
7844         struct smp_report_general_response *rgresponse = NULL;
7845         struct smp_discover_request *disrequest = NULL;
7846         struct smp_discover_response *disresponse = NULL;
7847         struct cam_devlist devlist;
7848         union ccb *ccb;
7849         int long_response = 0;
7850         int num_phys = 0;
7851         int quiet = 0;
7852         int retval;
7853         int i, c;
7854
7855         /*
7856          * Note that at the moment we don't support sending SMP CCBs to
7857          * devices that aren't probed by CAM.
7858          */
7859         ccb = cam_getccb(device);
7860         if (ccb == NULL) {
7861                 warnx("%s: error allocating CCB", __func__);
7862                 return (1);
7863         }
7864
7865         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7866         STAILQ_INIT(&devlist.dev_queue);
7867
7868         rgrequest = malloc(sizeof(*rgrequest));
7869         if (rgrequest == NULL) {
7870                 warn("%s: unable to allocate %zd bytes", __func__,
7871                      sizeof(*rgrequest));
7872                 retval = 1;
7873                 goto bailout;
7874         }
7875
7876         rgresponse = malloc(sizeof(*rgresponse));
7877         if (rgresponse == NULL) {
7878                 warn("%s: unable to allocate %zd bytes", __func__,
7879                      sizeof(*rgresponse));
7880                 retval = 1;
7881                 goto bailout;
7882         }
7883
7884         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7885                 switch (c) {
7886                 case 'l':
7887                         long_response = 1;
7888                         break;
7889                 case 'q':
7890                         quiet = 1;
7891                         break;
7892                 default:
7893                         break;
7894                 }
7895         }
7896
7897         smp_report_general(&ccb->smpio,
7898                            retry_count,
7899                            /*cbfcnp*/ NULL,
7900                            rgrequest,
7901                            /*request_len*/ sizeof(*rgrequest),
7902                            (uint8_t *)rgresponse,
7903                            /*response_len*/ sizeof(*rgresponse),
7904                            /*long_response*/ long_response,
7905                            timeout);
7906
7907         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7908
7909         if (((retval = cam_send_ccb(device, ccb)) < 0)
7910          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7911                 const char warnstr[] = "error sending command";
7912
7913                 if (retval < 0)
7914                         warn(warnstr);
7915                 else
7916                         warnx(warnstr);
7917
7918                 if (arglist & CAM_ARG_VERBOSE) {
7919                         cam_error_print(device, ccb, CAM_ESF_ALL,
7920                                         CAM_EPF_ALL, stderr);
7921                 }
7922                 retval = 1;
7923                 goto bailout;
7924         }
7925
7926         num_phys = rgresponse->num_phys;
7927
7928         if (num_phys == 0) {
7929                 if (quiet == 0)
7930                         fprintf(stdout, "%s: No Phys reported\n", __func__);
7931                 retval = 1;
7932                 goto bailout;
7933         }
7934
7935         devlist.path_id = device->path_id;
7936
7937         retval = buildbusdevlist(&devlist);
7938         if (retval != 0)
7939                 goto bailout;
7940
7941         if (quiet == 0) {
7942                 fprintf(stdout, "%d PHYs:\n", num_phys);
7943                 fprintf(stdout, "PHY  Attached SAS Address\n");
7944         }
7945
7946         disrequest = malloc(sizeof(*disrequest));
7947         if (disrequest == NULL) {
7948                 warn("%s: unable to allocate %zd bytes", __func__,
7949                      sizeof(*disrequest));
7950                 retval = 1;
7951                 goto bailout;
7952         }
7953
7954         disresponse = malloc(sizeof(*disresponse));
7955         if (disresponse == NULL) {
7956                 warn("%s: unable to allocate %zd bytes", __func__,
7957                      sizeof(*disresponse));
7958                 retval = 1;
7959                 goto bailout;
7960         }
7961
7962         for (i = 0; i < num_phys; i++) {
7963                 struct cam_devitem *item;
7964                 struct device_match_result *dev_match;
7965                 char vendor[16], product[48], revision[16];
7966                 char tmpstr[256];
7967                 int j;
7968
7969                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7970
7971                 ccb->ccb_h.status = CAM_REQ_INPROG;
7972                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7973
7974                 smp_discover(&ccb->smpio,
7975                              retry_count,
7976                              /*cbfcnp*/ NULL,
7977                              disrequest,
7978                              sizeof(*disrequest),
7979                              (uint8_t *)disresponse,
7980                              sizeof(*disresponse),
7981                              long_response,
7982                              /*ignore_zone_group*/ 0,
7983                              /*phy*/ i,
7984                              timeout);
7985
7986                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7987                  || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7988                   && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7989                         const char warnstr[] = "error sending command";
7990
7991                         if (retval < 0)
7992                                 warn(warnstr);
7993                         else
7994                                 warnx(warnstr);
7995
7996                         if (arglist & CAM_ARG_VERBOSE) {
7997                                 cam_error_print(device, ccb, CAM_ESF_ALL,
7998                                                 CAM_EPF_ALL, stderr);
7999                         }
8000                         retval = 1;
8001                         goto bailout;
8002                 }
8003
8004                 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
8005                         if (quiet == 0)
8006                                 fprintf(stdout, "%3d  <vacant>\n", i);
8007                         continue;
8008                 }
8009
8010                 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
8011                         item = NULL;
8012                 } else {
8013                         item = findsasdevice(&devlist,
8014                             scsi_8btou64(disresponse->attached_sas_address));
8015                 }
8016
8017                 if ((quiet == 0)
8018                  || (item != NULL)) {
8019                         fprintf(stdout, "%3d  0x%016jx", i,
8020                                 (uintmax_t)scsi_8btou64(
8021                                 disresponse->attached_sas_address));
8022                         if (item == NULL) {
8023                                 fprintf(stdout, "\n");
8024                                 continue;
8025                         }
8026                 } else if (quiet != 0)
8027                         continue;
8028
8029                 dev_match = &item->dev_match;
8030
8031                 if (dev_match->protocol == PROTO_SCSI) {
8032                         cam_strvis(vendor, dev_match->inq_data.vendor,
8033                                    sizeof(dev_match->inq_data.vendor),
8034                                    sizeof(vendor));
8035                         cam_strvis(product, dev_match->inq_data.product,
8036                                    sizeof(dev_match->inq_data.product),
8037                                    sizeof(product));
8038                         cam_strvis(revision, dev_match->inq_data.revision,
8039                                    sizeof(dev_match->inq_data.revision),
8040                                    sizeof(revision));
8041                         sprintf(tmpstr, "<%s %s %s>", vendor, product,
8042                                 revision);
8043                 } else if ((dev_match->protocol == PROTO_ATA)
8044                         || (dev_match->protocol == PROTO_SATAPM)) {
8045                         cam_strvis(product, dev_match->ident_data.model,
8046                                    sizeof(dev_match->ident_data.model),
8047                                    sizeof(product));
8048                         cam_strvis(revision, dev_match->ident_data.revision,
8049                                    sizeof(dev_match->ident_data.revision),
8050                                    sizeof(revision));
8051                         sprintf(tmpstr, "<%s %s>", product, revision);
8052                 } else {
8053                         sprintf(tmpstr, "<>");
8054                 }
8055                 fprintf(stdout, "   %-33s ", tmpstr);
8056
8057                 /*
8058                  * If we have 0 periphs, that's a bug...
8059                  */
8060                 if (item->num_periphs == 0) {
8061                         fprintf(stdout, "\n");
8062                         continue;
8063                 }
8064
8065                 fprintf(stdout, "(");
8066                 for (j = 0; j < item->num_periphs; j++) {
8067                         if (j > 0)
8068                                 fprintf(stdout, ",");
8069
8070                         fprintf(stdout, "%s%d",
8071                                 item->periph_matches[j].periph_name,
8072                                 item->periph_matches[j].unit_number);
8073                                 
8074                 }
8075                 fprintf(stdout, ")\n");
8076         }
8077 bailout:
8078         if (ccb != NULL)
8079                 cam_freeccb(ccb);
8080
8081         free(rgrequest);
8082
8083         free(rgresponse);
8084
8085         free(disrequest);
8086
8087         free(disresponse);
8088
8089         freebusdevlist(&devlist);
8090
8091         return (retval);
8092 }
8093
8094 static int
8095 atapm(struct cam_device *device, int argc, char **argv,
8096                  char *combinedopt, int retry_count, int timeout)
8097 {
8098         union ccb *ccb;
8099         int retval = 0;
8100         int t = -1;
8101         int c;
8102         u_char cmd, sc;
8103
8104         ccb = cam_getccb(device);
8105
8106         if (ccb == NULL) {
8107                 warnx("%s: error allocating ccb", __func__);
8108                 return (1);
8109         }
8110
8111         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8112                 switch (c) {
8113                 case 't':
8114                         t = atoi(optarg);
8115                         break;
8116                 default:
8117                         break;
8118                 }
8119         }
8120         if (strcmp(argv[1], "idle") == 0) {
8121                 if (t == -1)
8122                         cmd = ATA_IDLE_IMMEDIATE;
8123                 else
8124                         cmd = ATA_IDLE_CMD;
8125         } else if (strcmp(argv[1], "standby") == 0) {
8126                 if (t == -1)
8127                         cmd = ATA_STANDBY_IMMEDIATE;
8128                 else
8129                         cmd = ATA_STANDBY_CMD;
8130         } else {
8131                 cmd = ATA_SLEEP;
8132                 t = -1;
8133         }
8134
8135         if (t < 0)
8136                 sc = 0;
8137         else if (t <= (240 * 5))
8138                 sc = (t + 4) / 5;
8139         else if (t <= (252 * 5))
8140                 /* special encoding for 21 minutes */
8141                 sc = 252;
8142         else if (t <= (11 * 30 * 60))
8143                 sc = (t - 1) / (30 * 60) + 241;
8144         else
8145                 sc = 253;
8146
8147         retval = ata_do_28bit_cmd(device,
8148             ccb,
8149             /*retries*/retry_count,
8150             /*flags*/CAM_DIR_NONE,
8151             /*protocol*/AP_PROTO_NON_DATA,
8152             /*tag_action*/MSG_SIMPLE_Q_TAG,
8153             /*command*/cmd,
8154             /*features*/0,
8155             /*lba*/0,
8156             /*sector_count*/sc,
8157             /*data_ptr*/NULL,
8158             /*dxfer_len*/0,
8159             /*timeout*/timeout ? timeout : 30 * 1000,
8160             /*quiet*/1);
8161
8162         cam_freeccb(ccb);
8163         return (retval);
8164 }
8165
8166 static int
8167 ataaxm(struct cam_device *device, int argc, char **argv,
8168                  char *combinedopt, int retry_count, int timeout)
8169 {
8170         union ccb *ccb;
8171         int retval = 0;
8172         int l = -1;
8173         int c;
8174         u_char cmd, sc;
8175
8176         ccb = cam_getccb(device);
8177
8178         if (ccb == NULL) {
8179                 warnx("%s: error allocating ccb", __func__);
8180                 return (1);
8181         }
8182
8183         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8184                 switch (c) {
8185                 case 'l':
8186                         l = atoi(optarg);
8187                         break;
8188                 default:
8189                         break;
8190                 }
8191         }
8192         sc = 0;
8193         if (strcmp(argv[1], "apm") == 0) {
8194                 if (l == -1)
8195                         cmd = 0x85;
8196                 else {
8197                         cmd = 0x05;
8198                         sc = l;
8199                 }
8200         } else /* aam */ {
8201                 if (l == -1)
8202                         cmd = 0xC2;
8203                 else {
8204                         cmd = 0x42;
8205                         sc = l;
8206                 }
8207         }
8208
8209         retval = ata_do_28bit_cmd(device,
8210             ccb,
8211             /*retries*/retry_count,
8212             /*flags*/CAM_DIR_NONE,
8213             /*protocol*/AP_PROTO_NON_DATA,
8214             /*tag_action*/MSG_SIMPLE_Q_TAG,
8215             /*command*/ATA_SETFEATURES,
8216             /*features*/cmd,
8217             /*lba*/0,
8218             /*sector_count*/sc,
8219             /*data_ptr*/NULL,
8220             /*dxfer_len*/0,
8221             /*timeout*/timeout ? timeout : 30 * 1000,
8222             /*quiet*/1);
8223
8224         cam_freeccb(ccb);
8225         return (retval);
8226 }
8227
8228 int
8229 scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8230                int show_sa_errors, int sa_set, int service_action,
8231                int timeout_desc, int task_attr, int retry_count, int timeout,
8232                int verbosemode, uint32_t *fill_len, uint8_t **data_ptr)
8233 {
8234         union ccb *ccb = NULL;
8235         uint8_t *buf = NULL;
8236         uint32_t alloc_len = 0, num_opcodes;
8237         uint32_t valid_len = 0;
8238         uint32_t avail_len = 0;
8239         struct scsi_report_supported_opcodes_all *all_hdr;
8240         struct scsi_report_supported_opcodes_one *one;
8241         int options = 0;
8242         int retval = 0;
8243
8244         /*
8245          * Make it clear that we haven't yet allocated or filled anything.
8246          */
8247         *fill_len = 0;
8248         *data_ptr = NULL;
8249
8250         ccb = cam_getccb(device);
8251         if (ccb == NULL) {
8252                 warnx("couldn't allocate CCB");
8253                 retval = 1;
8254                 goto bailout;
8255         }
8256
8257         /* cam_getccb cleans up the header, caller has to zero the payload */
8258         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8259
8260         if (opcode_set != 0) {
8261                 options |= RSO_OPTIONS_OC;
8262                 num_opcodes = 1;
8263                 alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8264         } else {
8265                 num_opcodes = 256;
8266                 alloc_len = sizeof(*all_hdr) + (num_opcodes *
8267                     sizeof(struct scsi_report_supported_opcodes_descr));
8268         }
8269
8270         if (timeout_desc != 0) {
8271                 options |= RSO_RCTD;
8272                 alloc_len += num_opcodes *
8273                     sizeof(struct scsi_report_supported_opcodes_timeout);
8274         }
8275         
8276         if (sa_set != 0) {
8277                 options |= RSO_OPTIONS_OC_SA;
8278                 if (show_sa_errors != 0)
8279                         options &= ~RSO_OPTIONS_OC;
8280         }
8281
8282 retry_alloc:
8283         if (buf != NULL) {
8284                 free(buf);
8285                 buf = NULL;
8286         } 
8287
8288         buf = malloc(alloc_len);
8289         if (buf == NULL) {
8290                 warn("Unable to allocate %u bytes", alloc_len);
8291                 retval = 1;
8292                 goto bailout;
8293         }
8294         bzero(buf, alloc_len);
8295
8296         scsi_report_supported_opcodes(&ccb->csio,
8297                                       /*retries*/ retry_count,
8298                                       /*cbfcnp*/ NULL,
8299                                       /*tag_action*/ task_attr,
8300                                       /*options*/ options,
8301                                       /*req_opcode*/ opcode,
8302                                       /*req_service_action*/ service_action,
8303                                       /*data_ptr*/ buf,
8304                                       /*dxfer_len*/ alloc_len,
8305                                       /*sense_len*/ SSD_FULL_SIZE,
8306                                       /*timeout*/ timeout ? timeout : 10000);
8307
8308         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8309
8310         if (retry_count != 0)
8311                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
8312
8313         if (cam_send_ccb(device, ccb) < 0) {
8314                 perror("error sending REPORT SUPPORTED OPERATION CODES");
8315                 retval = 1;
8316                 goto bailout;
8317         }
8318
8319         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8320                 if (verbosemode != 0)
8321                         cam_error_print(device, ccb, CAM_ESF_ALL,
8322                                         CAM_EPF_ALL, stderr);
8323                 
8324                 retval = 1;
8325                 goto bailout;
8326         }
8327
8328         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
8329
8330         if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
8331          && (valid_len >= sizeof(*all_hdr))) {
8332                 all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
8333                 avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
8334         } else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
8335                 && (valid_len >= sizeof(*one))) {
8336                 uint32_t cdb_length;
8337
8338                 one = (struct scsi_report_supported_opcodes_one *)buf;
8339                 cdb_length = scsi_2btoul(one->cdb_length);
8340                 avail_len = sizeof(*one) + cdb_length;
8341                 if (one->support & RSO_ONE_CTDP) {
8342                         struct scsi_report_supported_opcodes_timeout *td;
8343
8344                         td = (struct scsi_report_supported_opcodes_timeout *)
8345                             &buf[avail_len];
8346                         if (valid_len >= (avail_len + sizeof(td->length))) {
8347                                 avail_len += scsi_2btoul(td->length) +
8348                                     sizeof(td->length);
8349                         } else {
8350                                 avail_len += sizeof(*td);
8351                         }
8352                 }
8353         }
8354
8355         /*
8356          * avail_len could be zero if we didn't get enough data back from
8357          * thet target to determine
8358          */
8359         if ((avail_len != 0)
8360          && (avail_len > valid_len)) {
8361                 alloc_len = avail_len;
8362                 goto retry_alloc;
8363         }
8364
8365         *fill_len = valid_len;
8366         *data_ptr = buf;
8367 bailout:
8368         if (retval != 0)
8369                 free(buf);
8370
8371         cam_freeccb(ccb);
8372
8373         return (retval);
8374 }
8375
8376 static int
8377 scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
8378                    int req_sa, uint8_t *buf, uint32_t valid_len)
8379 {
8380         struct scsi_report_supported_opcodes_one *one;
8381         struct scsi_report_supported_opcodes_timeout *td;
8382         uint32_t cdb_len = 0, td_len = 0;
8383         const char *op_desc = NULL;
8384         unsigned int i;
8385         int retval = 0;
8386
8387         one = (struct scsi_report_supported_opcodes_one *)buf;
8388
8389         /*
8390          * If we don't have the full single opcode descriptor, no point in
8391          * continuing.
8392          */
8393         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8394             cdb_length)) {
8395                 warnx("Only %u bytes returned, not enough to verify support",
8396                       valid_len);
8397                 retval = 1;
8398                 goto bailout;
8399         }
8400
8401         op_desc = scsi_op_desc(req_opcode, &device->inq_data);
8402
8403         printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
8404                req_opcode);
8405         if (sa_set != 0)
8406                 printf(", SA 0x%x", req_sa);
8407         printf(": ");
8408
8409         switch (one->support & RSO_ONE_SUP_MASK) {
8410         case RSO_ONE_SUP_UNAVAIL:
8411                 printf("No command support information currently available\n");
8412                 break;
8413         case RSO_ONE_SUP_NOT_SUP:
8414                 printf("Command not supported\n");
8415                 retval = 1;
8416                 goto bailout;
8417                 break; /*NOTREACHED*/
8418         case RSO_ONE_SUP_AVAIL:
8419                 printf("Command is supported, complies with a SCSI standard\n");
8420                 break;
8421         case RSO_ONE_SUP_VENDOR:
8422                 printf("Command is supported, vendor-specific "
8423                        "implementation\n");
8424                 break;
8425         default:
8426                 printf("Unknown command support flags 0x%#x\n",
8427                        one->support & RSO_ONE_SUP_MASK);
8428                 break;
8429         }
8430
8431         /*
8432          * If we don't have the CDB length, it isn't exactly an error, the
8433          * command probably isn't supported.
8434          */
8435         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8436             cdb_usage))
8437                 goto bailout;
8438
8439         cdb_len = scsi_2btoul(one->cdb_length);
8440
8441         /*
8442          * If our valid data doesn't include the full reported length,
8443          * return.  The caller should have detected this and adjusted his
8444          * allocation length to get all of the available data.
8445          */
8446         if (valid_len < sizeof(*one) + cdb_len) {
8447                 retval = 1;
8448                 goto bailout;
8449         }
8450
8451         /*
8452          * If all we have is the opcode, there is no point in printing out
8453          * the usage bitmap.
8454          */
8455         if (cdb_len <= 1) {
8456                 retval = 1;
8457                 goto bailout;
8458         }
8459
8460         printf("CDB usage bitmap:");
8461         for (i = 0; i < cdb_len; i++) {
8462                 printf(" %02x", one->cdb_usage[i]);
8463         }
8464         printf("\n");
8465
8466         /*
8467          * If we don't have a timeout descriptor, we're done.
8468          */
8469         if ((one->support & RSO_ONE_CTDP) == 0)
8470                 goto bailout;
8471
8472         /*
8473          * If we don't have enough valid length to include the timeout
8474          * descriptor length, we're done.
8475          */
8476         if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
8477                 goto bailout;
8478
8479         td = (struct scsi_report_supported_opcodes_timeout *)
8480             &buf[sizeof(*one) + cdb_len];
8481         td_len = scsi_2btoul(td->length);
8482         td_len += sizeof(td->length);
8483
8484         /*
8485          * If we don't have the full timeout descriptor, we're done.
8486          */
8487         if (td_len < sizeof(*td))
8488                 goto bailout;
8489
8490         /*
8491          * If we don't have enough valid length to contain the full timeout
8492          * descriptor, we're done.
8493          */
8494         if (valid_len < (sizeof(*one) + cdb_len + td_len))
8495                 goto bailout;
8496
8497         printf("Timeout information:\n");
8498         printf("Command-specific:    0x%02x\n", td->cmd_specific);
8499         printf("Nominal timeout:     %u seconds\n",
8500                scsi_4btoul(td->nominal_time));
8501         printf("Recommended timeout: %u seconds\n",
8502                scsi_4btoul(td->recommended_time));
8503
8504 bailout:
8505         return (retval);
8506 }
8507
8508 static int
8509 scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
8510                  uint32_t valid_len)
8511 {
8512         struct scsi_report_supported_opcodes_all *hdr;
8513         struct scsi_report_supported_opcodes_descr *desc;
8514         uint32_t avail_len = 0, used_len = 0;
8515         uint8_t *cur_ptr;
8516         int retval = 0;
8517
8518         if (valid_len < sizeof(*hdr)) {
8519                 warnx("%s: not enough returned data (%u bytes) opcode list",
8520                       __func__, valid_len);
8521                 retval = 1;
8522                 goto bailout;
8523         }
8524         hdr = (struct scsi_report_supported_opcodes_all *)buf;
8525         avail_len = scsi_4btoul(hdr->length);
8526         avail_len += sizeof(hdr->length);
8527         /*
8528          * Take the lesser of the amount of data the drive claims is
8529          * available, and the amount of data the HBA says was returned.
8530          */
8531         avail_len = MIN(avail_len, valid_len);
8532
8533         used_len = sizeof(hdr->length);
8534
8535         printf("%-6s %4s %8s ",
8536                "Opcode", "SA", "CDB len" );
8537
8538         if (td_req != 0)
8539                 printf("%5s %6s %6s ", "CS", "Nom", "Rec");
8540         printf(" Description\n");
8541
8542         while ((avail_len - used_len) > sizeof(*desc)) {
8543                 struct scsi_report_supported_opcodes_timeout *td;
8544                 uint32_t td_len;
8545                 const char *op_desc = NULL;
8546
8547                 cur_ptr = &buf[used_len];
8548                 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
8549
8550                 op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
8551                 if (op_desc == NULL)
8552                         op_desc = "UNKNOWN";
8553
8554                 printf("0x%02x   %#4x %8u ", desc->opcode,
8555                        scsi_2btoul(desc->service_action),
8556                        scsi_2btoul(desc->cdb_length));
8557
8558                 used_len += sizeof(*desc);
8559
8560                 if ((desc->flags & RSO_CTDP) == 0) {
8561                         printf(" %s\n", op_desc);
8562                         continue;
8563                 }
8564
8565                 /*
8566                  * If we don't have enough space to fit a timeout
8567                  * descriptor, then we're done.
8568                  */
8569                 if (avail_len - used_len < sizeof(*td)) {
8570                         used_len = avail_len;
8571                         printf(" %s\n", op_desc);
8572                         continue;
8573                 }
8574                 cur_ptr = &buf[used_len];
8575                 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
8576                 td_len = scsi_2btoul(td->length);
8577                 td_len += sizeof(td->length);
8578
8579                 used_len += td_len;
8580                 /*
8581                  * If the given timeout descriptor length is less than what
8582                  * we understand, skip it.
8583                  */
8584                 if (td_len < sizeof(*td)) {
8585                         printf(" %s\n", op_desc);
8586                         continue;
8587                 }
8588
8589                 printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
8590                        scsi_4btoul(td->nominal_time),
8591                        scsi_4btoul(td->recommended_time), op_desc);
8592         }
8593 bailout:
8594         return (retval);
8595 }
8596
8597 static int
8598 scsiopcodes(struct cam_device *device, int argc, char **argv,
8599             char *combinedopt, int task_attr, int retry_count, int timeout,
8600             int verbosemode)
8601 {
8602         int c;
8603         uint32_t opcode = 0, service_action = 0;
8604         int td_set = 0, opcode_set = 0, sa_set = 0;
8605         int show_sa_errors = 1;
8606         uint32_t valid_len = 0;
8607         uint8_t *buf = NULL;
8608         char *endptr;
8609         int retval = 0;
8610
8611         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8612                 switch (c) {
8613                 case 'N':
8614                         show_sa_errors = 0;
8615                         break;
8616                 case 'o':
8617                         opcode = strtoul(optarg, &endptr, 0);
8618                         if (*endptr != '\0') {
8619                                 warnx("Invalid opcode \"%s\", must be a number",
8620                                       optarg);
8621                                 retval = 1;
8622                                 goto bailout;
8623                         }
8624                         if (opcode > 0xff) {
8625                                 warnx("Invalid opcode 0x%#x, must be between"
8626                                       "0 and 0xff inclusive", opcode);
8627                                 retval = 1;
8628                                 goto bailout;
8629                         }
8630                         opcode_set = 1;
8631                         break;
8632                 case 's':
8633                         service_action = strtoul(optarg, &endptr, 0);
8634                         if (*endptr != '\0') {
8635                                 warnx("Invalid service action \"%s\", must "
8636                                       "be a number", optarg);
8637                                 retval = 1;
8638                                 goto bailout;
8639                         }
8640                         if (service_action > 0xffff) {
8641                                 warnx("Invalid service action 0x%#x, must "
8642                                       "be between 0 and 0xffff inclusive",
8643                                       service_action);
8644                                 retval = 1;
8645                         }
8646                         sa_set = 1;
8647                         break;
8648                 case 'T':
8649                         td_set = 1;
8650                         break;
8651                 default:
8652                         break;
8653                 }
8654         }
8655
8656         if ((sa_set != 0)
8657          && (opcode_set == 0)) {
8658                 warnx("You must specify an opcode with -o if a service "
8659                       "action is given");
8660                 retval = 1;
8661                 goto bailout;
8662         }
8663         retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
8664                                 sa_set, service_action, td_set, task_attr,
8665                                 retry_count, timeout, verbosemode, &valid_len,
8666                                 &buf);
8667         if (retval != 0)
8668                 goto bailout;
8669
8670         if ((opcode_set != 0)
8671          || (sa_set != 0)) {
8672                 retval = scsiprintoneopcode(device, opcode, sa_set,
8673                                             service_action, buf, valid_len);
8674         } else {
8675                 retval = scsiprintopcodes(device, td_set, buf, valid_len);
8676         }
8677
8678 bailout:
8679         free(buf);
8680
8681         return (retval);
8682 }
8683
8684 #endif /* MINIMALISTIC */
8685
8686 static int
8687 scsireprobe(struct cam_device *device)
8688 {
8689         union ccb *ccb;
8690         int retval = 0;
8691
8692         ccb = cam_getccb(device);
8693
8694         if (ccb == NULL) {
8695                 warnx("%s: error allocating ccb", __func__);
8696                 return (1);
8697         }
8698
8699         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8700
8701         ccb->ccb_h.func_code = XPT_REPROBE_LUN;
8702
8703         if (cam_send_ccb(device, ccb) < 0) {
8704                 warn("error sending XPT_REPROBE_LUN CCB");
8705                 retval = 1;
8706                 goto bailout;
8707         }
8708
8709         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8710                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
8711                 retval = 1;
8712                 goto bailout;
8713         }
8714
8715 bailout:
8716         cam_freeccb(ccb);
8717
8718         return (retval);
8719 }
8720
8721 void
8722 usage(int printlong)
8723 {
8724
8725         fprintf(printlong ? stdout : stderr,
8726 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
8727 "        camcontrol devlist    [-b] [-v]\n"
8728 #ifndef MINIMALISTIC
8729 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8730 "        camcontrol tur        [dev_id][generic args]\n"
8731 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
8732 "        camcontrol identify   [dev_id][generic args] [-v]\n"
8733 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8734 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8735 "                              [-q] [-s]\n"
8736 "        camcontrol start      [dev_id][generic args]\n"
8737 "        camcontrol stop       [dev_id][generic args]\n"
8738 "        camcontrol load       [dev_id][generic args]\n"
8739 "        camcontrol eject      [dev_id][generic args]\n"
8740 "        camcontrol reprobe    [dev_id][generic args]\n"
8741 #endif /* MINIMALISTIC */
8742 "        camcontrol rescan     <all | bus[:target:lun]>\n"
8743 "        camcontrol reset      <all | bus[:target:lun]>\n"
8744 #ifndef MINIMALISTIC
8745 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
8746 "                              [-q][-s][-S offset][-X]\n"
8747 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
8748 "                              [-P pagectl][-e | -b][-d]\n"
8749 "        camcontrol cmd        [dev_id][generic args]\n"
8750 "                              <-a cmd [args] | -c cmd [args]>\n"
8751 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8752 "        camcontrol smpcmd     [dev_id][generic args]\n"
8753 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
8754 "        camcontrol smprg      [dev_id][generic args][-l]\n"
8755 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
8756 "                              [-o operation][-d name][-m rate][-M rate]\n"
8757 "                              [-T pp_timeout][-a enable|disable]\n"
8758 "                              [-A enable|disable][-s enable|disable]\n"
8759 "                              [-S enable|disable]\n"
8760 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8761 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8762 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
8763 "                              <all|bus[:target[:lun]]|off>\n"
8764 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
8765 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
8766 "                              [-D <enable|disable>][-M mode][-O offset]\n"
8767 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
8768 "                              [-U][-W bus_width]\n"
8769 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
8770 "        camcontrol sanitize   [dev_id][generic args]\n"
8771 "                              [-a overwrite|block|crypto|exitfailure]\n"
8772 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8773 "                              [-y]\n"
8774 "        camcontrol idle       [dev_id][generic args][-t time]\n"
8775 "        camcontrol standby    [dev_id][generic args][-t time]\n"
8776 "        camcontrol sleep      [dev_id][generic args]\n"
8777 "        camcontrol apm        [dev_id][generic args][-l level]\n"
8778 "        camcontrol aam        [dev_id][generic args][-l level]\n"
8779 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
8780 "                              [-s][-y]\n"
8781 "        camcontrol security   [dev_id][generic args]\n"
8782 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8783 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8784 "                              [-U <user|master>] [-y]\n"
8785 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8786 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
8787 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
8788 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8789 "                              [-s scope][-S][-T type][-U]\n"
8790 "        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
8791 "                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
8792 "                              [-p part][-s start][-T type][-V vol]\n"
8793 "        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
8794 "                              [-N][-T]\n"
8795 #endif /* MINIMALISTIC */
8796 "        camcontrol help\n");
8797         if (!printlong)
8798                 return;
8799 #ifndef MINIMALISTIC
8800         fprintf(stdout,
8801 "Specify one of the following options:\n"
8802 "devlist     list all CAM devices\n"
8803 "periphlist  list all CAM peripheral drivers attached to a device\n"
8804 "tur         send a test unit ready to the named device\n"
8805 "inquiry     send a SCSI inquiry command to the named device\n"
8806 "identify    send a ATA identify command to the named device\n"
8807 "reportluns  send a SCSI report luns command to the device\n"
8808 "readcap     send a SCSI read capacity command to the device\n"
8809 "start       send a Start Unit command to the device\n"
8810 "stop        send a Stop Unit command to the device\n"
8811 "load        send a Start Unit command to the device with the load bit set\n"
8812 "eject       send a Stop Unit command to the device with the eject bit set\n"
8813 "reprobe     update capacity information of the given device\n"
8814 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
8815 "reset       reset all busses, the given bus, or bus:target:lun\n"
8816 "defects     read the defect list of the specified device\n"
8817 "modepage    display or edit (-e) the given mode page\n"
8818 "cmd         send the given SCSI command, may need -i or -o as well\n"
8819 "smpcmd      send the given SMP command, requires -o and -i\n"
8820 "smprg       send the SMP Report General command\n"
8821 "smppc       send the SMP PHY Control command, requires -p\n"
8822 "smpphylist  display phys attached to a SAS expander\n"
8823 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
8824 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
8825 "tags        report or set the number of transaction slots for a device\n"
8826 "negotiate   report or set device negotiation parameters\n"
8827 "format      send the SCSI FORMAT UNIT command to the named device\n"
8828 "sanitize    send the SCSI SANITIZE command to the named device\n"
8829 "idle        send the ATA IDLE command to the named device\n"
8830 "standby     send the ATA STANDBY command to the named device\n"
8831 "sleep       send the ATA SLEEP command to the named device\n"
8832 "fwdownload  program firmware of the named device with the given image\n"
8833 "security    report or send ATA security commands to the named device\n"
8834 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8835 "attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
8836 "opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
8837 "help        this message\n"
8838 "Device Identifiers:\n"
8839 "bus:target        specify the bus and target, lun defaults to 0\n"
8840 "bus:target:lun    specify the bus, target and lun\n"
8841 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
8842 "Generic arguments:\n"
8843 "-v                be verbose, print out sense information\n"
8844 "-t timeout        command timeout in seconds, overrides default timeout\n"
8845 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
8846 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
8847 "-E                have the kernel attempt to perform SCSI error recovery\n"
8848 "-C count          specify the SCSI command retry count (needs -E to work)\n"
8849 "-Q task_attr      specify ordered, simple or head tag type for SCSI cmds\n"
8850 "modepage arguments:\n"
8851 "-l                list all available mode pages\n"
8852 "-m page           specify the mode page to view or edit\n"
8853 "-e                edit the specified mode page\n"
8854 "-b                force view to binary mode\n"
8855 "-d                disable block descriptors for mode sense\n"
8856 "-P pgctl          page control field 0-3\n"
8857 "defects arguments:\n"
8858 "-f format         specify defect list format (block, bfi or phys)\n"
8859 "-G                get the grown defect list\n"
8860 "-P                get the permanent defect list\n"
8861 "inquiry arguments:\n"
8862 "-D                get the standard inquiry data\n"
8863 "-S                get the serial number\n"
8864 "-R                get the transfer rate, etc.\n"
8865 "reportluns arguments:\n"
8866 "-c                only report a count of available LUNs\n"
8867 "-l                only print out luns, and not a count\n"
8868 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
8869 "readcap arguments\n"
8870 "-b                only report the blocksize\n"
8871 "-h                human readable device size, base 2\n"
8872 "-H                human readable device size, base 10\n"
8873 "-N                print the number of blocks instead of last block\n"
8874 "-q                quiet, print numbers only\n"
8875 "-s                only report the last block/device size\n"
8876 "cmd arguments:\n"
8877 "-c cdb [args]     specify the SCSI CDB\n"
8878 "-i len fmt        specify input data and input data format\n"
8879 "-o len fmt [args] specify output data and output data fmt\n"
8880 "smpcmd arguments:\n"
8881 "-r len fmt [args] specify the SMP command to be sent\n"
8882 "-R len fmt [args] specify SMP response format\n"
8883 "smprg arguments:\n"
8884 "-l                specify the long response format\n"
8885 "smppc arguments:\n"
8886 "-p phy            specify the PHY to operate on\n"
8887 "-l                specify the long request/response format\n"
8888 "-o operation      specify the phy control operation\n"
8889 "-d name           set the attached device name\n"
8890 "-m rate           set the minimum physical link rate\n"
8891 "-M rate           set the maximum physical link rate\n"
8892 "-T pp_timeout     set the partial pathway timeout value\n"
8893 "-a enable|disable enable or disable SATA slumber\n"
8894 "-A enable|disable enable or disable SATA partial phy power\n"
8895 "-s enable|disable enable or disable SAS slumber\n"
8896 "-S enable|disable enable or disable SAS partial phy power\n"
8897 "smpphylist arguments:\n"
8898 "-l                specify the long response format\n"
8899 "-q                only print phys with attached devices\n"
8900 "smpmaninfo arguments:\n"
8901 "-l                specify the long response format\n"
8902 "debug arguments:\n"
8903 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
8904 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
8905 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
8906 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
8907 "tags arguments:\n"
8908 "-N tags           specify the number of tags to use for this device\n"
8909 "-q                be quiet, don't report the number of tags\n"
8910 "-v                report a number of tag-related parameters\n"
8911 "negotiate arguments:\n"
8912 "-a                send a test unit ready after negotiation\n"
8913 "-c                report/set current negotiation settings\n"
8914 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
8915 "-M mode           set ATA mode\n"
8916 "-O offset         set command delay offset\n"
8917 "-q                be quiet, don't report anything\n"
8918 "-R syncrate       synchronization rate in MHz\n"
8919 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
8920 "-U                report/set user negotiation settings\n"
8921 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
8922 "-v                also print a Path Inquiry CCB for the controller\n"
8923 "format arguments:\n"
8924 "-q                be quiet, don't print status messages\n"
8925 "-r                run in report only mode\n"
8926 "-w                don't send immediate format command\n"
8927 "-y                don't ask any questions\n"
8928 "sanitize arguments:\n"
8929 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
8930 "-c passes         overwrite passes to perform (1 to 31)\n"
8931 "-I                invert overwrite pattern after each pass\n"
8932 "-P pattern        path to overwrite pattern file\n"
8933 "-q                be quiet, don't print status messages\n"
8934 "-r                run in report only mode\n"
8935 "-U                run operation in unrestricted completion exit mode\n"
8936 "-w                don't send immediate sanitize command\n"
8937 "-y                don't ask any questions\n"
8938 "idle/standby arguments:\n"
8939 "-t <arg>          number of seconds before respective state.\n"
8940 "fwdownload arguments:\n"
8941 "-f fw_image       path to firmware image file\n"
8942 "-q                don't print informational messages, only errors\n"
8943 "-s                run in simulation mode\n"
8944 "-v                print info for every firmware segment sent to device\n"
8945 "-y                don't ask any questions\n"
8946 "security arguments:\n"
8947 "-d pwd            disable security using the given password for the selected\n"
8948 "                  user\n"
8949 "-e pwd            erase the device using the given pwd for the selected user\n"
8950 "-f                freeze the security configuration of the specified device\n"
8951 "-h pwd            enhanced erase the device using the given pwd for the\n"
8952 "                  selected user\n"
8953 "-k pwd            unlock the device using the given pwd for the selected\n"
8954 "                  user\n"
8955 "-l <high|maximum> specifies which security level to set: high or maximum\n"
8956 "-q                be quiet, do not print any status messages\n"
8957 "-s pwd            password the device (enable security) using the given\n"
8958 "                  pwd for the selected user\n"
8959 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
8960 "-U <user|master>  specifies which user to set: user or master\n"
8961 "-y                don't ask any questions\n"
8962 "hpa arguments:\n"
8963 "-f                freeze the HPA configuration of the device\n"
8964 "-l                lock the HPA configuration of the device\n"
8965 "-P                make the HPA max sectors persist\n"
8966 "-p pwd            Set the HPA configuration password required for unlock\n"
8967 "                  calls\n"
8968 "-q                be quiet, do not print any status messages\n"
8969 "-s sectors        configures the maximum user accessible sectors of the\n"
8970 "                  device\n"
8971 "-U pwd            unlock the HPA configuration of the device\n"
8972 "-y                don't ask any questions\n"
8973 "persist arguments:\n"
8974 "-i action         specify read_keys, read_reservation, report_cap, or\n"
8975 "                  read_full_status\n"
8976 "-o action         specify register, register_ignore, reserve, release,\n"
8977 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
8978 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
8979 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8980 "-k key            specify the Reservation Key\n"
8981 "-K sa_key         specify the Service Action Reservation Key\n"
8982 "-p                set the Activate Persist Through Power Loss bit\n"
8983 "-R rtp            specify the Relative Target Port\n"
8984 "-s scope          specify the scope: lun, extent, element or a number\n"
8985 "-S                specify Transport ID for register, requires -I\n"
8986 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8987 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8988 "-U                unregister the current initiator for register_move\n"
8989 "attrib arguments:\n"
8990 "-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
8991 "                  supp_attr\n"
8992 "-w attr           specify an attribute to write, one -w argument per attr\n"
8993 "-a attr_num       only display this attribute number\n"
8994 "-c                get cached attributes\n"
8995 "-e elem_addr      request attributes for the given element in a changer\n"
8996 "-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
8997 "                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
8998 "                  field_none, field_desc, field_num, field_size, field_rw\n"
8999 "-p partition      request attributes for the given partition\n"
9000 "-s start_attr     request attributes starting at the given number\n"
9001 "-T elem_type      specify the element type (used with -e)\n"
9002 "-V logical_vol    specify the logical volume ID\n"
9003 "opcodes arguments:\n"
9004 "-o opcode         specify the individual opcode to list\n"
9005 "-s service_action specify the service action for the opcode\n"
9006 "-N                do not return SCSI error for unsupported SA\n"
9007 "-T                request nominal and recommended timeout values\n"
9008 );
9009 #endif /* MINIMALISTIC */
9010 }
9011
9012 int
9013 main(int argc, char **argv)
9014 {
9015         int c;
9016         char *device = NULL;
9017         int unit = 0;
9018         struct cam_device *cam_dev = NULL;
9019         int timeout = 0, retry_count = 1;
9020         camcontrol_optret optreturn;
9021         char *tstr;
9022         const char *mainopt = "C:En:Q:t:u:v";
9023         const char *subopt = NULL;
9024         char combinedopt[256];
9025         int error = 0, optstart = 2;
9026         int task_attr = MSG_SIMPLE_Q_TAG;
9027         int devopen = 1;
9028 #ifndef MINIMALISTIC
9029         path_id_t bus;
9030         target_id_t target;
9031         lun_id_t lun;
9032 #endif /* MINIMALISTIC */
9033
9034         cmdlist = CAM_CMD_NONE;
9035         arglist = CAM_ARG_NONE;
9036
9037         if (argc < 2) {
9038                 usage(0);
9039                 exit(1);
9040         }
9041
9042         /*
9043          * Get the base option.
9044          */
9045         optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
9046
9047         if (optreturn == CC_OR_AMBIGUOUS) {
9048                 warnx("ambiguous option %s", argv[1]);
9049                 usage(0);
9050                 exit(1);
9051         } else if (optreturn == CC_OR_NOT_FOUND) {
9052                 warnx("option %s not found", argv[1]);
9053                 usage(0);
9054                 exit(1);
9055         }
9056
9057         /*
9058          * Ahh, getopt(3) is a pain.
9059          *
9060          * This is a gross hack.  There really aren't many other good
9061          * options (excuse the pun) for parsing options in a situation like
9062          * this.  getopt is kinda braindead, so you end up having to run
9063          * through the options twice, and give each invocation of getopt
9064          * the option string for the other invocation.
9065          *
9066          * You would think that you could just have two groups of options.
9067          * The first group would get parsed by the first invocation of
9068          * getopt, and the second group would get parsed by the second
9069          * invocation of getopt.  It doesn't quite work out that way.  When
9070          * the first invocation of getopt finishes, it leaves optind pointing
9071          * to the argument _after_ the first argument in the second group.
9072          * So when the second invocation of getopt comes around, it doesn't
9073          * recognize the first argument it gets and then bails out.
9074          *
9075          * A nice alternative would be to have a flag for getopt that says
9076          * "just keep parsing arguments even when you encounter an unknown
9077          * argument", but there isn't one.  So there's no real clean way to
9078          * easily parse two sets of arguments without having one invocation
9079          * of getopt know about the other.
9080          *
9081          * Without this hack, the first invocation of getopt would work as
9082          * long as the generic arguments are first, but the second invocation
9083          * (in the subfunction) would fail in one of two ways.  In the case
9084          * where you don't set optreset, it would fail because optind may be
9085          * pointing to the argument after the one it should be pointing at.
9086          * In the case where you do set optreset, and reset optind, it would
9087          * fail because getopt would run into the first set of options, which
9088          * it doesn't understand.
9089          *
9090          * All of this would "sort of" work if you could somehow figure out
9091          * whether optind had been incremented one option too far.  The
9092          * mechanics of that, however, are more daunting than just giving
9093          * both invocations all of the expect options for either invocation.
9094          *
9095          * Needless to say, I wouldn't mind if someone invented a better
9096          * (non-GPL!) command line parsing interface than getopt.  I
9097          * wouldn't mind if someone added more knobs to getopt to make it
9098          * work better.  Who knows, I may talk myself into doing it someday,
9099          * if the standards weenies let me.  As it is, it just leads to
9100          * hackery like this and causes people to avoid it in some cases.
9101          *
9102          * KDM, September 8th, 1998
9103          */
9104         if (subopt != NULL)
9105                 sprintf(combinedopt, "%s%s", mainopt, subopt);
9106         else
9107                 sprintf(combinedopt, "%s", mainopt);
9108
9109         /*
9110          * For these options we do not parse optional device arguments and
9111          * we do not open a passthrough device.
9112          */
9113         if ((cmdlist == CAM_CMD_RESCAN)
9114          || (cmdlist == CAM_CMD_RESET)
9115          || (cmdlist == CAM_CMD_DEVTREE)
9116          || (cmdlist == CAM_CMD_USAGE)
9117          || (cmdlist == CAM_CMD_DEBUG))
9118                 devopen = 0;
9119
9120 #ifndef MINIMALISTIC
9121         if ((devopen == 1)
9122          && (argc > 2 && argv[2][0] != '-')) {
9123                 char name[30];
9124                 int rv;
9125
9126                 if (isdigit(argv[2][0])) {
9127                         /* device specified as bus:target[:lun] */
9128                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9129                         if (rv < 2)
9130                                 errx(1, "numeric device specification must "
9131                                      "be either bus:target, or "
9132                                      "bus:target:lun");
9133                         /* default to 0 if lun was not specified */
9134                         if ((arglist & CAM_ARG_LUN) == 0) {
9135                                 lun = 0;
9136                                 arglist |= CAM_ARG_LUN;
9137                         }
9138                         optstart++;
9139                 } else {
9140                         if (cam_get_device(argv[2], name, sizeof name, &unit)
9141                             == -1)
9142                                 errx(1, "%s", cam_errbuf);
9143                         device = strdup(name);
9144                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9145                         optstart++;
9146                 }
9147         }
9148 #endif /* MINIMALISTIC */
9149         /*
9150          * Start getopt processing at argv[2/3], since we've already
9151          * accepted argv[1..2] as the command name, and as a possible
9152          * device name.
9153          */
9154         optind = optstart;
9155
9156         /*
9157          * Now we run through the argument list looking for generic
9158          * options, and ignoring options that possibly belong to
9159          * subfunctions.
9160          */
9161         while ((c = getopt(argc, argv, combinedopt))!= -1){
9162                 switch(c) {
9163                         case 'C':
9164                                 retry_count = strtol(optarg, NULL, 0);
9165                                 if (retry_count < 0)
9166                                         errx(1, "retry count %d is < 0",
9167                                              retry_count);
9168                                 arglist |= CAM_ARG_RETRIES;
9169                                 break;
9170                         case 'E':
9171                                 arglist |= CAM_ARG_ERR_RECOVER;
9172                                 break;
9173                         case 'n':
9174                                 arglist |= CAM_ARG_DEVICE;
9175                                 tstr = optarg;
9176                                 while (isspace(*tstr) && (*tstr != '\0'))
9177                                         tstr++;
9178                                 device = (char *)strdup(tstr);
9179                                 break;
9180                         case 'Q': {
9181                                 char *endptr;
9182                                 int table_entry = 0;
9183
9184                                 tstr = optarg;
9185                                 while (isspace(*tstr) && (*tstr != '\0'))
9186                                         tstr++;
9187                                 if (isdigit(*tstr)) {
9188                                         task_attr = strtol(tstr, &endptr, 0);
9189                                         if (*endptr != '\0') {
9190                                                 errx(1, "Invalid queue option "
9191                                                     "%s", tstr);
9192                                         }
9193                                 } else {
9194                                         size_t table_size;
9195                                         scsi_nv_status status;
9196
9197                                         table_size = sizeof(task_attrs) /
9198                                                      sizeof(task_attrs[0]);
9199                                         status = scsi_get_nv(task_attrs,
9200                                             table_size, tstr, &table_entry,
9201                                             SCSI_NV_FLAG_IG_CASE);
9202                                         if (status == SCSI_NV_FOUND)
9203                                                 task_attr = task_attrs[
9204                                                     table_entry].value;
9205                                         else {
9206                                                 errx(1, "%s option %s",
9207                                                   (status == SCSI_NV_AMBIGUOUS)?
9208                                                     "ambiguous" : "invalid",
9209                                                     tstr);
9210                                         }
9211                                 }
9212                                 break;
9213                         }
9214                         case 't':
9215                                 timeout = strtol(optarg, NULL, 0);
9216                                 if (timeout < 0)
9217                                         errx(1, "invalid timeout %d", timeout);
9218                                 /* Convert the timeout from seconds to ms */
9219                                 timeout *= 1000;
9220                                 arglist |= CAM_ARG_TIMEOUT;
9221                                 break;
9222                         case 'u':
9223                                 arglist |= CAM_ARG_UNIT;
9224                                 unit = strtol(optarg, NULL, 0);
9225                                 break;
9226                         case 'v':
9227                                 arglist |= CAM_ARG_VERBOSE;
9228                                 break;
9229                         default:
9230                                 break;
9231                 }
9232         }
9233
9234 #ifndef MINIMALISTIC
9235         /*
9236          * For most commands we'll want to open the passthrough device
9237          * associated with the specified device.  In the case of the rescan
9238          * commands, we don't use a passthrough device at all, just the
9239          * transport layer device.
9240          */
9241         if (devopen == 1) {
9242                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
9243                  && (((arglist & CAM_ARG_DEVICE) == 0)
9244                   || ((arglist & CAM_ARG_UNIT) == 0))) {
9245                         errx(1, "subcommand \"%s\" requires a valid device "
9246                              "identifier", argv[1]);
9247                 }
9248
9249                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
9250                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
9251                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
9252                      == NULL)
9253                         errx(1,"%s", cam_errbuf);
9254         }
9255 #endif /* MINIMALISTIC */
9256
9257         /*
9258          * Reset optind to 2, and reset getopt, so these routines can parse
9259          * the arguments again.
9260          */
9261         optind = optstart;
9262         optreset = 1;
9263
9264         switch(cmdlist) {
9265 #ifndef MINIMALISTIC
9266                 case CAM_CMD_DEVLIST:
9267                         error = getdevlist(cam_dev);
9268                         break;
9269                 case CAM_CMD_HPA:
9270                         error = atahpa(cam_dev, retry_count, timeout,
9271                                        argc, argv, combinedopt);
9272                         break;
9273 #endif /* MINIMALISTIC */
9274                 case CAM_CMD_DEVTREE:
9275                         error = getdevtree(argc, argv, combinedopt);
9276                         break;
9277 #ifndef MINIMALISTIC
9278                 case CAM_CMD_TUR:
9279                         error = testunitready(cam_dev, task_attr, retry_count,
9280                             timeout, 0);
9281                         break;
9282                 case CAM_CMD_INQUIRY:
9283                         error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
9284                                               task_attr, retry_count, timeout);
9285                         break;
9286                 case CAM_CMD_IDENTIFY:
9287                         error = ataidentify(cam_dev, retry_count, timeout);
9288                         break;
9289                 case CAM_CMD_STARTSTOP:
9290                         error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
9291                                           arglist & CAM_ARG_EJECT, task_attr,
9292                                           retry_count, timeout);
9293                         break;
9294 #endif /* MINIMALISTIC */
9295                 case CAM_CMD_RESCAN:
9296                         error = dorescan_or_reset(argc, argv, 1);
9297                         break;
9298                 case CAM_CMD_RESET:
9299                         error = dorescan_or_reset(argc, argv, 0);
9300                         break;
9301 #ifndef MINIMALISTIC
9302                 case CAM_CMD_READ_DEFECTS:
9303                         error = readdefects(cam_dev, argc, argv, combinedopt,
9304                                             task_attr, retry_count, timeout);
9305                         break;
9306                 case CAM_CMD_MODE_PAGE:
9307                         modepage(cam_dev, argc, argv, combinedopt,
9308                                  task_attr, retry_count, timeout);
9309                         break;
9310                 case CAM_CMD_SCSI_CMD:
9311                         error = scsicmd(cam_dev, argc, argv, combinedopt,
9312                                         task_attr, retry_count, timeout);
9313                         break;
9314                 case CAM_CMD_SMP_CMD:
9315                         error = smpcmd(cam_dev, argc, argv, combinedopt,
9316                                        retry_count, timeout);
9317                         break;
9318                 case CAM_CMD_SMP_RG:
9319                         error = smpreportgeneral(cam_dev, argc, argv,
9320                                                  combinedopt, retry_count,
9321                                                  timeout);
9322                         break;
9323                 case CAM_CMD_SMP_PC:
9324                         error = smpphycontrol(cam_dev, argc, argv, combinedopt, 
9325                                               retry_count, timeout);
9326                         break;
9327                 case CAM_CMD_SMP_PHYLIST:
9328                         error = smpphylist(cam_dev, argc, argv, combinedopt,
9329                                            retry_count, timeout);
9330                         break;
9331                 case CAM_CMD_SMP_MANINFO:
9332                         error = smpmaninfo(cam_dev, argc, argv, combinedopt,
9333                                            retry_count, timeout);
9334                         break;
9335                 case CAM_CMD_DEBUG:
9336                         error = camdebug(argc, argv, combinedopt);
9337                         break;
9338                 case CAM_CMD_TAG:
9339                         error = tagcontrol(cam_dev, argc, argv, combinedopt);
9340                         break;
9341                 case CAM_CMD_RATE:
9342                         error = ratecontrol(cam_dev, task_attr, retry_count,
9343                                             timeout, argc, argv, combinedopt);
9344                         break;
9345                 case CAM_CMD_FORMAT:
9346                         error = scsiformat(cam_dev, argc, argv,
9347                                            combinedopt, task_attr, retry_count,
9348                                            timeout);
9349                         break;
9350                 case CAM_CMD_REPORTLUNS:
9351                         error = scsireportluns(cam_dev, argc, argv,
9352                                                combinedopt, task_attr,
9353                                                retry_count, timeout);
9354                         break;
9355                 case CAM_CMD_READCAP:
9356                         error = scsireadcapacity(cam_dev, argc, argv,
9357                                                  combinedopt, task_attr,
9358                                                  retry_count, timeout);
9359                         break;
9360                 case CAM_CMD_IDLE:
9361                 case CAM_CMD_STANDBY:
9362                 case CAM_CMD_SLEEP:
9363                         error = atapm(cam_dev, argc, argv,
9364                                       combinedopt, retry_count, timeout);
9365                         break;
9366                 case CAM_CMD_APM:
9367                 case CAM_CMD_AAM:
9368                         error = ataaxm(cam_dev, argc, argv,
9369                                       combinedopt, retry_count, timeout);
9370                         break;
9371                 case CAM_CMD_SECURITY:
9372                         error = atasecurity(cam_dev, retry_count, timeout,
9373                                             argc, argv, combinedopt);
9374                         break;
9375                 case CAM_CMD_DOWNLOAD_FW:
9376                         error = fwdownload(cam_dev, argc, argv, combinedopt,
9377                             arglist & CAM_ARG_VERBOSE, task_attr, retry_count,
9378                             timeout);
9379                         break;
9380                 case CAM_CMD_SANITIZE:
9381                         error = scsisanitize(cam_dev, argc, argv,
9382                                              combinedopt, task_attr,
9383                                              retry_count, timeout);
9384                         break;
9385                 case CAM_CMD_PERSIST:
9386                         error = scsipersist(cam_dev, argc, argv, combinedopt,
9387                             task_attr, retry_count, timeout,
9388                             arglist & CAM_ARG_VERBOSE,
9389                             arglist & CAM_ARG_ERR_RECOVER);
9390                         break;
9391                 case CAM_CMD_ATTRIB:
9392                         error = scsiattrib(cam_dev, argc, argv, combinedopt,
9393                             task_attr, retry_count, timeout,
9394                             arglist & CAM_ARG_VERBOSE,
9395                             arglist & CAM_ARG_ERR_RECOVER);
9396                         break;
9397                 case CAM_CMD_OPCODES:
9398                         error = scsiopcodes(cam_dev, argc, argv, combinedopt,
9399                             task_attr, retry_count, timeout,
9400                             arglist & CAM_ARG_VERBOSE);
9401                         break;
9402                 case CAM_CMD_REPROBE:
9403                         error = scsireprobe(cam_dev);
9404                         break;
9405
9406 #endif /* MINIMALISTIC */
9407                 case CAM_CMD_USAGE:
9408                         usage(1);
9409                         break;
9410                 default:
9411                         usage(0);
9412                         error = 1;
9413                         break;
9414         }
9415
9416         if (cam_dev != NULL)
9417                 cam_close_device(cam_dev);
9418
9419         exit(error);
9420 }