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