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