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