]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sbin/camcontrol/camcontrol.c
MFC r298758:
[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                 retval = -1;
4996                 goto bailout;
4997         }
4998
4999         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5000                 if (verbosemode != 0)
5001                         cam_error_print(dev, ccb, CAM_ESF_ALL,
5002                                         CAM_EPF_ALL, stderr);
5003                 retval = -1;
5004                 goto bailout;
5005         }
5006
5007         for (i = 0; i < sup_pages.length; i++) {
5008                 if (sup_pages.list[i] == page_id) {
5009                         retval = 1;
5010                         goto bailout;
5011                 }
5012         }
5013 bailout:
5014         if (ccb != NULL)
5015                 cam_freeccb(ccb);
5016         
5017         return (retval);
5018 }
5019
5020 /*
5021  * devtype is filled in with the type of device.
5022  * Returns 0 for success, non-zero for failure.
5023  */
5024 int
5025 get_device_type(struct cam_device *dev, int retry_count, int timeout,
5026                     int verbosemode, camcontrol_devtype *devtype)
5027 {
5028         struct ccb_getdev cgd;
5029         int retval = 0;
5030
5031         retval = get_cgd(dev, &cgd);
5032         if (retval != 0)
5033                 goto bailout;
5034
5035         switch (cgd.protocol) {
5036         case PROTO_SCSI:
5037                 break;
5038         case PROTO_ATA:
5039         case PROTO_ATAPI:
5040         case PROTO_SATAPM:
5041                 *devtype = CC_DT_ATA;
5042                 goto bailout;
5043                 break; /*NOTREACHED*/
5044         default:
5045                 *devtype = CC_DT_UNKNOWN;
5046                 goto bailout; 
5047                 break; /*NOTREACHED*/
5048         }
5049
5050         /*
5051          * Check for the ATA Information VPD page (0x89).  If this is an
5052          * ATA device behind a SCSI to ATA translation layer, this VPD page
5053          * should be present.
5054          *
5055          * If that VPD page isn't present, or we get an error back from the
5056          * INQUIRY command, we'll just treat it as a normal SCSI device.
5057          */
5058         retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5059                                   timeout, verbosemode);
5060         if (retval == 1)
5061                 *devtype = CC_DT_ATA_BEHIND_SCSI;
5062         else
5063                 *devtype = CC_DT_SCSI;
5064
5065         retval = 0;
5066
5067 bailout:
5068         return (retval);
5069 }
5070
5071 void
5072 build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5073     uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5074     uint16_t sector_count, uint64_t lba, uint8_t command, uint8_t *data_ptr,
5075     uint16_t dxfer_len, uint8_t sense_len, uint32_t timeout,
5076     int is48bit, camcontrol_devtype devtype)
5077 {
5078         if (devtype == CC_DT_ATA) {
5079                 cam_fill_ataio(&ccb->ataio,
5080                     /*retries*/ retry_count,
5081                     /*cbfcnp*/ NULL,
5082                     /*flags*/ flags,
5083                     /*tag_action*/ tag_action,
5084                     /*data_ptr*/ data_ptr,
5085                     /*dxfer_len*/ dxfer_len,
5086                     /*timeout*/ timeout);
5087                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5088                         ata_48bit_cmd(&ccb->ataio, command, features, lba,
5089                             sector_count);
5090                 else
5091                         ata_28bit_cmd(&ccb->ataio, command, features, lba,
5092                             sector_count);
5093         } else {
5094                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5095                         protocol |= AP_EXTEND;
5096
5097                 scsi_ata_pass_16(&ccb->csio,
5098                     /*retries*/ retry_count,
5099                     /*cbfcnp*/ NULL,
5100                     /*flags*/ flags,
5101                     /*tag_action*/ tag_action,
5102                     /*protocol*/ protocol,
5103                     /*ata_flags*/ ata_flags,
5104                     /*features*/ features,
5105                     /*sector_count*/ sector_count, 
5106                     /*lba*/ lba,
5107                     /*command*/ command,
5108                     /*control*/ 0,
5109                     /*data_ptr*/ data_ptr,
5110                     /*dxfer_len*/ dxfer_len,
5111                     /*sense_len*/ sense_len,
5112                     /*timeout*/ timeout);
5113         }
5114 }
5115
5116
5117 static void
5118 cpi_print(struct ccb_pathinq *cpi)
5119 {
5120         char adapter_str[1024];
5121         int i;
5122
5123         snprintf(adapter_str, sizeof(adapter_str),
5124                  "%s%d:", cpi->dev_name, cpi->unit_number);
5125
5126         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5127                 cpi->version_num);
5128
5129         for (i = 1; i < 0xff; i = i << 1) {
5130                 const char *str;
5131
5132                 if ((i & cpi->hba_inquiry) == 0)
5133                         continue;
5134
5135                 fprintf(stdout, "%s supports ", adapter_str);
5136
5137                 switch(i) {
5138                 case PI_MDP_ABLE:
5139                         str = "MDP message";
5140                         break;
5141                 case PI_WIDE_32:
5142                         str = "32 bit wide SCSI";
5143                         break;
5144                 case PI_WIDE_16:
5145                         str = "16 bit wide SCSI";
5146                         break;
5147                 case PI_SDTR_ABLE:
5148                         str = "SDTR message";
5149                         break;
5150                 case PI_LINKED_CDB:
5151                         str = "linked CDBs";
5152                         break;
5153                 case PI_TAG_ABLE:
5154                         str = "tag queue messages";
5155                         break;
5156                 case PI_SOFT_RST:
5157                         str = "soft reset alternative";
5158                         break;
5159                 case PI_SATAPM:
5160                         str = "SATA Port Multiplier";
5161                         break;
5162                 default:
5163                         str = "unknown PI bit set";
5164                         break;
5165                 }
5166                 fprintf(stdout, "%s\n", str);
5167         }
5168
5169         for (i = 1; i < 0xff; i = i << 1) {
5170                 const char *str;
5171
5172                 if ((i & cpi->hba_misc) == 0)
5173                         continue;
5174
5175                 fprintf(stdout, "%s ", adapter_str);
5176
5177                 switch(i) {
5178                 case PIM_SCANHILO:
5179                         str = "bus scans from high ID to low ID";
5180                         break;
5181                 case PIM_NOREMOVE:
5182                         str = "removable devices not included in scan";
5183                         break;
5184                 case PIM_NOINITIATOR:
5185                         str = "initiator role not supported";
5186                         break;
5187                 case PIM_NOBUSRESET:
5188                         str = "user has disabled initial BUS RESET or"
5189                               " controller is in target/mixed mode";
5190                         break;
5191                 case PIM_NO_6_BYTE:
5192                         str = "do not send 6-byte commands";
5193                         break;
5194                 case PIM_SEQSCAN:
5195                         str = "scan bus sequentially";
5196                         break;
5197                 default:
5198                         str = "unknown PIM bit set";
5199                         break;
5200                 }
5201                 fprintf(stdout, "%s\n", str);
5202         }
5203
5204         for (i = 1; i < 0xff; i = i << 1) {
5205                 const char *str;
5206
5207                 if ((i & cpi->target_sprt) == 0)
5208                         continue;
5209
5210                 fprintf(stdout, "%s supports ", adapter_str);
5211                 switch(i) {
5212                 case PIT_PROCESSOR:
5213                         str = "target mode processor mode";
5214                         break;
5215                 case PIT_PHASE:
5216                         str = "target mode phase cog. mode";
5217                         break;
5218                 case PIT_DISCONNECT:
5219                         str = "disconnects in target mode";
5220                         break;
5221                 case PIT_TERM_IO:
5222                         str = "terminate I/O message in target mode";
5223                         break;
5224                 case PIT_GRP_6:
5225                         str = "group 6 commands in target mode";
5226                         break;
5227                 case PIT_GRP_7:
5228                         str = "group 7 commands in target mode";
5229                         break;
5230                 default:
5231                         str = "unknown PIT bit set";
5232                         break;
5233                 }
5234
5235                 fprintf(stdout, "%s\n", str);
5236         }
5237         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5238                 cpi->hba_eng_cnt);
5239         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5240                 cpi->max_target);
5241         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5242                 cpi->max_lun);
5243         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5244                 adapter_str, cpi->hpath_id);
5245         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5246                 cpi->initiator_id);
5247         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5248         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5249         fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5250             adapter_str, cpi->hba_vendor);
5251         fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5252             adapter_str, cpi->hba_device);
5253         fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5254             adapter_str, cpi->hba_subvendor);
5255         fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5256             adapter_str, cpi->hba_subdevice);
5257         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5258         fprintf(stdout, "%s base transfer speed: ", adapter_str);
5259         if (cpi->base_transfer_speed > 1000)
5260                 fprintf(stdout, "%d.%03dMB/sec\n",
5261                         cpi->base_transfer_speed / 1000,
5262                         cpi->base_transfer_speed % 1000);
5263         else
5264                 fprintf(stdout, "%dKB/sec\n",
5265                         (cpi->base_transfer_speed % 1000) * 1000);
5266         fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5267             adapter_str, cpi->maxio);
5268 }
5269
5270 static int
5271 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5272               struct ccb_trans_settings *cts)
5273 {
5274         int retval;
5275         union ccb *ccb;
5276
5277         retval = 0;
5278         ccb = cam_getccb(device);
5279
5280         if (ccb == NULL) {
5281                 warnx("get_print_cts: error allocating ccb");
5282                 return(1);
5283         }
5284
5285         bzero(&(&ccb->ccb_h)[1],
5286               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5287
5288         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5289
5290         if (user_settings == 0)
5291                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5292         else
5293                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5294
5295         if (cam_send_ccb(device, ccb) < 0) {
5296                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5297                 if (arglist & CAM_ARG_VERBOSE)
5298                         cam_error_print(device, ccb, CAM_ESF_ALL,
5299                                         CAM_EPF_ALL, stderr);
5300                 retval = 1;
5301                 goto get_print_cts_bailout;
5302         }
5303
5304         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5305                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5306                 if (arglist & CAM_ARG_VERBOSE)
5307                         cam_error_print(device, ccb, CAM_ESF_ALL,
5308                                         CAM_EPF_ALL, stderr);
5309                 retval = 1;
5310                 goto get_print_cts_bailout;
5311         }
5312
5313         if (quiet == 0)
5314                 cts_print(device, &ccb->cts);
5315
5316         if (cts != NULL)
5317                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5318
5319 get_print_cts_bailout:
5320
5321         cam_freeccb(ccb);
5322
5323         return(retval);
5324 }
5325
5326 static int
5327 ratecontrol(struct cam_device *device, int retry_count, int timeout,
5328             int argc, char **argv, char *combinedopt)
5329 {
5330         int c;
5331         union ccb *ccb;
5332         int user_settings = 0;
5333         int retval = 0;
5334         int disc_enable = -1, tag_enable = -1;
5335         int mode = -1;
5336         int offset = -1;
5337         double syncrate = -1;
5338         int bus_width = -1;
5339         int quiet = 0;
5340         int change_settings = 0, send_tur = 0;
5341         struct ccb_pathinq cpi;
5342
5343         ccb = cam_getccb(device);
5344         if (ccb == NULL) {
5345                 warnx("ratecontrol: error allocating ccb");
5346                 return(1);
5347         }
5348         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5349                 switch(c){
5350                 case 'a':
5351                         send_tur = 1;
5352                         break;
5353                 case 'c':
5354                         user_settings = 0;
5355                         break;
5356                 case 'D':
5357                         if (strncasecmp(optarg, "enable", 6) == 0)
5358                                 disc_enable = 1;
5359                         else if (strncasecmp(optarg, "disable", 7) == 0)
5360                                 disc_enable = 0;
5361                         else {
5362                                 warnx("-D argument \"%s\" is unknown", optarg);
5363                                 retval = 1;
5364                                 goto ratecontrol_bailout;
5365                         }
5366                         change_settings = 1;
5367                         break;
5368                 case 'M':
5369                         mode = ata_string2mode(optarg);
5370                         if (mode < 0) {
5371                                 warnx("unknown mode '%s'", optarg);
5372                                 retval = 1;
5373                                 goto ratecontrol_bailout;
5374                         }
5375                         change_settings = 1;
5376                         break;
5377                 case 'O':
5378                         offset = strtol(optarg, NULL, 0);
5379                         if (offset < 0) {
5380                                 warnx("offset value %d is < 0", offset);
5381                                 retval = 1;
5382                                 goto ratecontrol_bailout;
5383                         }
5384                         change_settings = 1;
5385                         break;
5386                 case 'q':
5387                         quiet++;
5388                         break;
5389                 case 'R':
5390                         syncrate = atof(optarg);
5391                         if (syncrate < 0) {
5392                                 warnx("sync rate %f is < 0", syncrate);
5393                                 retval = 1;
5394                                 goto ratecontrol_bailout;
5395                         }
5396                         change_settings = 1;
5397                         break;
5398                 case 'T':
5399                         if (strncasecmp(optarg, "enable", 6) == 0)
5400                                 tag_enable = 1;
5401                         else if (strncasecmp(optarg, "disable", 7) == 0)
5402                                 tag_enable = 0;
5403                         else {
5404                                 warnx("-T argument \"%s\" is unknown", optarg);
5405                                 retval = 1;
5406                                 goto ratecontrol_bailout;
5407                         }
5408                         change_settings = 1;
5409                         break;
5410                 case 'U':
5411                         user_settings = 1;
5412                         break;
5413                 case 'W':
5414                         bus_width = strtol(optarg, NULL, 0);
5415                         if (bus_width < 0) {
5416                                 warnx("bus width %d is < 0", bus_width);
5417                                 retval = 1;
5418                                 goto ratecontrol_bailout;
5419                         }
5420                         change_settings = 1;
5421                         break;
5422                 default:
5423                         break;
5424                 }
5425         }
5426         bzero(&(&ccb->ccb_h)[1],
5427               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5428         /*
5429          * Grab path inquiry information, so we can determine whether
5430          * or not the initiator is capable of the things that the user
5431          * requests.
5432          */
5433         ccb->ccb_h.func_code = XPT_PATH_INQ;
5434         if (cam_send_ccb(device, ccb) < 0) {
5435                 perror("error sending XPT_PATH_INQ CCB");
5436                 if (arglist & CAM_ARG_VERBOSE) {
5437                         cam_error_print(device, ccb, CAM_ESF_ALL,
5438                                         CAM_EPF_ALL, stderr);
5439                 }
5440                 retval = 1;
5441                 goto ratecontrol_bailout;
5442         }
5443         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5444                 warnx("XPT_PATH_INQ CCB failed");
5445                 if (arglist & CAM_ARG_VERBOSE) {
5446                         cam_error_print(device, ccb, CAM_ESF_ALL,
5447                                         CAM_EPF_ALL, stderr);
5448                 }
5449                 retval = 1;
5450                 goto ratecontrol_bailout;
5451         }
5452         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5453         bzero(&(&ccb->ccb_h)[1],
5454               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5455         if (quiet == 0) {
5456                 fprintf(stdout, "%s parameters:\n",
5457                     user_settings ? "User" : "Current");
5458         }
5459         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5460         if (retval != 0)
5461                 goto ratecontrol_bailout;
5462
5463         if (arglist & CAM_ARG_VERBOSE)
5464                 cpi_print(&cpi);
5465
5466         if (change_settings) {
5467                 int didsettings = 0;
5468                 struct ccb_trans_settings_spi *spi = NULL;
5469                 struct ccb_trans_settings_pata *pata = NULL;
5470                 struct ccb_trans_settings_sata *sata = NULL;
5471                 struct ccb_trans_settings_ata *ata = NULL;
5472                 struct ccb_trans_settings_scsi *scsi = NULL;
5473
5474                 if (ccb->cts.transport == XPORT_SPI)
5475                         spi = &ccb->cts.xport_specific.spi;
5476                 if (ccb->cts.transport == XPORT_ATA)
5477                         pata = &ccb->cts.xport_specific.ata;
5478                 if (ccb->cts.transport == XPORT_SATA)
5479                         sata = &ccb->cts.xport_specific.sata;
5480                 if (ccb->cts.protocol == PROTO_ATA)
5481                         ata = &ccb->cts.proto_specific.ata;
5482                 if (ccb->cts.protocol == PROTO_SCSI)
5483                         scsi = &ccb->cts.proto_specific.scsi;
5484                 ccb->cts.xport_specific.valid = 0;
5485                 ccb->cts.proto_specific.valid = 0;
5486                 if (spi && disc_enable != -1) {
5487                         spi->valid |= CTS_SPI_VALID_DISC;
5488                         if (disc_enable == 0)
5489                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5490                         else
5491                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5492                         didsettings++;
5493                 }
5494                 if (tag_enable != -1) {
5495                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5496                                 warnx("HBA does not support tagged queueing, "
5497                                       "so you cannot modify tag settings");
5498                                 retval = 1;
5499                                 goto ratecontrol_bailout;
5500                         }
5501                         if (ata) {
5502                                 ata->valid |= CTS_SCSI_VALID_TQ;
5503                                 if (tag_enable == 0)
5504                                         ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5505                                 else
5506                                         ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5507                                 didsettings++;
5508                         } else if (scsi) {
5509                                 scsi->valid |= CTS_SCSI_VALID_TQ;
5510                                 if (tag_enable == 0)
5511                                         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5512                                 else
5513                                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5514                                 didsettings++;
5515                         }
5516                 }
5517                 if (spi && offset != -1) {
5518                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5519                                 warnx("HBA is not capable of changing offset");
5520                                 retval = 1;
5521                                 goto ratecontrol_bailout;
5522                         }
5523                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5524                         spi->sync_offset = offset;
5525                         didsettings++;
5526                 }
5527                 if (spi && syncrate != -1) {
5528                         int prelim_sync_period;
5529
5530                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5531                                 warnx("HBA is not capable of changing "
5532                                       "transfer rates");
5533                                 retval = 1;
5534                                 goto ratecontrol_bailout;
5535                         }
5536                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5537                         /*
5538                          * The sync rate the user gives us is in MHz.
5539                          * We need to translate it into KHz for this
5540                          * calculation.
5541                          */
5542                         syncrate *= 1000;
5543                         /*
5544                          * Next, we calculate a "preliminary" sync period
5545                          * in tenths of a nanosecond.
5546                          */
5547                         if (syncrate == 0)
5548                                 prelim_sync_period = 0;
5549                         else
5550                                 prelim_sync_period = 10000000 / syncrate;
5551                         spi->sync_period =
5552                                 scsi_calc_syncparam(prelim_sync_period);
5553                         didsettings++;
5554                 }
5555                 if (sata && syncrate != -1) {
5556                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5557                                 warnx("HBA is not capable of changing "
5558                                       "transfer rates");
5559                                 retval = 1;
5560                                 goto ratecontrol_bailout;
5561                         }
5562                         if  (!user_settings) {
5563                                 warnx("You can modify only user rate "
5564                                     "settings for SATA");
5565                                 retval = 1;
5566                                 goto ratecontrol_bailout;
5567                         }
5568                         sata->revision = ata_speed2revision(syncrate * 100);
5569                         if (sata->revision < 0) {
5570                                 warnx("Invalid rate %f", syncrate);
5571                                 retval = 1;
5572                                 goto ratecontrol_bailout;
5573                         }
5574                         sata->valid |= CTS_SATA_VALID_REVISION;
5575                         didsettings++;
5576                 }
5577                 if ((pata || sata) && mode != -1) {
5578                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5579                                 warnx("HBA is not capable of changing "
5580                                       "transfer rates");
5581                                 retval = 1;
5582                                 goto ratecontrol_bailout;
5583                         }
5584                         if  (!user_settings) {
5585                                 warnx("You can modify only user mode "
5586                                     "settings for ATA/SATA");
5587                                 retval = 1;
5588                                 goto ratecontrol_bailout;
5589                         }
5590                         if (pata) {
5591                                 pata->mode = mode;
5592                                 pata->valid |= CTS_ATA_VALID_MODE;
5593                         } else {
5594                                 sata->mode = mode;
5595                                 sata->valid |= CTS_SATA_VALID_MODE;
5596                         }
5597                         didsettings++;
5598                 }
5599                 /*
5600                  * The bus_width argument goes like this:
5601                  * 0 == 8 bit
5602                  * 1 == 16 bit
5603                  * 2 == 32 bit
5604                  * Therefore, if you shift the number of bits given on the
5605                  * command line right by 4, you should get the correct
5606                  * number.
5607                  */
5608                 if (spi && bus_width != -1) {
5609                         /*
5610                          * We might as well validate things here with a
5611                          * decipherable error message, rather than what
5612                          * will probably be an indecipherable error message
5613                          * by the time it gets back to us.
5614                          */
5615                         if ((bus_width == 16)
5616                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5617                                 warnx("HBA does not support 16 bit bus width");
5618                                 retval = 1;
5619                                 goto ratecontrol_bailout;
5620                         } else if ((bus_width == 32)
5621                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5622                                 warnx("HBA does not support 32 bit bus width");
5623                                 retval = 1;
5624                                 goto ratecontrol_bailout;
5625                         } else if ((bus_width != 8)
5626                                 && (bus_width != 16)
5627                                 && (bus_width != 32)) {
5628                                 warnx("Invalid bus width %d", bus_width);
5629                                 retval = 1;
5630                                 goto ratecontrol_bailout;
5631                         }
5632                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5633                         spi->bus_width = bus_width >> 4;
5634                         didsettings++;
5635                 }
5636                 if  (didsettings == 0) {
5637                         goto ratecontrol_bailout;
5638                 }
5639                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5640                 if (cam_send_ccb(device, ccb) < 0) {
5641                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5642                         if (arglist & CAM_ARG_VERBOSE) {
5643                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5644                                                 CAM_EPF_ALL, stderr);
5645                         }
5646                         retval = 1;
5647                         goto ratecontrol_bailout;
5648                 }
5649                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5650                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5651                         if (arglist & CAM_ARG_VERBOSE) {
5652                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5653                                                 CAM_EPF_ALL, stderr);
5654                         }
5655                         retval = 1;
5656                         goto ratecontrol_bailout;
5657                 }
5658         }
5659         if (send_tur) {
5660                 retval = testunitready(device, retry_count, timeout,
5661                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5662                 /*
5663                  * If the TUR didn't succeed, just bail.
5664                  */
5665                 if (retval != 0) {
5666                         if (quiet == 0)
5667                                 fprintf(stderr, "Test Unit Ready failed\n");
5668                         goto ratecontrol_bailout;
5669                 }
5670         }
5671         if ((change_settings || send_tur) && !quiet &&
5672             (ccb->cts.transport == XPORT_ATA ||
5673              ccb->cts.transport == XPORT_SATA || send_tur)) {
5674                 fprintf(stdout, "New parameters:\n");
5675                 retval = get_print_cts(device, user_settings, 0, NULL);
5676         }
5677
5678 ratecontrol_bailout:
5679         cam_freeccb(ccb);
5680         return(retval);
5681 }
5682
5683 static int
5684 scsiformat(struct cam_device *device, int argc, char **argv,
5685            char *combinedopt, int retry_count, int timeout)
5686 {
5687         union ccb *ccb;
5688         int c;
5689         int ycount = 0, quiet = 0;
5690         int error = 0, retval = 0;
5691         int use_timeout = 10800 * 1000;
5692         int immediate = 1;
5693         struct format_defect_list_header fh;
5694         u_int8_t *data_ptr = NULL;
5695         u_int32_t dxfer_len = 0;
5696         u_int8_t byte2 = 0;
5697         int num_warnings = 0;
5698         int reportonly = 0;
5699
5700         ccb = cam_getccb(device);
5701
5702         if (ccb == NULL) {
5703                 warnx("scsiformat: error allocating ccb");
5704                 return(1);
5705         }
5706
5707         bzero(&(&ccb->ccb_h)[1],
5708               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5709
5710         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5711                 switch(c) {
5712                 case 'q':
5713                         quiet++;
5714                         break;
5715                 case 'r':
5716                         reportonly = 1;
5717                         break;
5718                 case 'w':
5719                         immediate = 0;
5720                         break;
5721                 case 'y':
5722                         ycount++;
5723                         break;
5724                 }
5725         }
5726
5727         if (reportonly)
5728                 goto doreport;
5729
5730         if (quiet == 0) {
5731                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5732                         "following device:\n");
5733
5734                 error = scsidoinquiry(device, argc, argv, combinedopt,
5735                                       retry_count, timeout);
5736
5737                 if (error != 0) {
5738                         warnx("scsiformat: error sending inquiry");
5739                         goto scsiformat_bailout;
5740                 }
5741         }
5742
5743         if (ycount == 0) {
5744                 if (!get_confirmation()) {
5745                         error = 1;
5746                         goto scsiformat_bailout;
5747                 }
5748         }
5749
5750         if (timeout != 0)
5751                 use_timeout = timeout;
5752
5753         if (quiet == 0) {
5754                 fprintf(stdout, "Current format timeout is %d seconds\n",
5755                         use_timeout / 1000);
5756         }
5757
5758         /*
5759          * If the user hasn't disabled questions and didn't specify a
5760          * timeout on the command line, ask them if they want the current
5761          * timeout.
5762          */
5763         if ((ycount == 0)
5764          && (timeout == 0)) {
5765                 char str[1024];
5766                 int new_timeout = 0;
5767
5768                 fprintf(stdout, "Enter new timeout in seconds or press\n"
5769                         "return to keep the current timeout [%d] ",
5770                         use_timeout / 1000);
5771
5772                 if (fgets(str, sizeof(str), stdin) != NULL) {
5773                         if (str[0] != '\0')
5774                                 new_timeout = atoi(str);
5775                 }
5776
5777                 if (new_timeout != 0) {
5778                         use_timeout = new_timeout * 1000;
5779                         fprintf(stdout, "Using new timeout value %d\n",
5780                                 use_timeout / 1000);
5781                 }
5782         }
5783
5784         /*
5785          * Keep this outside the if block below to silence any unused
5786          * variable warnings.
5787          */
5788         bzero(&fh, sizeof(fh));
5789
5790         /*
5791          * If we're in immediate mode, we've got to include the format
5792          * header
5793          */
5794         if (immediate != 0) {
5795                 fh.byte2 = FU_DLH_IMMED;
5796                 data_ptr = (u_int8_t *)&fh;
5797                 dxfer_len = sizeof(fh);
5798                 byte2 = FU_FMT_DATA;
5799         } else if (quiet == 0) {
5800                 fprintf(stdout, "Formatting...");
5801                 fflush(stdout);
5802         }
5803
5804         scsi_format_unit(&ccb->csio,
5805                          /* retries */ retry_count,
5806                          /* cbfcnp */ NULL,
5807                          /* tag_action */ MSG_SIMPLE_Q_TAG,
5808                          /* byte2 */ byte2,
5809                          /* ileave */ 0,
5810                          /* data_ptr */ data_ptr,
5811                          /* dxfer_len */ dxfer_len,
5812                          /* sense_len */ SSD_FULL_SIZE,
5813                          /* timeout */ use_timeout);
5814
5815         /* Disable freezing the device queue */
5816         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5817
5818         if (arglist & CAM_ARG_ERR_RECOVER)
5819                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5820
5821         if (((retval = cam_send_ccb(device, ccb)) < 0)
5822          || ((immediate == 0)
5823            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5824                 const char errstr[] = "error sending format command";
5825
5826                 if (retval < 0)
5827                         warn(errstr);
5828                 else
5829                         warnx(errstr);
5830
5831                 if (arglist & CAM_ARG_VERBOSE) {
5832                         cam_error_print(device, ccb, CAM_ESF_ALL,
5833                                         CAM_EPF_ALL, stderr);
5834                 }
5835                 error = 1;
5836                 goto scsiformat_bailout;
5837         }
5838
5839         /*
5840          * If we ran in non-immediate mode, we already checked for errors
5841          * above and printed out any necessary information.  If we're in
5842          * immediate mode, we need to loop through and get status
5843          * information periodically.
5844          */
5845         if (immediate == 0) {
5846                 if (quiet == 0) {
5847                         fprintf(stdout, "Format Complete\n");
5848                 }
5849                 goto scsiformat_bailout;
5850         }
5851
5852 doreport:
5853         do {
5854                 cam_status status;
5855
5856                 bzero(&(&ccb->ccb_h)[1],
5857                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5858
5859                 /*
5860                  * There's really no need to do error recovery or
5861                  * retries here, since we're just going to sit in a
5862                  * loop and wait for the device to finish formatting.
5863                  */
5864                 scsi_test_unit_ready(&ccb->csio,
5865                                      /* retries */ 0,
5866                                      /* cbfcnp */ NULL,
5867                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
5868                                      /* sense_len */ SSD_FULL_SIZE,
5869                                      /* timeout */ 5000);
5870
5871                 /* Disable freezing the device queue */
5872                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5873
5874                 retval = cam_send_ccb(device, ccb);
5875
5876                 /*
5877                  * If we get an error from the ioctl, bail out.  SCSI
5878                  * errors are expected.
5879                  */
5880                 if (retval < 0) {
5881                         warn("error sending CAMIOCOMMAND ioctl");
5882                         if (arglist & CAM_ARG_VERBOSE) {
5883                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5884                                                 CAM_EPF_ALL, stderr);
5885                         }
5886                         error = 1;
5887                         goto scsiformat_bailout;
5888                 }
5889
5890                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5891
5892                 if ((status != CAM_REQ_CMP)
5893                  && (status == CAM_SCSI_STATUS_ERROR)
5894                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5895                         struct scsi_sense_data *sense;
5896                         int error_code, sense_key, asc, ascq;
5897
5898                         sense = &ccb->csio.sense_data;
5899                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
5900                             ccb->csio.sense_resid, &error_code, &sense_key,
5901                             &asc, &ascq, /*show_errors*/ 1);
5902
5903                         /*
5904                          * According to the SCSI-2 and SCSI-3 specs, a
5905                          * drive that is in the middle of a format should
5906                          * return NOT READY with an ASC of "logical unit
5907                          * not ready, format in progress".  The sense key
5908                          * specific bytes will then be a progress indicator.
5909                          */
5910                         if ((sense_key == SSD_KEY_NOT_READY)
5911                          && (asc == 0x04) && (ascq == 0x04)) {
5912                                 uint8_t sks[3];
5913
5914                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5915                                      ccb->csio.sense_resid, sks) == 0)
5916                                  && (quiet == 0)) {
5917                                         int val;
5918                                         u_int64_t percentage;
5919
5920                                         val = scsi_2btoul(&sks[1]);
5921                                         percentage = 10000 * val;
5922
5923                                         fprintf(stdout,
5924                                                 "\rFormatting:  %ju.%02u %% "
5925                                                 "(%d/%d) done",
5926                                                 (uintmax_t)(percentage /
5927                                                 (0x10000 * 100)),
5928                                                 (unsigned)((percentage /
5929                                                 0x10000) % 100),
5930                                                 val, 0x10000);
5931                                         fflush(stdout);
5932                                 } else if ((quiet == 0)
5933                                         && (++num_warnings <= 1)) {
5934                                         warnx("Unexpected SCSI Sense Key "
5935                                               "Specific value returned "
5936                                               "during format:");
5937                                         scsi_sense_print(device, &ccb->csio,
5938                                                          stderr);
5939                                         warnx("Unable to print status "
5940                                               "information, but format will "
5941                                               "proceed.");
5942                                         warnx("will exit when format is "
5943                                               "complete");
5944                                 }
5945                                 sleep(1);
5946                         } else {
5947                                 warnx("Unexpected SCSI error during format");
5948                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5949                                                 CAM_EPF_ALL, stderr);
5950                                 error = 1;
5951                                 goto scsiformat_bailout;
5952                         }
5953
5954                 } else if (status != CAM_REQ_CMP) {
5955                         warnx("Unexpected CAM status %#x", status);
5956                         if (arglist & CAM_ARG_VERBOSE)
5957                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5958                                                 CAM_EPF_ALL, stderr);
5959                         error = 1;
5960                         goto scsiformat_bailout;
5961                 }
5962
5963         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5964
5965         if (quiet == 0)
5966                 fprintf(stdout, "\nFormat Complete\n");
5967
5968 scsiformat_bailout:
5969
5970         cam_freeccb(ccb);
5971
5972         return(error);
5973 }
5974
5975 static int
5976 scsisanitize(struct cam_device *device, int argc, char **argv,
5977              char *combinedopt, int retry_count, int timeout)
5978 {
5979         union ccb *ccb;
5980         u_int8_t action = 0;
5981         int c;
5982         int ycount = 0, quiet = 0;
5983         int error = 0, retval = 0;
5984         int use_timeout = 10800 * 1000;
5985         int immediate = 1;
5986         int invert = 0;
5987         int passes = 0;
5988         int ause = 0;
5989         int fd = -1;
5990         const char *pattern = NULL;
5991         u_int8_t *data_ptr = NULL;
5992         u_int32_t dxfer_len = 0;
5993         u_int8_t byte2 = 0;
5994         int num_warnings = 0;
5995         int reportonly = 0;
5996
5997         ccb = cam_getccb(device);
5998
5999         if (ccb == NULL) {
6000                 warnx("scsisanitize: error allocating ccb");
6001                 return(1);
6002         }
6003
6004         bzero(&(&ccb->ccb_h)[1],
6005               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6006
6007         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6008                 switch(c) {
6009                 case 'a':
6010                         if (strcasecmp(optarg, "overwrite") == 0)
6011                                 action = SSZ_SERVICE_ACTION_OVERWRITE;
6012                         else if (strcasecmp(optarg, "block") == 0)
6013                                 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6014                         else if (strcasecmp(optarg, "crypto") == 0)
6015                                 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6016                         else if (strcasecmp(optarg, "exitfailure") == 0)
6017                                 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6018                         else {
6019                                 warnx("invalid service operation \"%s\"",
6020                                       optarg);
6021                                 error = 1;
6022                                 goto scsisanitize_bailout;
6023                         }
6024                         break;
6025                 case 'c':
6026                         passes = strtol(optarg, NULL, 0);
6027                         if (passes < 1 || passes > 31) {
6028                                 warnx("invalid passes value %d", passes);
6029                                 error = 1;
6030                                 goto scsisanitize_bailout;
6031                         }
6032                         break;
6033                 case 'I':
6034                         invert = 1;
6035                         break;
6036                 case 'P':
6037                         pattern = optarg;
6038                         break;
6039                 case 'q':
6040                         quiet++;
6041                         break;
6042                 case 'U':
6043                         ause = 1;
6044                         break;
6045                 case 'r':
6046                         reportonly = 1;
6047                         break;
6048                 case 'w':
6049                         immediate = 0;
6050                         break;
6051                 case 'y':
6052                         ycount++;
6053                         break;
6054                 }
6055         }
6056
6057         if (reportonly)
6058                 goto doreport;
6059
6060         if (action == 0) {
6061                 warnx("an action is required");
6062                 error = 1;
6063                 goto scsisanitize_bailout;
6064         } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6065                 struct scsi_sanitize_parameter_list *pl;
6066                 struct stat sb;
6067                 ssize_t sz, amt;
6068
6069                 if (pattern == NULL) {
6070                         warnx("overwrite action requires -P argument");
6071                         error = 1;
6072                         goto scsisanitize_bailout;
6073                 }
6074                 fd = open(pattern, O_RDONLY);
6075                 if (fd < 0) {
6076                         warn("cannot open pattern file %s", pattern);
6077                         error = 1;
6078                         goto scsisanitize_bailout;
6079                 }
6080                 if (fstat(fd, &sb) < 0) {
6081                         warn("cannot stat pattern file %s", pattern);
6082                         error = 1;
6083                         goto scsisanitize_bailout;
6084                 }
6085                 sz = sb.st_size;
6086                 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6087                         warnx("pattern file size exceeds maximum value %d",
6088                               SSZPL_MAX_PATTERN_LENGTH);
6089                         error = 1;
6090                         goto scsisanitize_bailout;
6091                 }
6092                 dxfer_len = sizeof(*pl) + sz;
6093                 data_ptr = calloc(1, dxfer_len);
6094                 if (data_ptr == NULL) {
6095                         warnx("cannot allocate parameter list buffer");
6096                         error = 1;
6097                         goto scsisanitize_bailout;
6098                 }
6099
6100                 amt = read(fd, data_ptr + sizeof(*pl), sz);
6101                 if (amt < 0) {
6102                         warn("cannot read pattern file");
6103                         error = 1;
6104                         goto scsisanitize_bailout;
6105                 } else if (amt != sz) {
6106                         warnx("short pattern file read");
6107                         error = 1;
6108                         goto scsisanitize_bailout;
6109                 }
6110
6111                 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6112                 if (passes == 0)
6113                         pl->byte1 = 1;
6114                 else
6115                         pl->byte1 = passes;
6116                 if (invert != 0)
6117                         pl->byte1 |= SSZPL_INVERT;
6118                 scsi_ulto2b(sz, pl->length);
6119         } else {
6120                 const char *arg;
6121
6122                 if (passes != 0)
6123                         arg = "-c";
6124                 else if (invert != 0)
6125                         arg = "-I";
6126                 else if (pattern != NULL)
6127                         arg = "-P";
6128                 else
6129                         arg = NULL;
6130                 if (arg != NULL) {
6131                         warnx("%s argument only valid with overwrite "
6132                               "operation", arg);
6133                         error = 1;
6134                         goto scsisanitize_bailout;
6135                 }
6136         }
6137
6138         if (quiet == 0) {
6139                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6140                         "following device:\n");
6141
6142                 error = scsidoinquiry(device, argc, argv, combinedopt,
6143                                       retry_count, timeout);
6144
6145                 if (error != 0) {
6146                         warnx("scsisanitize: error sending inquiry");
6147                         goto scsisanitize_bailout;
6148                 }
6149         }
6150
6151         if (ycount == 0) {
6152                 if (!get_confirmation()) {
6153                         error = 1;
6154                         goto scsisanitize_bailout;
6155                 }
6156         }
6157
6158         if (timeout != 0)
6159                 use_timeout = timeout;
6160
6161         if (quiet == 0) {
6162                 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6163                         use_timeout / 1000);
6164         }
6165
6166         /*
6167          * If the user hasn't disabled questions and didn't specify a
6168          * timeout on the command line, ask them if they want the current
6169          * timeout.
6170          */
6171         if ((ycount == 0)
6172          && (timeout == 0)) {
6173                 char str[1024];
6174                 int new_timeout = 0;
6175
6176                 fprintf(stdout, "Enter new timeout in seconds or press\n"
6177                         "return to keep the current timeout [%d] ",
6178                         use_timeout / 1000);
6179
6180                 if (fgets(str, sizeof(str), stdin) != NULL) {
6181                         if (str[0] != '\0')
6182                                 new_timeout = atoi(str);
6183                 }
6184
6185                 if (new_timeout != 0) {
6186                         use_timeout = new_timeout * 1000;
6187                         fprintf(stdout, "Using new timeout value %d\n",
6188                                 use_timeout / 1000);
6189                 }
6190         }
6191
6192         byte2 = action;
6193         if (ause != 0)
6194                 byte2 |= SSZ_UNRESTRICTED_EXIT;
6195         if (immediate != 0)
6196                 byte2 |= SSZ_IMMED;
6197
6198         scsi_sanitize(&ccb->csio,
6199                       /* retries */ retry_count,
6200                       /* cbfcnp */ NULL,
6201                       /* tag_action */ MSG_SIMPLE_Q_TAG,
6202                       /* byte2 */ byte2,
6203                       /* control */ 0,
6204                       /* data_ptr */ data_ptr,
6205                       /* dxfer_len */ dxfer_len,
6206                       /* sense_len */ SSD_FULL_SIZE,
6207                       /* timeout */ use_timeout);
6208
6209         /* Disable freezing the device queue */
6210         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6211
6212         if (arglist & CAM_ARG_ERR_RECOVER)
6213                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6214
6215         if (cam_send_ccb(device, ccb) < 0) {
6216                 warn("error sending sanitize command");
6217                 error = 1;
6218                 goto scsisanitize_bailout;
6219         }
6220
6221         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6222                 struct scsi_sense_data *sense;
6223                 int error_code, sense_key, asc, ascq;
6224
6225                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6226                     CAM_SCSI_STATUS_ERROR) {
6227                         sense = &ccb->csio.sense_data;
6228                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6229                             ccb->csio.sense_resid, &error_code, &sense_key,
6230                             &asc, &ascq, /*show_errors*/ 1);
6231
6232                         if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6233                             asc == 0x20 && ascq == 0x00)
6234                                 warnx("sanitize is not supported by "
6235                                       "this device");
6236                         else
6237                                 warnx("error sanitizing this device");
6238                 } else
6239                         warnx("error sanitizing this device");
6240
6241                 if (arglist & CAM_ARG_VERBOSE) {
6242                         cam_error_print(device, ccb, CAM_ESF_ALL,
6243                                         CAM_EPF_ALL, stderr);
6244                 }
6245                 error = 1;
6246                 goto scsisanitize_bailout;
6247         }
6248
6249         /*
6250          * If we ran in non-immediate mode, we already checked for errors
6251          * above and printed out any necessary information.  If we're in
6252          * immediate mode, we need to loop through and get status
6253          * information periodically.
6254          */
6255         if (immediate == 0) {
6256                 if (quiet == 0) {
6257                         fprintf(stdout, "Sanitize Complete\n");
6258                 }
6259                 goto scsisanitize_bailout;
6260         }
6261
6262 doreport:
6263         do {
6264                 cam_status status;
6265
6266                 bzero(&(&ccb->ccb_h)[1],
6267                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6268
6269                 /*
6270                  * There's really no need to do error recovery or
6271                  * retries here, since we're just going to sit in a
6272                  * loop and wait for the device to finish sanitizing.
6273                  */
6274                 scsi_test_unit_ready(&ccb->csio,
6275                                      /* retries */ 0,
6276                                      /* cbfcnp */ NULL,
6277                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
6278                                      /* sense_len */ SSD_FULL_SIZE,
6279                                      /* timeout */ 5000);
6280
6281                 /* Disable freezing the device queue */
6282                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6283
6284                 retval = cam_send_ccb(device, ccb);
6285
6286                 /*
6287                  * If we get an error from the ioctl, bail out.  SCSI
6288                  * errors are expected.
6289                  */
6290                 if (retval < 0) {
6291                         warn("error sending CAMIOCOMMAND ioctl");
6292                         if (arglist & CAM_ARG_VERBOSE) {
6293                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6294                                                 CAM_EPF_ALL, stderr);
6295                         }
6296                         error = 1;
6297                         goto scsisanitize_bailout;
6298                 }
6299
6300                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6301
6302                 if ((status != CAM_REQ_CMP)
6303                  && (status == CAM_SCSI_STATUS_ERROR)
6304                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6305                         struct scsi_sense_data *sense;
6306                         int error_code, sense_key, asc, ascq;
6307
6308                         sense = &ccb->csio.sense_data;
6309                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6310                             ccb->csio.sense_resid, &error_code, &sense_key,
6311                             &asc, &ascq, /*show_errors*/ 1);
6312
6313                         /*
6314                          * According to the SCSI-3 spec, a drive that is in the
6315                          * middle of a sanitize should return NOT READY with an
6316                          * ASC of "logical unit not ready, sanitize in
6317                          * progress". The sense key specific bytes will then
6318                          * be a progress indicator.
6319                          */
6320                         if ((sense_key == SSD_KEY_NOT_READY)
6321                          && (asc == 0x04) && (ascq == 0x1b)) {
6322                                 uint8_t sks[3];
6323
6324                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6325                                      ccb->csio.sense_resid, sks) == 0)
6326                                  && (quiet == 0)) {
6327                                         int val;
6328                                         u_int64_t percentage;
6329
6330                                         val = scsi_2btoul(&sks[1]);
6331                                         percentage = 10000 * val;
6332
6333                                         fprintf(stdout,
6334                                                 "\rSanitizing:  %ju.%02u %% "
6335                                                 "(%d/%d) done",
6336                                                 (uintmax_t)(percentage /
6337                                                 (0x10000 * 100)),
6338                                                 (unsigned)((percentage /
6339                                                 0x10000) % 100),
6340                                                 val, 0x10000);
6341                                         fflush(stdout);
6342                                 } else if ((quiet == 0)
6343                                         && (++num_warnings <= 1)) {
6344                                         warnx("Unexpected SCSI Sense Key "
6345                                               "Specific value returned "
6346                                               "during sanitize:");
6347                                         scsi_sense_print(device, &ccb->csio,
6348                                                          stderr);
6349                                         warnx("Unable to print status "
6350                                               "information, but sanitze will "
6351                                               "proceed.");
6352                                         warnx("will exit when sanitize is "
6353                                               "complete");
6354                                 }
6355                                 sleep(1);
6356                         } else {
6357                                 warnx("Unexpected SCSI error during sanitize");
6358                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6359                                                 CAM_EPF_ALL, stderr);
6360                                 error = 1;
6361                                 goto scsisanitize_bailout;
6362                         }
6363
6364                 } else if (status != CAM_REQ_CMP) {
6365                         warnx("Unexpected CAM status %#x", status);
6366                         if (arglist & CAM_ARG_VERBOSE)
6367                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6368                                                 CAM_EPF_ALL, stderr);
6369                         error = 1;
6370                         goto scsisanitize_bailout;
6371                 }
6372         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6373
6374         if (quiet == 0)
6375                 fprintf(stdout, "\nSanitize Complete\n");
6376
6377 scsisanitize_bailout:
6378         if (fd >= 0)
6379                 close(fd);
6380         if (data_ptr != NULL)
6381                 free(data_ptr);
6382         cam_freeccb(ccb);
6383
6384         return(error);
6385 }
6386
6387 static int
6388 scsireportluns(struct cam_device *device, int argc, char **argv,
6389                char *combinedopt, int retry_count, int timeout)
6390 {
6391         union ccb *ccb;
6392         int c, countonly, lunsonly;
6393         struct scsi_report_luns_data *lundata;
6394         int alloc_len;
6395         uint8_t report_type;
6396         uint32_t list_len, i, j;
6397         int retval;
6398
6399         retval = 0;
6400         lundata = NULL;
6401         report_type = RPL_REPORT_DEFAULT;
6402         ccb = cam_getccb(device);
6403
6404         if (ccb == NULL) {
6405                 warnx("%s: error allocating ccb", __func__);
6406                 return (1);
6407         }
6408
6409         bzero(&(&ccb->ccb_h)[1],
6410               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6411
6412         countonly = 0;
6413         lunsonly = 0;
6414
6415         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6416                 switch (c) {
6417                 case 'c':
6418                         countonly++;
6419                         break;
6420                 case 'l':
6421                         lunsonly++;
6422                         break;
6423                 case 'r':
6424                         if (strcasecmp(optarg, "default") == 0)
6425                                 report_type = RPL_REPORT_DEFAULT;
6426                         else if (strcasecmp(optarg, "wellknown") == 0)
6427                                 report_type = RPL_REPORT_WELLKNOWN;
6428                         else if (strcasecmp(optarg, "all") == 0)
6429                                 report_type = RPL_REPORT_ALL;
6430                         else {
6431                                 warnx("%s: invalid report type \"%s\"",
6432                                       __func__, optarg);
6433                                 retval = 1;
6434                                 goto bailout;
6435                         }
6436                         break;
6437                 default:
6438                         break;
6439                 }
6440         }
6441
6442         if ((countonly != 0)
6443          && (lunsonly != 0)) {
6444                 warnx("%s: you can only specify one of -c or -l", __func__);
6445                 retval = 1;
6446                 goto bailout;
6447         }
6448         /*
6449          * According to SPC-4, the allocation length must be at least 16
6450          * bytes -- enough for the header and one LUN.
6451          */
6452         alloc_len = sizeof(*lundata) + 8;
6453
6454 retry:
6455
6456         lundata = malloc(alloc_len);
6457
6458         if (lundata == NULL) {
6459                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6460                 retval = 1;
6461                 goto bailout;
6462         }
6463
6464         scsi_report_luns(&ccb->csio,
6465                          /*retries*/ retry_count,
6466                          /*cbfcnp*/ NULL,
6467                          /*tag_action*/ MSG_SIMPLE_Q_TAG,
6468                          /*select_report*/ report_type,
6469                          /*rpl_buf*/ lundata,
6470                          /*alloc_len*/ alloc_len,
6471                          /*sense_len*/ SSD_FULL_SIZE,
6472                          /*timeout*/ timeout ? timeout : 5000);
6473
6474         /* Disable freezing the device queue */
6475         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6476
6477         if (arglist & CAM_ARG_ERR_RECOVER)
6478                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6479
6480         if (cam_send_ccb(device, ccb) < 0) {
6481                 warn("error sending REPORT LUNS command");
6482
6483                 if (arglist & CAM_ARG_VERBOSE)
6484                         cam_error_print(device, ccb, CAM_ESF_ALL,
6485                                         CAM_EPF_ALL, stderr);
6486
6487                 retval = 1;
6488                 goto bailout;
6489         }
6490
6491         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6492                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6493                 retval = 1;
6494                 goto bailout;
6495         }
6496
6497
6498         list_len = scsi_4btoul(lundata->length);
6499
6500         /*
6501          * If we need to list the LUNs, and our allocation
6502          * length was too short, reallocate and retry.
6503          */
6504         if ((countonly == 0)
6505          && (list_len > (alloc_len - sizeof(*lundata)))) {
6506                 alloc_len = list_len + sizeof(*lundata);
6507                 free(lundata);
6508                 goto retry;
6509         }
6510
6511         if (lunsonly == 0)
6512                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6513                         ((list_len / 8) > 1) ? "s" : "");
6514
6515         if (countonly != 0)
6516                 goto bailout;
6517
6518         for (i = 0; i < (list_len / 8); i++) {
6519                 int no_more;
6520
6521                 no_more = 0;
6522                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6523                         if (j != 0)
6524                                 fprintf(stdout, ",");
6525                         switch (lundata->luns[i].lundata[j] &
6526                                 RPL_LUNDATA_ATYP_MASK) {
6527                         case RPL_LUNDATA_ATYP_PERIPH:
6528                                 if ((lundata->luns[i].lundata[j] &
6529                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6530                                         fprintf(stdout, "%d:",
6531                                                 lundata->luns[i].lundata[j] &
6532                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
6533                                 else if ((j == 0)
6534                                       && ((lundata->luns[i].lundata[j+2] &
6535                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6536                                         no_more = 1;
6537
6538                                 fprintf(stdout, "%d",
6539                                         lundata->luns[i].lundata[j+1]);
6540                                 break;
6541                         case RPL_LUNDATA_ATYP_FLAT: {
6542                                 uint8_t tmplun[2];
6543                                 tmplun[0] = lundata->luns[i].lundata[j] &
6544                                         RPL_LUNDATA_FLAT_LUN_MASK;
6545                                 tmplun[1] = lundata->luns[i].lundata[j+1];
6546
6547                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6548                                 no_more = 1;
6549                                 break;
6550                         }
6551                         case RPL_LUNDATA_ATYP_LUN:
6552                                 fprintf(stdout, "%d:%d:%d",
6553                                         (lundata->luns[i].lundata[j+1] &
6554                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6555                                         lundata->luns[i].lundata[j] &
6556                                         RPL_LUNDATA_LUN_TARG_MASK,
6557                                         lundata->luns[i].lundata[j+1] &
6558                                         RPL_LUNDATA_LUN_LUN_MASK);
6559                                 break;
6560                         case RPL_LUNDATA_ATYP_EXTLUN: {
6561                                 int field_len_code, eam_code;
6562
6563                                 eam_code = lundata->luns[i].lundata[j] &
6564                                         RPL_LUNDATA_EXT_EAM_MASK;
6565                                 field_len_code = (lundata->luns[i].lundata[j] &
6566                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6567
6568                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6569                                  && (field_len_code == 0x00)) {
6570                                         fprintf(stdout, "%d",
6571                                                 lundata->luns[i].lundata[j+1]);
6572                                 } else if ((eam_code ==
6573                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6574                                         && (field_len_code == 0x03)) {
6575                                         uint8_t tmp_lun[8];
6576
6577                                         /*
6578                                          * This format takes up all 8 bytes.
6579                                          * If we aren't starting at offset 0,
6580                                          * that's a bug.
6581                                          */
6582                                         if (j != 0) {
6583                                                 fprintf(stdout, "Invalid "
6584                                                         "offset %d for "
6585                                                         "Extended LUN not "
6586                                                         "specified format", j);
6587                                                 no_more = 1;
6588                                                 break;
6589                                         }
6590                                         bzero(tmp_lun, sizeof(tmp_lun));
6591                                         bcopy(&lundata->luns[i].lundata[j+1],
6592                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
6593                                         fprintf(stdout, "%#jx",
6594                                                (intmax_t)scsi_8btou64(tmp_lun));
6595                                         no_more = 1;
6596                                 } else {
6597                                         fprintf(stderr, "Unknown Extended LUN"
6598                                                 "Address method %#x, length "
6599                                                 "code %#x", eam_code,
6600                                                 field_len_code);
6601                                         no_more = 1;
6602                                 }
6603                                 break;
6604                         }
6605                         default:
6606                                 fprintf(stderr, "Unknown LUN address method "
6607                                         "%#x\n", lundata->luns[i].lundata[0] &
6608                                         RPL_LUNDATA_ATYP_MASK);
6609                                 break;
6610                         }
6611                         /*
6612                          * For the flat addressing method, there are no
6613                          * other levels after it.
6614                          */
6615                         if (no_more != 0)
6616                                 break;
6617                 }
6618                 fprintf(stdout, "\n");
6619         }
6620
6621 bailout:
6622
6623         cam_freeccb(ccb);
6624
6625         free(lundata);
6626
6627         return (retval);
6628 }
6629
6630 static int
6631 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6632                  char *combinedopt, int retry_count, int timeout)
6633 {
6634         union ccb *ccb;
6635         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6636         struct scsi_read_capacity_data rcap;
6637         struct scsi_read_capacity_data_long rcaplong;
6638         uint64_t maxsector;
6639         uint32_t block_len;
6640         int retval;
6641         int c;
6642
6643         blocksizeonly = 0;
6644         humanize = 0;
6645         numblocks = 0;
6646         quiet = 0;
6647         sizeonly = 0;
6648         baseten = 0;
6649         retval = 0;
6650
6651         ccb = cam_getccb(device);
6652
6653         if (ccb == NULL) {
6654                 warnx("%s: error allocating ccb", __func__);
6655                 return (1);
6656         }
6657
6658         bzero(&(&ccb->ccb_h)[1],
6659               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6660
6661         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6662                 switch (c) {
6663                 case 'b':
6664                         blocksizeonly++;
6665                         break;
6666                 case 'h':
6667                         humanize++;
6668                         baseten = 0;
6669                         break;
6670                 case 'H':
6671                         humanize++;
6672                         baseten++;
6673                         break;
6674                 case 'N':
6675                         numblocks++;
6676                         break;
6677                 case 'q':
6678                         quiet++;
6679                         break;
6680                 case 's':
6681                         sizeonly++;
6682                         break;
6683                 default:
6684                         break;
6685                 }
6686         }
6687
6688         if ((blocksizeonly != 0)
6689          && (numblocks != 0)) {
6690                 warnx("%s: you can only specify one of -b or -N", __func__);
6691                 retval = 1;
6692                 goto bailout;
6693         }
6694
6695         if ((blocksizeonly != 0)
6696          && (sizeonly != 0)) {
6697                 warnx("%s: you can only specify one of -b or -s", __func__);
6698                 retval = 1;
6699                 goto bailout;
6700         }
6701
6702         if ((humanize != 0)
6703          && (quiet != 0)) {
6704                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6705                 retval = 1;
6706                 goto bailout;
6707         }
6708
6709         if ((humanize != 0)
6710          && (blocksizeonly != 0)) {
6711                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6712                 retval = 1;
6713                 goto bailout;
6714         }
6715
6716         scsi_read_capacity(&ccb->csio,
6717                            /*retries*/ retry_count,
6718                            /*cbfcnp*/ NULL,
6719                            /*tag_action*/ MSG_SIMPLE_Q_TAG,
6720                            &rcap,
6721                            SSD_FULL_SIZE,
6722                            /*timeout*/ timeout ? timeout : 5000);
6723
6724         /* Disable freezing the device queue */
6725         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6726
6727         if (arglist & CAM_ARG_ERR_RECOVER)
6728                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6729
6730         if (cam_send_ccb(device, ccb) < 0) {
6731                 warn("error sending READ CAPACITY command");
6732
6733                 if (arglist & CAM_ARG_VERBOSE)
6734                         cam_error_print(device, ccb, CAM_ESF_ALL,
6735                                         CAM_EPF_ALL, stderr);
6736
6737                 retval = 1;
6738                 goto bailout;
6739         }
6740
6741         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6742                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6743                 retval = 1;
6744                 goto bailout;
6745         }
6746
6747         maxsector = scsi_4btoul(rcap.addr);
6748         block_len = scsi_4btoul(rcap.length);
6749
6750         /*
6751          * A last block of 2^32-1 means that the true capacity is over 2TB,
6752          * and we need to issue the long READ CAPACITY to get the real
6753          * capacity.  Otherwise, we're all set.
6754          */
6755         if (maxsector != 0xffffffff)
6756                 goto do_print;
6757
6758         scsi_read_capacity_16(&ccb->csio,
6759                               /*retries*/ retry_count,
6760                               /*cbfcnp*/ NULL,
6761                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
6762                               /*lba*/ 0,
6763                               /*reladdr*/ 0,
6764                               /*pmi*/ 0,
6765                               /*rcap_buf*/ (uint8_t *)&rcaplong,
6766                               /*rcap_buf_len*/ sizeof(rcaplong),
6767                               /*sense_len*/ SSD_FULL_SIZE,
6768                               /*timeout*/ timeout ? timeout : 5000);
6769
6770         /* Disable freezing the device queue */
6771         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6772
6773         if (arglist & CAM_ARG_ERR_RECOVER)
6774                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6775
6776         if (cam_send_ccb(device, ccb) < 0) {
6777                 warn("error sending READ CAPACITY (16) command");
6778
6779                 if (arglist & CAM_ARG_VERBOSE)
6780                         cam_error_print(device, ccb, CAM_ESF_ALL,
6781                                         CAM_EPF_ALL, stderr);
6782
6783                 retval = 1;
6784                 goto bailout;
6785         }
6786
6787         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6788                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6789                 retval = 1;
6790                 goto bailout;
6791         }
6792
6793         maxsector = scsi_8btou64(rcaplong.addr);
6794         block_len = scsi_4btoul(rcaplong.length);
6795
6796 do_print:
6797         if (blocksizeonly == 0) {
6798                 /*
6799                  * Humanize implies !quiet, and also implies numblocks.
6800                  */
6801                 if (humanize != 0) {
6802                         char tmpstr[6];
6803                         int64_t tmpbytes;
6804                         int ret;
6805
6806                         tmpbytes = (maxsector + 1) * block_len;
6807                         ret = humanize_number(tmpstr, sizeof(tmpstr),
6808                                               tmpbytes, "", HN_AUTOSCALE,
6809                                               HN_B | HN_DECIMAL |
6810                                               ((baseten != 0) ?
6811                                               HN_DIVISOR_1000 : 0));
6812                         if (ret == -1) {
6813                                 warnx("%s: humanize_number failed!", __func__);
6814                                 retval = 1;
6815                                 goto bailout;
6816                         }
6817                         fprintf(stdout, "Device Size: %s%s", tmpstr,
6818                                 (sizeonly == 0) ?  ", " : "\n");
6819                 } else if (numblocks != 0) {
6820                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6821                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
6822                                 (sizeonly == 0) ? ", " : "\n");
6823                 } else {
6824                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6825                                 "Last Block: " : "", (uintmax_t)maxsector,
6826                                 (sizeonly == 0) ? ", " : "\n");
6827                 }
6828         }
6829         if (sizeonly == 0)
6830                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6831                         "Block Length: " : "", block_len, (quiet == 0) ?
6832                         " bytes" : "");
6833 bailout:
6834         cam_freeccb(ccb);
6835
6836         return (retval);
6837 }
6838
6839 static int
6840 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6841        int retry_count, int timeout)
6842 {
6843         int c, error = 0;
6844         union ccb *ccb;
6845         uint8_t *smp_request = NULL, *smp_response = NULL;
6846         int request_size = 0, response_size = 0;
6847         int fd_request = 0, fd_response = 0;
6848         char *datastr = NULL;
6849         struct get_hook hook;
6850         int retval;
6851         int flags = 0;
6852
6853         /*
6854          * Note that at the moment we don't support sending SMP CCBs to
6855          * devices that aren't probed by CAM.
6856          */
6857         ccb = cam_getccb(device);
6858         if (ccb == NULL) {
6859                 warnx("%s: error allocating CCB", __func__);
6860                 return (1);
6861         }
6862
6863         bzero(&(&ccb->ccb_h)[1],
6864               sizeof(union ccb) - sizeof(struct ccb_hdr));
6865
6866         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6867                 switch (c) {
6868                 case 'R':
6869                         arglist |= CAM_ARG_CMD_IN;
6870                         response_size = strtol(optarg, NULL, 0);
6871                         if (response_size <= 0) {
6872                                 warnx("invalid number of response bytes %d",
6873                                       response_size);
6874                                 error = 1;
6875                                 goto smpcmd_bailout;
6876                         }
6877                         hook.argc = argc - optind;
6878                         hook.argv = argv + optind;
6879                         hook.got = 0;
6880                         optind++;
6881                         datastr = cget(&hook, NULL);
6882                         /*
6883                          * If the user supplied "-" instead of a format, he
6884                          * wants the data to be written to stdout.
6885                          */
6886                         if ((datastr != NULL)
6887                          && (datastr[0] == '-'))
6888                                 fd_response = 1;
6889
6890                         smp_response = (u_int8_t *)malloc(response_size);
6891                         if (smp_response == NULL) {
6892                                 warn("can't malloc memory for SMP response");
6893                                 error = 1;
6894                                 goto smpcmd_bailout;
6895                         }
6896                         break;
6897                 case 'r':
6898                         arglist |= CAM_ARG_CMD_OUT;
6899                         request_size = strtol(optarg, NULL, 0);
6900                         if (request_size <= 0) {
6901                                 warnx("invalid number of request bytes %d",
6902                                       request_size);
6903                                 error = 1;
6904                                 goto smpcmd_bailout;
6905                         }
6906                         hook.argc = argc - optind;
6907                         hook.argv = argv + optind;
6908                         hook.got = 0;
6909                         datastr = cget(&hook, NULL);
6910                         smp_request = (u_int8_t *)malloc(request_size);
6911                         if (smp_request == NULL) {
6912                                 warn("can't malloc memory for SMP request");
6913                                 error = 1;
6914                                 goto smpcmd_bailout;
6915                         }
6916                         bzero(smp_request, request_size);
6917                         /*
6918                          * If the user supplied "-" instead of a format, he
6919                          * wants the data to be read from stdin.
6920                          */
6921                         if ((datastr != NULL)
6922                          && (datastr[0] == '-'))
6923                                 fd_request = 1;
6924                         else
6925                                 buff_encode_visit(smp_request, request_size,
6926                                                   datastr,
6927                                                   iget, &hook);
6928                         optind += hook.got;
6929                         break;
6930                 default:
6931                         break;
6932                 }
6933         }
6934
6935         /*
6936          * If fd_data is set, and we're writing to the device, we need to
6937          * read the data the user wants written from stdin.
6938          */
6939         if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6940                 ssize_t amt_read;
6941                 int amt_to_read = request_size;
6942                 u_int8_t *buf_ptr = smp_request;
6943
6944                 for (amt_read = 0; amt_to_read > 0;
6945                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6946                         if (amt_read == -1) {
6947                                 warn("error reading data from stdin");
6948                                 error = 1;
6949                                 goto smpcmd_bailout;
6950                         }
6951                         amt_to_read -= amt_read;
6952                         buf_ptr += amt_read;
6953                 }
6954         }
6955
6956         if (((arglist & CAM_ARG_CMD_IN) == 0)
6957          || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6958                 warnx("%s: need both the request (-r) and response (-R) "
6959                       "arguments", __func__);
6960                 error = 1;
6961                 goto smpcmd_bailout;
6962         }
6963
6964         flags |= CAM_DEV_QFRZDIS;
6965
6966         cam_fill_smpio(&ccb->smpio,
6967                        /*retries*/ retry_count,
6968                        /*cbfcnp*/ NULL,
6969                        /*flags*/ flags,
6970                        /*smp_request*/ smp_request,
6971                        /*smp_request_len*/ request_size,
6972                        /*smp_response*/ smp_response,
6973                        /*smp_response_len*/ response_size,
6974                        /*timeout*/ timeout ? timeout : 5000);
6975
6976         ccb->smpio.flags = SMP_FLAG_NONE;
6977
6978         if (((retval = cam_send_ccb(device, ccb)) < 0)
6979          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6980                 const char warnstr[] = "error sending command";
6981
6982                 if (retval < 0)
6983                         warn(warnstr);
6984                 else
6985                         warnx(warnstr);
6986
6987                 if (arglist & CAM_ARG_VERBOSE) {
6988                         cam_error_print(device, ccb, CAM_ESF_ALL,
6989                                         CAM_EPF_ALL, stderr);
6990                 }
6991         }
6992
6993         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6994          && (response_size > 0)) {
6995                 if (fd_response == 0) {
6996                         buff_decode_visit(smp_response, response_size,
6997                                           datastr, arg_put, NULL);
6998                         fprintf(stdout, "\n");
6999                 } else {
7000                         ssize_t amt_written;
7001                         int amt_to_write = response_size;
7002                         u_int8_t *buf_ptr = smp_response;
7003
7004                         for (amt_written = 0; (amt_to_write > 0) &&
7005                              (amt_written = write(STDOUT_FILENO, buf_ptr,
7006                                                   amt_to_write)) > 0;){
7007                                 amt_to_write -= amt_written;
7008                                 buf_ptr += amt_written;
7009                         }
7010                         if (amt_written == -1) {
7011                                 warn("error writing data to stdout");
7012                                 error = 1;
7013                                 goto smpcmd_bailout;
7014                         } else if ((amt_written == 0)
7015                                 && (amt_to_write > 0)) {
7016                                 warnx("only wrote %u bytes out of %u",
7017                                       response_size - amt_to_write, 
7018                                       response_size);
7019                         }
7020                 }
7021         }
7022 smpcmd_bailout:
7023         if (ccb != NULL)
7024                 cam_freeccb(ccb);
7025
7026         if (smp_request != NULL)
7027                 free(smp_request);
7028
7029         if (smp_response != NULL)
7030                 free(smp_response);
7031
7032         return (error);
7033 }
7034
7035 static int
7036 smpreportgeneral(struct cam_device *device, int argc, char **argv,
7037                  char *combinedopt, int retry_count, int timeout)
7038 {
7039         union ccb *ccb;
7040         struct smp_report_general_request *request = NULL;
7041         struct smp_report_general_response *response = NULL;
7042         struct sbuf *sb = NULL;
7043         int error = 0;
7044         int c, long_response = 0;
7045         int retval;
7046
7047         /*
7048          * Note that at the moment we don't support sending SMP CCBs to
7049          * devices that aren't probed by CAM.
7050          */
7051         ccb = cam_getccb(device);
7052         if (ccb == NULL) {
7053                 warnx("%s: error allocating CCB", __func__);
7054                 return (1);
7055         }
7056
7057         bzero(&(&ccb->ccb_h)[1],
7058               sizeof(union ccb) - sizeof(struct ccb_hdr));
7059
7060         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7061                 switch (c) {
7062                 case 'l':
7063                         long_response = 1;
7064                         break;
7065                 default:
7066                         break;
7067                 }
7068         }
7069         request = malloc(sizeof(*request));
7070         if (request == NULL) {
7071                 warn("%s: unable to allocate %zd bytes", __func__,
7072                      sizeof(*request));
7073                 error = 1;
7074                 goto bailout;
7075         }
7076
7077         response = malloc(sizeof(*response));
7078         if (response == NULL) {
7079                 warn("%s: unable to allocate %zd bytes", __func__,
7080                      sizeof(*response));
7081                 error = 1;
7082                 goto bailout;
7083         }
7084
7085 try_long:
7086         smp_report_general(&ccb->smpio,
7087                            retry_count,
7088                            /*cbfcnp*/ NULL,
7089                            request,
7090                            /*request_len*/ sizeof(*request),
7091                            (uint8_t *)response,
7092                            /*response_len*/ sizeof(*response),
7093                            /*long_response*/ long_response,
7094                            timeout);
7095
7096         if (((retval = cam_send_ccb(device, ccb)) < 0)
7097          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7098                 const char warnstr[] = "error sending command";
7099
7100                 if (retval < 0)
7101                         warn(warnstr);
7102                 else
7103                         warnx(warnstr);
7104
7105                 if (arglist & CAM_ARG_VERBOSE) {
7106                         cam_error_print(device, ccb, CAM_ESF_ALL,
7107                                         CAM_EPF_ALL, stderr);
7108                 }
7109                 error = 1;
7110                 goto bailout;
7111         }
7112
7113         /*
7114          * If the device supports the long response bit, try again and see
7115          * if we can get all of the data.
7116          */
7117         if ((response->long_response & SMP_RG_LONG_RESPONSE)
7118          && (long_response == 0)) {
7119                 ccb->ccb_h.status = CAM_REQ_INPROG;
7120                 bzero(&(&ccb->ccb_h)[1],
7121                       sizeof(union ccb) - sizeof(struct ccb_hdr));
7122                 long_response = 1;
7123                 goto try_long;
7124         }
7125
7126         /*
7127          * XXX KDM detect and decode SMP errors here.
7128          */
7129         sb = sbuf_new_auto();
7130         if (sb == NULL) {
7131                 warnx("%s: error allocating sbuf", __func__);
7132                 goto bailout;
7133         }
7134
7135         smp_report_general_sbuf(response, sizeof(*response), sb);
7136
7137         if (sbuf_finish(sb) != 0) {
7138                 warnx("%s: sbuf_finish", __func__);
7139                 goto bailout;
7140         }
7141
7142         printf("%s", sbuf_data(sb));
7143
7144 bailout:
7145         if (ccb != NULL)
7146                 cam_freeccb(ccb);
7147
7148         if (request != NULL)
7149                 free(request);
7150
7151         if (response != NULL)
7152                 free(response);
7153
7154         if (sb != NULL)
7155                 sbuf_delete(sb);
7156
7157         return (error);
7158 }
7159
7160 static struct camcontrol_opts phy_ops[] = {
7161         {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7162         {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7163         {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7164         {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7165         {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7166         {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7167         {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7168         {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7169         {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7170         {NULL, 0, 0, NULL}
7171 };
7172
7173 static int
7174 smpphycontrol(struct cam_device *device, int argc, char **argv,
7175               char *combinedopt, int retry_count, int timeout)
7176 {
7177         union ccb *ccb;
7178         struct smp_phy_control_request *request = NULL;
7179         struct smp_phy_control_response *response = NULL;
7180         int long_response = 0;
7181         int retval = 0;
7182         int phy = -1;
7183         uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7184         int phy_op_set = 0;
7185         uint64_t attached_dev_name = 0;
7186         int dev_name_set = 0;
7187         uint32_t min_plr = 0, max_plr = 0;
7188         uint32_t pp_timeout_val = 0;
7189         int slumber_partial = 0;
7190         int set_pp_timeout_val = 0;
7191         int c;
7192
7193         /*
7194          * Note that at the moment we don't support sending SMP CCBs to
7195          * devices that aren't probed by CAM.
7196          */
7197         ccb = cam_getccb(device);
7198         if (ccb == NULL) {
7199                 warnx("%s: error allocating CCB", __func__);
7200                 return (1);
7201         }
7202
7203         bzero(&(&ccb->ccb_h)[1],
7204               sizeof(union ccb) - sizeof(struct ccb_hdr));
7205
7206         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7207                 switch (c) {
7208                 case 'a':
7209                 case 'A':
7210                 case 's':
7211                 case 'S': {
7212                         int enable = -1;
7213
7214                         if (strcasecmp(optarg, "enable") == 0)
7215                                 enable = 1;
7216                         else if (strcasecmp(optarg, "disable") == 0)
7217                                 enable = 2;
7218                         else {
7219                                 warnx("%s: Invalid argument %s", __func__,
7220                                       optarg);
7221                                 retval = 1;
7222                                 goto bailout;
7223                         }
7224                         switch (c) {
7225                         case 's':
7226                                 slumber_partial |= enable <<
7227                                                    SMP_PC_SAS_SLUMBER_SHIFT;
7228                                 break;
7229                         case 'S':
7230                                 slumber_partial |= enable <<
7231                                                    SMP_PC_SAS_PARTIAL_SHIFT;
7232                                 break;
7233                         case 'a':
7234                                 slumber_partial |= enable <<
7235                                                    SMP_PC_SATA_SLUMBER_SHIFT;
7236                                 break;
7237                         case 'A':
7238                                 slumber_partial |= enable <<
7239                                                    SMP_PC_SATA_PARTIAL_SHIFT;
7240                                 break;
7241                         default:
7242                                 warnx("%s: programmer error", __func__);
7243                                 retval = 1;
7244                                 goto bailout;
7245                                 break; /*NOTREACHED*/
7246                         }
7247                         break;
7248                 }
7249                 case 'd':
7250                         attached_dev_name = (uintmax_t)strtoumax(optarg,
7251                                                                  NULL,0);
7252                         dev_name_set = 1;
7253                         break;
7254                 case 'l':
7255                         long_response = 1;
7256                         break;
7257                 case 'm':
7258                         /*
7259                          * We don't do extensive checking here, so this
7260                          * will continue to work when new speeds come out.
7261                          */
7262                         min_plr = strtoul(optarg, NULL, 0);
7263                         if ((min_plr == 0)
7264                          || (min_plr > 0xf)) {
7265                                 warnx("%s: invalid link rate %x",
7266                                       __func__, min_plr);
7267                                 retval = 1;
7268                                 goto bailout;
7269                         }
7270                         break;
7271                 case 'M':
7272                         /*
7273                          * We don't do extensive checking here, so this
7274                          * will continue to work when new speeds come out.
7275                          */
7276                         max_plr = strtoul(optarg, NULL, 0);
7277                         if ((max_plr == 0)
7278                          || (max_plr > 0xf)) {
7279                                 warnx("%s: invalid link rate %x",
7280                                       __func__, max_plr);
7281                                 retval = 1;
7282                                 goto bailout;
7283                         }
7284                         break;
7285                 case 'o': {
7286                         camcontrol_optret optreturn;
7287                         cam_argmask argnums;
7288                         const char *subopt;
7289
7290                         if (phy_op_set != 0) {
7291                                 warnx("%s: only one phy operation argument "
7292                                       "(-o) allowed", __func__);
7293                                 retval = 1;
7294                                 goto bailout;
7295                         }
7296
7297                         phy_op_set = 1;
7298
7299                         /*
7300                          * Allow the user to specify the phy operation
7301                          * numerically, as well as with a name.  This will
7302                          * future-proof it a bit, so options that are added
7303                          * in future specs can be used.
7304                          */
7305                         if (isdigit(optarg[0])) {
7306                                 phy_operation = strtoul(optarg, NULL, 0);
7307                                 if ((phy_operation == 0)
7308                                  || (phy_operation > 0xff)) {
7309                                         warnx("%s: invalid phy operation %#x",
7310                                               __func__, phy_operation);
7311                                         retval = 1;
7312                                         goto bailout;
7313                                 }
7314                                 break;
7315                         }
7316                         optreturn = getoption(phy_ops, optarg, &phy_operation,
7317                                               &argnums, &subopt);
7318
7319                         if (optreturn == CC_OR_AMBIGUOUS) {
7320                                 warnx("%s: ambiguous option %s", __func__,
7321                                       optarg);
7322                                 usage(0);
7323                                 retval = 1;
7324                                 goto bailout;
7325                         } else if (optreturn == CC_OR_NOT_FOUND) {
7326                                 warnx("%s: option %s not found", __func__,
7327                                       optarg);
7328                                 usage(0);
7329                                 retval = 1;
7330                                 goto bailout;
7331                         }
7332                         break;
7333                 }
7334                 case 'p':
7335                         phy = atoi(optarg);
7336                         break;
7337                 case 'T':
7338                         pp_timeout_val = strtoul(optarg, NULL, 0);
7339                         if (pp_timeout_val > 15) {
7340                                 warnx("%s: invalid partial pathway timeout "
7341                                       "value %u, need a value less than 16",
7342                                       __func__, pp_timeout_val);
7343                                 retval = 1;
7344                                 goto bailout;
7345                         }
7346                         set_pp_timeout_val = 1;
7347                         break;
7348                 default:
7349                         break;
7350                 }
7351         }
7352
7353         if (phy == -1) {
7354                 warnx("%s: a PHY (-p phy) argument is required",__func__);
7355                 retval = 1;
7356                 goto bailout;
7357         }
7358
7359         if (((dev_name_set != 0)
7360           && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7361          || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7362           && (dev_name_set == 0))) {
7363                 warnx("%s: -d name and -o setdevname arguments both "
7364                       "required to set device name", __func__);
7365                 retval = 1;
7366                 goto bailout;
7367         }
7368
7369         request = malloc(sizeof(*request));
7370         if (request == NULL) {
7371                 warn("%s: unable to allocate %zd bytes", __func__,
7372                      sizeof(*request));
7373                 retval = 1;
7374                 goto bailout;
7375         }
7376
7377         response = malloc(sizeof(*response));
7378         if (response == NULL) {
7379                 warn("%s: unable to allocate %zd bytes", __func__,
7380                      sizeof(*request));
7381                 retval = 1;
7382                 goto bailout;
7383         }
7384
7385         smp_phy_control(&ccb->smpio,
7386                         retry_count,
7387                         /*cbfcnp*/ NULL,
7388                         request,
7389                         sizeof(*request),
7390                         (uint8_t *)response,
7391                         sizeof(*response),
7392                         long_response,
7393                         /*expected_exp_change_count*/ 0,
7394                         phy,
7395                         phy_operation,
7396                         (set_pp_timeout_val != 0) ? 1 : 0,
7397                         attached_dev_name,
7398                         min_plr,
7399                         max_plr,
7400                         slumber_partial,
7401                         pp_timeout_val,
7402                         timeout);
7403
7404         if (((retval = cam_send_ccb(device, ccb)) < 0)
7405          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7406                 const char warnstr[] = "error sending command";
7407
7408                 if (retval < 0)
7409                         warn(warnstr);
7410                 else
7411                         warnx(warnstr);
7412
7413                 if (arglist & CAM_ARG_VERBOSE) {
7414                         /*
7415                          * Use CAM_EPF_NORMAL so we only get one line of
7416                          * SMP command decoding.
7417                          */
7418                         cam_error_print(device, ccb, CAM_ESF_ALL,
7419                                         CAM_EPF_NORMAL, stderr);
7420                 }
7421                 retval = 1;
7422                 goto bailout;
7423         }
7424
7425         /* XXX KDM print out something here for success? */
7426 bailout:
7427         if (ccb != NULL)
7428                 cam_freeccb(ccb);
7429
7430         if (request != NULL)
7431                 free(request);
7432
7433         if (response != NULL)
7434                 free(response);
7435
7436         return (retval);
7437 }
7438
7439 static int
7440 smpmaninfo(struct cam_device *device, int argc, char **argv,
7441            char *combinedopt, int retry_count, int timeout)
7442 {
7443         union ccb *ccb;
7444         struct smp_report_manuf_info_request request;
7445         struct smp_report_manuf_info_response response;
7446         struct sbuf *sb = NULL;
7447         int long_response = 0;
7448         int retval = 0;
7449         int c;
7450
7451         /*
7452          * Note that at the moment we don't support sending SMP CCBs to
7453          * devices that aren't probed by CAM.
7454          */
7455         ccb = cam_getccb(device);
7456         if (ccb == NULL) {
7457                 warnx("%s: error allocating CCB", __func__);
7458                 return (1);
7459         }
7460
7461         bzero(&(&ccb->ccb_h)[1],
7462               sizeof(union ccb) - sizeof(struct ccb_hdr));
7463
7464         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7465                 switch (c) {
7466                 case 'l':
7467                         long_response = 1;
7468                         break;
7469                 default:
7470                         break;
7471                 }
7472         }
7473         bzero(&request, sizeof(request));
7474         bzero(&response, sizeof(response));
7475
7476         smp_report_manuf_info(&ccb->smpio,
7477                               retry_count,
7478                               /*cbfcnp*/ NULL,
7479                               &request,
7480                               sizeof(request),
7481                               (uint8_t *)&response,
7482                               sizeof(response),
7483                               long_response,
7484                               timeout);
7485
7486         if (((retval = cam_send_ccb(device, ccb)) < 0)
7487          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7488                 const char warnstr[] = "error sending command";
7489
7490                 if (retval < 0)
7491                         warn(warnstr);
7492                 else
7493                         warnx(warnstr);
7494
7495                 if (arglist & CAM_ARG_VERBOSE) {
7496                         cam_error_print(device, ccb, CAM_ESF_ALL,
7497                                         CAM_EPF_ALL, stderr);
7498                 }
7499                 retval = 1;
7500                 goto bailout;
7501         }
7502
7503         sb = sbuf_new_auto();
7504         if (sb == NULL) {
7505                 warnx("%s: error allocating sbuf", __func__);
7506                 goto bailout;
7507         }
7508
7509         smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7510
7511         if (sbuf_finish(sb) != 0) {
7512                 warnx("%s: sbuf_finish", __func__);
7513                 goto bailout;
7514         }
7515
7516         printf("%s", sbuf_data(sb));
7517
7518 bailout:
7519
7520         if (ccb != NULL)
7521                 cam_freeccb(ccb);
7522
7523         if (sb != NULL)
7524                 sbuf_delete(sb);
7525
7526         return (retval);
7527 }
7528
7529 static int
7530 getdevid(struct cam_devitem *item)
7531 {
7532         int retval = 0;
7533         union ccb *ccb = NULL;
7534
7535         struct cam_device *dev;
7536
7537         dev = cam_open_btl(item->dev_match.path_id,
7538                            item->dev_match.target_id,
7539                            item->dev_match.target_lun, O_RDWR, NULL);
7540
7541         if (dev == NULL) {
7542                 warnx("%s", cam_errbuf);
7543                 retval = 1;
7544                 goto bailout;
7545         }
7546
7547         item->device_id_len = 0;
7548
7549         ccb = cam_getccb(dev);
7550         if (ccb == NULL) {
7551                 warnx("%s: error allocating CCB", __func__);
7552                 retval = 1;
7553                 goto bailout;
7554         }
7555
7556         bzero(&(&ccb->ccb_h)[1],
7557               sizeof(union ccb) - sizeof(struct ccb_hdr));
7558
7559         /*
7560          * On the first try, we just probe for the size of the data, and
7561          * then allocate that much memory and try again.
7562          */
7563 retry:
7564         ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7565         ccb->ccb_h.flags = CAM_DIR_IN;
7566         ccb->cdai.flags = CDAI_FLAG_NONE;
7567         ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7568         ccb->cdai.bufsiz = item->device_id_len;
7569         if (item->device_id_len != 0)
7570                 ccb->cdai.buf = (uint8_t *)item->device_id;
7571
7572         if (cam_send_ccb(dev, ccb) < 0) {
7573                 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7574                 retval = 1;
7575                 goto bailout;
7576         }
7577
7578         if (ccb->ccb_h.status != CAM_REQ_CMP) {
7579                 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7580                 retval = 1;
7581                 goto bailout;
7582         }
7583
7584         if (item->device_id_len == 0) {
7585                 /*
7586                  * This is our first time through.  Allocate the buffer,
7587                  * and then go back to get the data.
7588                  */
7589                 if (ccb->cdai.provsiz == 0) {
7590                         warnx("%s: invalid .provsiz field returned with "
7591                              "XPT_GDEV_ADVINFO CCB", __func__);
7592                         retval = 1;
7593                         goto bailout;
7594                 }
7595                 item->device_id_len = ccb->cdai.provsiz;
7596                 item->device_id = malloc(item->device_id_len);
7597                 if (item->device_id == NULL) {
7598                         warn("%s: unable to allocate %d bytes", __func__,
7599                              item->device_id_len);
7600                         retval = 1;
7601                         goto bailout;
7602                 }
7603                 ccb->ccb_h.status = CAM_REQ_INPROG;
7604                 goto retry;
7605         }
7606
7607 bailout:
7608         if (dev != NULL)
7609                 cam_close_device(dev);
7610
7611         if (ccb != NULL)
7612                 cam_freeccb(ccb);
7613
7614         return (retval);
7615 }
7616
7617 /*
7618  * XXX KDM merge this code with getdevtree()?
7619  */
7620 static int
7621 buildbusdevlist(struct cam_devlist *devlist)
7622 {
7623         union ccb ccb;
7624         int bufsize, fd = -1;
7625         struct dev_match_pattern *patterns;
7626         struct cam_devitem *item = NULL;
7627         int skip_device = 0;
7628         int retval = 0;
7629
7630         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7631                 warn("couldn't open %s", XPT_DEVICE);
7632                 return(1);
7633         }
7634
7635         bzero(&ccb, sizeof(union ccb));
7636
7637         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7638         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7639         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7640
7641         ccb.ccb_h.func_code = XPT_DEV_MATCH;
7642         bufsize = sizeof(struct dev_match_result) * 100;
7643         ccb.cdm.match_buf_len = bufsize;
7644         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7645         if (ccb.cdm.matches == NULL) {
7646                 warnx("can't malloc memory for matches");
7647                 close(fd);
7648                 return(1);
7649         }
7650         ccb.cdm.num_matches = 0;
7651         ccb.cdm.num_patterns = 2;
7652         ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7653                 ccb.cdm.num_patterns;
7654
7655         patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7656         if (patterns == NULL) {
7657                 warnx("can't malloc memory for patterns");
7658                 retval = 1;
7659                 goto bailout;
7660         }
7661
7662         ccb.cdm.patterns = patterns;
7663         bzero(patterns, ccb.cdm.pattern_buf_len);
7664
7665         patterns[0].type = DEV_MATCH_DEVICE;
7666         patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7667         patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7668         patterns[1].type = DEV_MATCH_PERIPH;
7669         patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7670         patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7671
7672         /*
7673          * We do the ioctl multiple times if necessary, in case there are
7674          * more than 100 nodes in the EDT.
7675          */
7676         do {
7677                 unsigned int i;
7678
7679                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7680                         warn("error sending CAMIOCOMMAND ioctl");
7681                         retval = 1;
7682                         goto bailout;
7683                 }
7684
7685                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7686                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7687                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7688                         warnx("got CAM error %#x, CDM error %d\n",
7689                               ccb.ccb_h.status, ccb.cdm.status);
7690                         retval = 1;
7691                         goto bailout;
7692                 }
7693
7694                 for (i = 0; i < ccb.cdm.num_matches; i++) {
7695                         switch (ccb.cdm.matches[i].type) {
7696                         case DEV_MATCH_DEVICE: {
7697                                 struct device_match_result *dev_result;
7698
7699                                 dev_result = 
7700                                      &ccb.cdm.matches[i].result.device_result;
7701
7702                                 if (dev_result->flags &
7703                                     DEV_RESULT_UNCONFIGURED) {
7704                                         skip_device = 1;
7705                                         break;
7706                                 } else
7707                                         skip_device = 0;
7708
7709                                 item = malloc(sizeof(*item));
7710                                 if (item == NULL) {
7711                                         warn("%s: unable to allocate %zd bytes",
7712                                              __func__, sizeof(*item));
7713                                         retval = 1;
7714                                         goto bailout;
7715                                 }
7716                                 bzero(item, sizeof(*item));
7717                                 bcopy(dev_result, &item->dev_match,
7718                                       sizeof(*dev_result));
7719                                 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7720                                                    links);
7721
7722                                 if (getdevid(item) != 0) {
7723                                         retval = 1;
7724                                         goto bailout;
7725                                 }
7726                                 break;
7727                         }
7728                         case DEV_MATCH_PERIPH: {
7729                                 struct periph_match_result *periph_result;
7730
7731                                 periph_result =
7732                                       &ccb.cdm.matches[i].result.periph_result;
7733
7734                                 if (skip_device != 0)
7735                                         break;
7736                                 item->num_periphs++;
7737                                 item->periph_matches = realloc(
7738                                         item->periph_matches,
7739                                         item->num_periphs *
7740                                         sizeof(struct periph_match_result));
7741                                 if (item->periph_matches == NULL) {
7742                                         warn("%s: error allocating periph "
7743                                              "list", __func__);
7744                                         retval = 1;
7745                                         goto bailout;
7746                                 }
7747                                 bcopy(periph_result, &item->periph_matches[
7748                                       item->num_periphs - 1],
7749                                       sizeof(*periph_result));
7750                                 break;
7751                         }
7752                         default:
7753                                 fprintf(stderr, "%s: unexpected match "
7754                                         "type %d\n", __func__,
7755                                         ccb.cdm.matches[i].type);
7756                                 retval = 1;
7757                                 goto bailout;
7758                                 break; /*NOTREACHED*/
7759                         }
7760                 }
7761         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7762                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7763 bailout:
7764
7765         if (fd != -1)
7766                 close(fd);
7767
7768         free(patterns);
7769
7770         free(ccb.cdm.matches);
7771
7772         if (retval != 0)
7773                 freebusdevlist(devlist);
7774
7775         return (retval);
7776 }
7777
7778 static void
7779 freebusdevlist(struct cam_devlist *devlist)
7780 {
7781         struct cam_devitem *item, *item2;
7782
7783         STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7784                 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7785                               links);
7786                 free(item->device_id);
7787                 free(item->periph_matches);
7788                 free(item);
7789         }
7790 }
7791
7792 static struct cam_devitem *
7793 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7794 {
7795         struct cam_devitem *item;
7796
7797         STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7798                 struct scsi_vpd_id_descriptor *idd;
7799
7800                 /*
7801                  * XXX KDM look for LUN IDs as well?
7802                  */
7803                 idd = scsi_get_devid(item->device_id,
7804                                            item->device_id_len,
7805                                            scsi_devid_is_sas_target);
7806                 if (idd == NULL)
7807                         continue;
7808
7809                 if (scsi_8btou64(idd->identifier) == sasaddr)
7810                         return (item);
7811         }
7812
7813         return (NULL);
7814 }
7815
7816 static int
7817 smpphylist(struct cam_device *device, int argc, char **argv,
7818            char *combinedopt, int retry_count, int timeout)
7819 {
7820         struct smp_report_general_request *rgrequest = NULL;
7821         struct smp_report_general_response *rgresponse = NULL;
7822         struct smp_discover_request *disrequest = NULL;
7823         struct smp_discover_response *disresponse = NULL;
7824         struct cam_devlist devlist;
7825         union ccb *ccb;
7826         int long_response = 0;
7827         int num_phys = 0;
7828         int quiet = 0;
7829         int retval;
7830         int i, c;
7831
7832         /*
7833          * Note that at the moment we don't support sending SMP CCBs to
7834          * devices that aren't probed by CAM.
7835          */
7836         ccb = cam_getccb(device);
7837         if (ccb == NULL) {
7838                 warnx("%s: error allocating CCB", __func__);
7839                 return (1);
7840         }
7841
7842         bzero(&(&ccb->ccb_h)[1],
7843               sizeof(union ccb) - sizeof(struct ccb_hdr));
7844         STAILQ_INIT(&devlist.dev_queue);
7845
7846         rgrequest = malloc(sizeof(*rgrequest));
7847         if (rgrequest == NULL) {
7848                 warn("%s: unable to allocate %zd bytes", __func__,
7849                      sizeof(*rgrequest));
7850                 retval = 1;
7851                 goto bailout;
7852         }
7853
7854         rgresponse = malloc(sizeof(*rgresponse));
7855         if (rgresponse == NULL) {
7856                 warn("%s: unable to allocate %zd bytes", __func__,
7857                      sizeof(*rgresponse));
7858                 retval = 1;
7859                 goto bailout;
7860         }
7861
7862         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7863                 switch (c) {
7864                 case 'l':
7865                         long_response = 1;
7866                         break;
7867                 case 'q':
7868                         quiet = 1;
7869                         break;
7870                 default:
7871                         break;
7872                 }
7873         }
7874
7875         smp_report_general(&ccb->smpio,
7876                            retry_count,
7877                            /*cbfcnp*/ NULL,
7878                            rgrequest,
7879                            /*request_len*/ sizeof(*rgrequest),
7880                            (uint8_t *)rgresponse,
7881                            /*response_len*/ sizeof(*rgresponse),
7882                            /*long_response*/ long_response,
7883                            timeout);
7884
7885         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7886
7887         if (((retval = cam_send_ccb(device, ccb)) < 0)
7888          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7889                 const char warnstr[] = "error sending command";
7890
7891                 if (retval < 0)
7892                         warn(warnstr);
7893                 else
7894                         warnx(warnstr);
7895
7896                 if (arglist & CAM_ARG_VERBOSE) {
7897                         cam_error_print(device, ccb, CAM_ESF_ALL,
7898                                         CAM_EPF_ALL, stderr);
7899                 }
7900                 retval = 1;
7901                 goto bailout;
7902         }
7903
7904         num_phys = rgresponse->num_phys;
7905
7906         if (num_phys == 0) {
7907                 if (quiet == 0)
7908                         fprintf(stdout, "%s: No Phys reported\n", __func__);
7909                 retval = 1;
7910                 goto bailout;
7911         }
7912
7913         devlist.path_id = device->path_id;
7914
7915         retval = buildbusdevlist(&devlist);
7916         if (retval != 0)
7917                 goto bailout;
7918
7919         if (quiet == 0) {
7920                 fprintf(stdout, "%d PHYs:\n", num_phys);
7921                 fprintf(stdout, "PHY  Attached SAS Address\n");
7922         }
7923
7924         disrequest = malloc(sizeof(*disrequest));
7925         if (disrequest == NULL) {
7926                 warn("%s: unable to allocate %zd bytes", __func__,
7927                      sizeof(*disrequest));
7928                 retval = 1;
7929                 goto bailout;
7930         }
7931
7932         disresponse = malloc(sizeof(*disresponse));
7933         if (disresponse == NULL) {
7934                 warn("%s: unable to allocate %zd bytes", __func__,
7935                      sizeof(*disresponse));
7936                 retval = 1;
7937                 goto bailout;
7938         }
7939
7940         for (i = 0; i < num_phys; i++) {
7941                 struct cam_devitem *item;
7942                 struct device_match_result *dev_match;
7943                 char vendor[16], product[48], revision[16];
7944                 char tmpstr[256];
7945                 int j;
7946
7947                 bzero(&(&ccb->ccb_h)[1],
7948                       sizeof(union ccb) - sizeof(struct ccb_hdr));
7949
7950                 ccb->ccb_h.status = CAM_REQ_INPROG;
7951                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7952
7953                 smp_discover(&ccb->smpio,
7954                              retry_count,
7955                              /*cbfcnp*/ NULL,
7956                              disrequest,
7957                              sizeof(*disrequest),
7958                              (uint8_t *)disresponse,
7959                              sizeof(*disresponse),
7960                              long_response,
7961                              /*ignore_zone_group*/ 0,
7962                              /*phy*/ i,
7963                              timeout);
7964
7965                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7966                  || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7967                   && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7968                         const char warnstr[] = "error sending command";
7969
7970                         if (retval < 0)
7971                                 warn(warnstr);
7972                         else
7973                                 warnx(warnstr);
7974
7975                         if (arglist & CAM_ARG_VERBOSE) {
7976                                 cam_error_print(device, ccb, CAM_ESF_ALL,
7977                                                 CAM_EPF_ALL, stderr);
7978                         }
7979                         retval = 1;
7980                         goto bailout;
7981                 }
7982
7983                 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7984                         if (quiet == 0)
7985                                 fprintf(stdout, "%3d  <vacant>\n", i);
7986                         continue;
7987                 }
7988
7989                 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7990                         item = NULL;
7991                 } else {
7992                         item = findsasdevice(&devlist,
7993                             scsi_8btou64(disresponse->attached_sas_address));
7994                 }
7995
7996                 if ((quiet == 0)
7997                  || (item != NULL)) {
7998                         fprintf(stdout, "%3d  0x%016jx", i,
7999                                 (uintmax_t)scsi_8btou64(
8000                                 disresponse->attached_sas_address));
8001                         if (item == NULL) {
8002                                 fprintf(stdout, "\n");
8003                                 continue;
8004                         }
8005                 } else if (quiet != 0)
8006                         continue;
8007
8008                 dev_match = &item->dev_match;
8009
8010                 if (dev_match->protocol == PROTO_SCSI) {
8011                         cam_strvis(vendor, dev_match->inq_data.vendor,
8012                                    sizeof(dev_match->inq_data.vendor),
8013                                    sizeof(vendor));
8014                         cam_strvis(product, dev_match->inq_data.product,
8015                                    sizeof(dev_match->inq_data.product),
8016                                    sizeof(product));
8017                         cam_strvis(revision, dev_match->inq_data.revision,
8018                                    sizeof(dev_match->inq_data.revision),
8019                                    sizeof(revision));
8020                         sprintf(tmpstr, "<%s %s %s>", vendor, product,
8021                                 revision);
8022                 } else if ((dev_match->protocol == PROTO_ATA)
8023                         || (dev_match->protocol == PROTO_SATAPM)) {
8024                         cam_strvis(product, dev_match->ident_data.model,
8025                                    sizeof(dev_match->ident_data.model),
8026                                    sizeof(product));
8027                         cam_strvis(revision, dev_match->ident_data.revision,
8028                                    sizeof(dev_match->ident_data.revision),
8029                                    sizeof(revision));
8030                         sprintf(tmpstr, "<%s %s>", product, revision);
8031                 } else {
8032                         sprintf(tmpstr, "<>");
8033                 }
8034                 fprintf(stdout, "   %-33s ", tmpstr);
8035
8036                 /*
8037                  * If we have 0 periphs, that's a bug...
8038                  */
8039                 if (item->num_periphs == 0) {
8040                         fprintf(stdout, "\n");
8041                         continue;
8042                 }
8043
8044                 fprintf(stdout, "(");
8045                 for (j = 0; j < item->num_periphs; j++) {
8046                         if (j > 0)
8047                                 fprintf(stdout, ",");
8048
8049                         fprintf(stdout, "%s%d",
8050                                 item->periph_matches[j].periph_name,
8051                                 item->periph_matches[j].unit_number);
8052                                 
8053                 }
8054                 fprintf(stdout, ")\n");
8055         }
8056 bailout:
8057         if (ccb != NULL)
8058                 cam_freeccb(ccb);
8059
8060         free(rgrequest);
8061
8062         free(rgresponse);
8063
8064         free(disrequest);
8065
8066         free(disresponse);
8067
8068         freebusdevlist(&devlist);
8069
8070         return (retval);
8071 }
8072
8073 static int
8074 atapm(struct cam_device *device, int argc, char **argv,
8075                  char *combinedopt, int retry_count, int timeout)
8076 {
8077         union ccb *ccb;
8078         int retval = 0;
8079         int t = -1;
8080         int c;
8081         u_char cmd, sc;
8082
8083         ccb = cam_getccb(device);
8084
8085         if (ccb == NULL) {
8086                 warnx("%s: error allocating ccb", __func__);
8087                 return (1);
8088         }
8089
8090         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8091                 switch (c) {
8092                 case 't':
8093                         t = atoi(optarg);
8094                         break;
8095                 default:
8096                         break;
8097                 }
8098         }
8099         if (strcmp(argv[1], "idle") == 0) {
8100                 if (t == -1)
8101                         cmd = ATA_IDLE_IMMEDIATE;
8102                 else
8103                         cmd = ATA_IDLE_CMD;
8104         } else if (strcmp(argv[1], "standby") == 0) {
8105                 if (t == -1)
8106                         cmd = ATA_STANDBY_IMMEDIATE;
8107                 else
8108                         cmd = ATA_STANDBY_CMD;
8109         } else {
8110                 cmd = ATA_SLEEP;
8111                 t = -1;
8112         }
8113
8114         if (t < 0)
8115                 sc = 0;
8116         else if (t <= (240 * 5))
8117                 sc = (t + 4) / 5;
8118         else if (t <= (252 * 5))
8119                 /* special encoding for 21 minutes */
8120                 sc = 252;
8121         else if (t <= (11 * 30 * 60))
8122                 sc = (t - 1) / (30 * 60) + 241;
8123         else
8124                 sc = 253;
8125
8126         retval = ata_do_28bit_cmd(device,
8127             ccb,
8128             /*retries*/retry_count,
8129             /*flags*/CAM_DIR_NONE,
8130             /*protocol*/AP_PROTO_NON_DATA,
8131             /*tag_action*/MSG_SIMPLE_Q_TAG,
8132             /*command*/cmd,
8133             /*features*/0,
8134             /*lba*/0,
8135             /*sector_count*/sc,
8136             /*data_ptr*/NULL,
8137             /*dxfer_len*/0,
8138             /*timeout*/timeout ? timeout : 30 * 1000,
8139             /*quiet*/1);
8140
8141         cam_freeccb(ccb);
8142         return (retval);
8143 }
8144
8145 static int
8146 ataaxm(struct cam_device *device, int argc, char **argv,
8147                  char *combinedopt, int retry_count, int timeout)
8148 {
8149         union ccb *ccb;
8150         int retval = 0;
8151         int l = -1;
8152         int c;
8153         u_char cmd, sc;
8154
8155         ccb = cam_getccb(device);
8156
8157         if (ccb == NULL) {
8158                 warnx("%s: error allocating ccb", __func__);
8159                 return (1);
8160         }
8161
8162         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8163                 switch (c) {
8164                 case 'l':
8165                         l = atoi(optarg);
8166                         break;
8167                 default:
8168                         break;
8169                 }
8170         }
8171         sc = 0;
8172         if (strcmp(argv[1], "apm") == 0) {
8173                 if (l == -1)
8174                         cmd = 0x85;
8175                 else {
8176                         cmd = 0x05;
8177                         sc = l;
8178                 }
8179         } else /* aam */ {
8180                 if (l == -1)
8181                         cmd = 0xC2;
8182                 else {
8183                         cmd = 0x42;
8184                         sc = l;
8185                 }
8186         }
8187
8188         retval = ata_do_28bit_cmd(device,
8189             ccb,
8190             /*retries*/retry_count,
8191             /*flags*/CAM_DIR_NONE,
8192             /*protocol*/AP_PROTO_NON_DATA,
8193             /*tag_action*/MSG_SIMPLE_Q_TAG,
8194             /*command*/ATA_SETFEATURES,
8195             /*features*/cmd,
8196             /*lba*/0,
8197             /*sector_count*/sc,
8198             /*data_ptr*/NULL,
8199             /*dxfer_len*/0,
8200             /*timeout*/timeout ? timeout : 30 * 1000,
8201             /*quiet*/1);
8202
8203         cam_freeccb(ccb);
8204         return (retval);
8205 }
8206
8207 int
8208 scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8209                int show_sa_errors, int sa_set, int service_action,
8210                int timeout_desc, int retry_count, int timeout, int verbosemode,
8211                uint32_t *fill_len, uint8_t **data_ptr)
8212 {
8213         union ccb *ccb = NULL;
8214         uint8_t *buf = NULL;
8215         uint32_t alloc_len = 0, num_opcodes;
8216         uint32_t valid_len = 0;
8217         uint32_t avail_len = 0;
8218         struct scsi_report_supported_opcodes_all *all_hdr;
8219         struct scsi_report_supported_opcodes_one *one;
8220         int options = 0;
8221         int retval = 0;
8222
8223         /*
8224          * Make it clear that we haven't yet allocated or filled anything.
8225          */
8226         *fill_len = 0;
8227         *data_ptr = NULL;
8228
8229         ccb = cam_getccb(device);
8230         if (ccb == NULL) {
8231                 warnx("couldn't allocate CCB");
8232                 retval = 1;
8233                 goto bailout;
8234         }
8235
8236         /* cam_getccb cleans up the header, caller has to zero the payload */
8237         bzero(&(&ccb->ccb_h)[1],
8238               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
8239
8240         if (opcode_set != 0) {
8241                 options |= RSO_OPTIONS_OC;
8242                 num_opcodes = 1;
8243                 alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8244         } else {
8245                 num_opcodes = 256;
8246                 alloc_len = sizeof(*all_hdr) + (num_opcodes *
8247                     sizeof(struct scsi_report_supported_opcodes_descr));
8248         }
8249
8250         if (timeout_desc != 0) {
8251                 options |= RSO_RCTD;
8252                 alloc_len += num_opcodes *
8253                     sizeof(struct scsi_report_supported_opcodes_timeout);
8254         }
8255         
8256         if (sa_set != 0) {
8257                 options |= RSO_OPTIONS_OC_SA;
8258                 if (show_sa_errors != 0)
8259                         options &= ~RSO_OPTIONS_OC;
8260         }
8261
8262 retry_alloc:
8263         if (buf != NULL) {
8264                 free(buf);
8265                 buf = NULL;
8266         } 
8267
8268         buf = malloc(alloc_len);
8269         if (buf == NULL) {
8270                 warn("Unable to allocate %u bytes", alloc_len);
8271                 retval = 1;
8272                 goto bailout;
8273         }
8274         bzero(buf, alloc_len);
8275
8276         scsi_report_supported_opcodes(&ccb->csio,
8277                                       /*retries*/ retry_count,
8278                                       /*cbfcnp*/ NULL,
8279                                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
8280                                       /*options*/ options,
8281                                       /*req_opcode*/ opcode,
8282                                       /*req_service_action*/ service_action,
8283                                       /*data_ptr*/ buf,
8284                                       /*dxfer_len*/ alloc_len,
8285                                       /*sense_len*/ SSD_FULL_SIZE,
8286                                       /*timeout*/ timeout ? timeout : 10000);
8287
8288         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8289
8290         if (retry_count != 0)
8291                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
8292
8293         if (cam_send_ccb(device, ccb) < 0) {
8294                 perror("error sending REPORT SUPPORTED OPERATION CODES");
8295                 retval = 1;
8296                 goto bailout;
8297         }
8298
8299         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8300                 if (verbosemode != 0)
8301                         cam_error_print(device, ccb, CAM_ESF_ALL,
8302                                         CAM_EPF_ALL, stderr);
8303                 
8304                 retval = 1;
8305                 goto bailout;
8306         }
8307
8308         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
8309
8310         if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
8311          && (valid_len >= sizeof(*all_hdr))) {
8312                 all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
8313                 avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
8314         } else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
8315                 && (valid_len >= sizeof(*one))) {
8316                 uint32_t cdb_length;
8317
8318                 one = (struct scsi_report_supported_opcodes_one *)buf;
8319                 cdb_length = scsi_2btoul(one->cdb_length);
8320                 avail_len = sizeof(*one) + cdb_length;
8321                 if (one->support & RSO_ONE_CTDP) {
8322                         struct scsi_report_supported_opcodes_timeout *td;
8323
8324                         td = (struct scsi_report_supported_opcodes_timeout *)
8325                             &buf[avail_len];
8326                         if (valid_len >= (avail_len + sizeof(td->length))) {
8327                                 avail_len += scsi_2btoul(td->length) +
8328                                     sizeof(td->length);
8329                         } else {
8330                                 avail_len += sizeof(*td);
8331                         }
8332                 }
8333         }
8334
8335         /*
8336          * avail_len could be zero if we didn't get enough data back from
8337          * thet target to determine
8338          */
8339         if ((avail_len != 0)
8340          && (avail_len > valid_len)) {
8341                 alloc_len = avail_len;
8342                 goto retry_alloc;
8343         }
8344
8345         *fill_len = valid_len;
8346         *data_ptr = buf;
8347 bailout:
8348         if (retval != 0)
8349                 free(buf);
8350
8351         cam_freeccb(ccb);
8352
8353         return (retval);
8354 }
8355
8356 static int
8357 scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
8358                    int req_sa, uint8_t *buf, uint32_t valid_len)
8359 {
8360         struct scsi_report_supported_opcodes_one *one;
8361         struct scsi_report_supported_opcodes_timeout *td;
8362         uint32_t cdb_len = 0, td_len = 0;
8363         const char *op_desc = NULL;
8364         unsigned int i;
8365         int retval = 0;
8366
8367         one = (struct scsi_report_supported_opcodes_one *)buf;
8368
8369         /*
8370          * If we don't have the full single opcode descriptor, no point in
8371          * continuing.
8372          */
8373         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8374             cdb_length)) {
8375                 warnx("Only %u bytes returned, not enough to verify support",
8376                       valid_len);
8377                 retval = 1;
8378                 goto bailout;
8379         }
8380
8381         op_desc = scsi_op_desc(req_opcode, &device->inq_data);
8382
8383         printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
8384                req_opcode);
8385         if (sa_set != 0)
8386                 printf(", SA 0x%x", req_sa);
8387         printf(": ");
8388
8389         switch (one->support & RSO_ONE_SUP_MASK) {
8390         case RSO_ONE_SUP_UNAVAIL:
8391                 printf("No command support information currently available\n");
8392                 break;
8393         case RSO_ONE_SUP_NOT_SUP:
8394                 printf("Command not supported\n");
8395                 retval = 1;
8396                 goto bailout;
8397                 break; /*NOTREACHED*/
8398         case RSO_ONE_SUP_AVAIL:
8399                 printf("Command is supported, complies with a SCSI standard\n");
8400                 break;
8401         case RSO_ONE_SUP_VENDOR:
8402                 printf("Command is supported, vendor-specific "
8403                        "implementation\n");
8404                 break;
8405         default:
8406                 printf("Unknown command support flags 0x%#x\n",
8407                        one->support & RSO_ONE_SUP_MASK);
8408                 break;
8409         }
8410
8411         /*
8412          * If we don't have the CDB length, it isn't exactly an error, the
8413          * command probably isn't supported.
8414          */
8415         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8416             cdb_usage))
8417                 goto bailout;
8418
8419         cdb_len = scsi_2btoul(one->cdb_length);
8420
8421         /*
8422          * If our valid data doesn't include the full reported length,
8423          * return.  The caller should have detected this and adjusted his
8424          * allocation length to get all of the available data.
8425          */
8426         if (valid_len < sizeof(*one) + cdb_len) {
8427                 retval = 1;
8428                 goto bailout;
8429         }
8430
8431         /*
8432          * If all we have is the opcode, there is no point in printing out
8433          * the usage bitmap.
8434          */
8435         if (cdb_len <= 1) {
8436                 retval = 1;
8437                 goto bailout;
8438         }
8439
8440         printf("CDB usage bitmap:");
8441         for (i = 0; i < cdb_len; i++) {
8442                 printf(" %02x", one->cdb_usage[i]);
8443         }
8444         printf("\n");
8445
8446         /*
8447          * If we don't have a timeout descriptor, we're done.
8448          */
8449         if ((one->support & RSO_ONE_CTDP) == 0)
8450                 goto bailout;
8451
8452         /*
8453          * If we don't have enough valid length to include the timeout
8454          * descriptor length, we're done.
8455          */
8456         if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
8457                 goto bailout;
8458
8459         td = (struct scsi_report_supported_opcodes_timeout *)
8460             &buf[sizeof(*one) + cdb_len];
8461         td_len = scsi_2btoul(td->length);
8462         td_len += sizeof(td->length);
8463
8464         /*
8465          * If we don't have the full timeout descriptor, we're done.
8466          */
8467         if (td_len < sizeof(*td))
8468                 goto bailout;
8469
8470         /*
8471          * If we don't have enough valid length to contain the full timeout
8472          * descriptor, we're done.
8473          */
8474         if (valid_len < (sizeof(*one) + cdb_len + td_len))
8475                 goto bailout;
8476
8477         printf("Timeout information:\n");
8478         printf("Command-specific:    0x%02x\n", td->cmd_specific);
8479         printf("Nominal timeout:     %u seconds\n",
8480                scsi_4btoul(td->nominal_time));
8481         printf("Recommended timeout: %u seconds\n",
8482                scsi_4btoul(td->recommended_time));
8483
8484 bailout:
8485         return (retval);
8486 }
8487
8488 static int
8489 scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
8490                  uint32_t valid_len)
8491 {
8492         struct scsi_report_supported_opcodes_all *hdr;
8493         struct scsi_report_supported_opcodes_descr *desc;
8494         uint32_t avail_len = 0, used_len = 0;
8495         uint8_t *cur_ptr;
8496         int retval = 0;
8497
8498         if (valid_len < sizeof(*hdr)) {
8499                 warnx("%s: not enough returned data (%u bytes) opcode list",
8500                       __func__, valid_len);
8501                 retval = 1;
8502                 goto bailout;
8503         }
8504         hdr = (struct scsi_report_supported_opcodes_all *)buf;
8505         avail_len = scsi_4btoul(hdr->length);
8506         avail_len += sizeof(hdr->length);
8507         /*
8508          * Take the lesser of the amount of data the drive claims is
8509          * available, and the amount of data the HBA says was returned.
8510          */
8511         avail_len = MIN(avail_len, valid_len);
8512
8513         used_len = sizeof(hdr->length);
8514
8515         printf("%-6s %4s %8s ",
8516                "Opcode", "SA", "CDB len" );
8517
8518         if (td_req != 0)
8519                 printf("%5s %6s %6s ", "CS", "Nom", "Rec");
8520         printf(" Description\n");
8521
8522         while ((avail_len - used_len) > sizeof(*desc)) {
8523                 struct scsi_report_supported_opcodes_timeout *td;
8524                 uint32_t td_len;
8525                 const char *op_desc = NULL;
8526
8527                 cur_ptr = &buf[used_len];
8528                 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
8529
8530                 op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
8531                 if (op_desc == NULL)
8532                         op_desc = "UNKNOWN";
8533
8534                 printf("0x%02x   %#4x %8u ", desc->opcode,
8535                        scsi_2btoul(desc->service_action),
8536                        scsi_2btoul(desc->cdb_length));
8537
8538                 used_len += sizeof(*desc);
8539
8540                 if ((desc->flags & RSO_CTDP) == 0) {
8541                         printf(" %s\n", op_desc);
8542                         continue;
8543                 }
8544
8545                 /*
8546                  * If we don't have enough space to fit a timeout
8547                  * descriptor, then we're done.
8548                  */
8549                 if (avail_len - used_len < sizeof(*td)) {
8550                         used_len = avail_len;
8551                         printf(" %s\n", op_desc);
8552                         continue;
8553                 }
8554                 cur_ptr = &buf[used_len];
8555                 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
8556                 td_len = scsi_2btoul(td->length);
8557                 td_len += sizeof(td->length);
8558
8559                 used_len += td_len;
8560                 /*
8561                  * If the given timeout descriptor length is less than what
8562                  * we understand, skip it.
8563                  */
8564                 if (td_len < sizeof(*td)) {
8565                         printf(" %s\n", op_desc);
8566                         continue;
8567                 }
8568
8569                 printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
8570                        scsi_4btoul(td->nominal_time),
8571                        scsi_4btoul(td->recommended_time), op_desc);
8572         }
8573 bailout:
8574         return (retval);
8575 }
8576
8577 static int
8578 scsiopcodes(struct cam_device *device, int argc, char **argv,
8579             char *combinedopt, int retry_count, int timeout, int verbosemode)
8580 {
8581         int c;
8582         uint32_t opcode = 0, service_action = 0;
8583         int td_set = 0, opcode_set = 0, sa_set = 0;
8584         int show_sa_errors = 1;
8585         uint32_t valid_len = 0;
8586         uint8_t *buf = NULL;
8587         char *endptr;
8588         int retval = 0;
8589
8590         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8591                 switch (c) {
8592                 case 'N':
8593                         show_sa_errors = 0;
8594                         break;
8595                 case 'o':
8596                         opcode = strtoul(optarg, &endptr, 0);
8597                         if (*endptr != '\0') {
8598                                 warnx("Invalid opcode \"%s\", must be a number",
8599                                       optarg);
8600                                 retval = 1;
8601                                 goto bailout;
8602                         }
8603                         if (opcode > 0xff) {
8604                                 warnx("Invalid opcode 0x%#x, must be between"
8605                                       "0 and 0xff inclusive", opcode);
8606                                 retval = 1;
8607                                 goto bailout;
8608                         }
8609                         opcode_set = 1;
8610                         break;
8611                 case 's':
8612                         service_action = strtoul(optarg, &endptr, 0);
8613                         if (*endptr != '\0') {
8614                                 warnx("Invalid service action \"%s\", must "
8615                                       "be a number", optarg);
8616                                 retval = 1;
8617                                 goto bailout;
8618                         }
8619                         if (service_action > 0xffff) {
8620                                 warnx("Invalid service action 0x%#x, must "
8621                                       "be between 0 and 0xffff inclusive",
8622                                       service_action);
8623                                 retval = 1;
8624                         }
8625                         sa_set = 1;
8626                         break;
8627                 case 'T':
8628                         td_set = 1;
8629                         break;
8630                 default:
8631                         break;
8632                 }
8633         }
8634
8635         if ((sa_set != 0)
8636          && (opcode_set == 0)) {
8637                 warnx("You must specify an opcode with -o if a service "
8638                       "action is given");
8639                 retval = 1;
8640                 goto bailout;
8641         }
8642         retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
8643                                 sa_set, service_action, td_set, retry_count,
8644                                 timeout, verbosemode, &valid_len, &buf);
8645         if (retval != 0)
8646                 goto bailout;
8647
8648         if ((opcode_set != 0)
8649          || (sa_set != 0)) {
8650                 retval = scsiprintoneopcode(device, opcode, sa_set,
8651                                             service_action, buf, valid_len);
8652         } else {
8653                 retval = scsiprintopcodes(device, td_set, buf, valid_len);
8654         }
8655
8656 bailout:
8657         free(buf);
8658
8659         return (retval);
8660 }
8661
8662 #endif /* MINIMALISTIC */
8663
8664 void
8665 usage(int printlong)
8666 {
8667
8668         fprintf(printlong ? stdout : stderr,
8669 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
8670 "        camcontrol devlist    [-b] [-v]\n"
8671 #ifndef MINIMALISTIC
8672 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8673 "        camcontrol tur        [dev_id][generic args]\n"
8674 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
8675 "        camcontrol identify   [dev_id][generic args] [-v]\n"
8676 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8677 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8678 "                              [-q] [-s]\n"
8679 "        camcontrol start      [dev_id][generic args]\n"
8680 "        camcontrol stop       [dev_id][generic args]\n"
8681 "        camcontrol load       [dev_id][generic args]\n"
8682 "        camcontrol eject      [dev_id][generic args]\n"
8683 #endif /* MINIMALISTIC */
8684 "        camcontrol rescan     <all | bus[:target:lun]>\n"
8685 "        camcontrol reset      <all | bus[:target:lun]>\n"
8686 #ifndef MINIMALISTIC
8687 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
8688 "                              [-q][-s][-S offset][-X]\n"
8689 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
8690 "                              [-P pagectl][-e | -b][-d]\n"
8691 "        camcontrol cmd        [dev_id][generic args]\n"
8692 "                              <-a cmd [args] | -c cmd [args]>\n"
8693 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8694 "        camcontrol smpcmd     [dev_id][generic args]\n"
8695 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
8696 "        camcontrol smprg      [dev_id][generic args][-l]\n"
8697 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
8698 "                              [-o operation][-d name][-m rate][-M rate]\n"
8699 "                              [-T pp_timeout][-a enable|disable]\n"
8700 "                              [-A enable|disable][-s enable|disable]\n"
8701 "                              [-S enable|disable]\n"
8702 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8703 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8704 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
8705 "                              <all|bus[:target[:lun]]|off>\n"
8706 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
8707 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
8708 "                              [-D <enable|disable>][-M mode][-O offset]\n"
8709 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
8710 "                              [-U][-W bus_width]\n"
8711 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
8712 "        camcontrol sanitize   [dev_id][generic args]\n"
8713 "                              [-a overwrite|block|crypto|exitfailure]\n"
8714 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8715 "                              [-y]\n"
8716 "        camcontrol idle       [dev_id][generic args][-t time]\n"
8717 "        camcontrol standby    [dev_id][generic args][-t time]\n"
8718 "        camcontrol sleep      [dev_id][generic args]\n"
8719 "        camcontrol apm        [dev_id][generic args][-l level]\n"
8720 "        camcontrol aam        [dev_id][generic args][-l level]\n"
8721 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
8722 "                              [-s][-y]\n"
8723 "        camcontrol security   [dev_id][generic args]\n"
8724 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8725 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8726 "                              [-U <user|master>] [-y]\n"
8727 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8728 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
8729 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
8730 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8731 "                              [-s scope][-S][-T type][-U]\n"
8732 "        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
8733 "                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
8734 "                              [-p part][-s start][-T type][-V vol]\n"
8735 "        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
8736 "                              [-N][-T]\n"
8737 #endif /* MINIMALISTIC */
8738 "        camcontrol help\n");
8739         if (!printlong)
8740                 return;
8741 #ifndef MINIMALISTIC
8742         fprintf(stdout,
8743 "Specify one of the following options:\n"
8744 "devlist     list all CAM devices\n"
8745 "periphlist  list all CAM peripheral drivers attached to a device\n"
8746 "tur         send a test unit ready to the named device\n"
8747 "inquiry     send a SCSI inquiry command to the named device\n"
8748 "identify    send a ATA identify command to the named device\n"
8749 "reportluns  send a SCSI report luns command to the device\n"
8750 "readcap     send a SCSI read capacity command to the device\n"
8751 "start       send a Start Unit command to the device\n"
8752 "stop        send a Stop Unit command to the device\n"
8753 "load        send a Start Unit command to the device with the load bit set\n"
8754 "eject       send a Stop Unit command to the device with the eject bit set\n"
8755 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
8756 "reset       reset all busses, the given bus, or bus:target:lun\n"
8757 "defects     read the defect list of the specified device\n"
8758 "modepage    display or edit (-e) the given mode page\n"
8759 "cmd         send the given SCSI command, may need -i or -o as well\n"
8760 "smpcmd      send the given SMP command, requires -o and -i\n"
8761 "smprg       send the SMP Report General command\n"
8762 "smppc       send the SMP PHY Control command, requires -p\n"
8763 "smpphylist  display phys attached to a SAS expander\n"
8764 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
8765 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
8766 "tags        report or set the number of transaction slots for a device\n"
8767 "negotiate   report or set device negotiation parameters\n"
8768 "format      send the SCSI FORMAT UNIT command to the named device\n"
8769 "sanitize    send the SCSI SANITIZE command to the named device\n"
8770 "idle        send the ATA IDLE command to the named device\n"
8771 "standby     send the ATA STANDBY command to the named device\n"
8772 "sleep       send the ATA SLEEP command to the named device\n"
8773 "fwdownload  program firmware of the named device with the given image\n"
8774 "security    report or send ATA security commands to the named device\n"
8775 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8776 "attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
8777 "opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
8778 "help        this message\n"
8779 "Device Identifiers:\n"
8780 "bus:target        specify the bus and target, lun defaults to 0\n"
8781 "bus:target:lun    specify the bus, target and lun\n"
8782 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
8783 "Generic arguments:\n"
8784 "-v                be verbose, print out sense information\n"
8785 "-t timeout        command timeout in seconds, overrides default timeout\n"
8786 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
8787 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
8788 "-E                have the kernel attempt to perform SCSI error recovery\n"
8789 "-C count          specify the SCSI command retry count (needs -E to work)\n"
8790 "modepage arguments:\n"
8791 "-l                list all available mode pages\n"
8792 "-m page           specify the mode page to view or edit\n"
8793 "-e                edit the specified mode page\n"
8794 "-b                force view to binary mode\n"
8795 "-d                disable block descriptors for mode sense\n"
8796 "-P pgctl          page control field 0-3\n"
8797 "defects arguments:\n"
8798 "-f format         specify defect list format (block, bfi or phys)\n"
8799 "-G                get the grown defect list\n"
8800 "-P                get the permanent defect list\n"
8801 "inquiry arguments:\n"
8802 "-D                get the standard inquiry data\n"
8803 "-S                get the serial number\n"
8804 "-R                get the transfer rate, etc.\n"
8805 "reportluns arguments:\n"
8806 "-c                only report a count of available LUNs\n"
8807 "-l                only print out luns, and not a count\n"
8808 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
8809 "readcap arguments\n"
8810 "-b                only report the blocksize\n"
8811 "-h                human readable device size, base 2\n"
8812 "-H                human readable device size, base 10\n"
8813 "-N                print the number of blocks instead of last block\n"
8814 "-q                quiet, print numbers only\n"
8815 "-s                only report the last block/device size\n"
8816 "cmd arguments:\n"
8817 "-c cdb [args]     specify the SCSI CDB\n"
8818 "-i len fmt        specify input data and input data format\n"
8819 "-o len fmt [args] specify output data and output data fmt\n"
8820 "smpcmd arguments:\n"
8821 "-r len fmt [args] specify the SMP command to be sent\n"
8822 "-R len fmt [args] specify SMP response format\n"
8823 "smprg arguments:\n"
8824 "-l                specify the long response format\n"
8825 "smppc arguments:\n"
8826 "-p phy            specify the PHY to operate on\n"
8827 "-l                specify the long request/response format\n"
8828 "-o operation      specify the phy control operation\n"
8829 "-d name           set the attached device name\n"
8830 "-m rate           set the minimum physical link rate\n"
8831 "-M rate           set the maximum physical link rate\n"
8832 "-T pp_timeout     set the partial pathway timeout value\n"
8833 "-a enable|disable enable or disable SATA slumber\n"
8834 "-A enable|disable enable or disable SATA partial phy power\n"
8835 "-s enable|disable enable or disable SAS slumber\n"
8836 "-S enable|disable enable or disable SAS partial phy power\n"
8837 "smpphylist arguments:\n"
8838 "-l                specify the long response format\n"
8839 "-q                only print phys with attached devices\n"
8840 "smpmaninfo arguments:\n"
8841 "-l                specify the long response format\n"
8842 "debug arguments:\n"
8843 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
8844 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
8845 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
8846 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
8847 "tags arguments:\n"
8848 "-N tags           specify the number of tags to use for this device\n"
8849 "-q                be quiet, don't report the number of tags\n"
8850 "-v                report a number of tag-related parameters\n"
8851 "negotiate arguments:\n"
8852 "-a                send a test unit ready after negotiation\n"
8853 "-c                report/set current negotiation settings\n"
8854 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
8855 "-M mode           set ATA mode\n"
8856 "-O offset         set command delay offset\n"
8857 "-q                be quiet, don't report anything\n"
8858 "-R syncrate       synchronization rate in MHz\n"
8859 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
8860 "-U                report/set user negotiation settings\n"
8861 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
8862 "-v                also print a Path Inquiry CCB for the controller\n"
8863 "format arguments:\n"
8864 "-q                be quiet, don't print status messages\n"
8865 "-r                run in report only mode\n"
8866 "-w                don't send immediate format command\n"
8867 "-y                don't ask any questions\n"
8868 "sanitize arguments:\n"
8869 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
8870 "-c passes         overwrite passes to perform (1 to 31)\n"
8871 "-I                invert overwrite pattern after each pass\n"
8872 "-P pattern        path to overwrite pattern file\n"
8873 "-q                be quiet, don't print status messages\n"
8874 "-r                run in report only mode\n"
8875 "-U                run operation in unrestricted completion exit mode\n"
8876 "-w                don't send immediate sanitize command\n"
8877 "-y                don't ask any questions\n"
8878 "idle/standby arguments:\n"
8879 "-t <arg>          number of seconds before respective state.\n"
8880 "fwdownload arguments:\n"
8881 "-f fw_image       path to firmware image file\n"
8882 "-q                don't print informational messages, only errors\n"
8883 "-s                run in simulation mode\n"
8884 "-v                print info for every firmware segment sent to device\n"
8885 "-y                don't ask any questions\n"
8886 "security arguments:\n"
8887 "-d pwd            disable security using the given password for the selected\n"
8888 "                  user\n"
8889 "-e pwd            erase the device using the given pwd for the selected user\n"
8890 "-f                freeze the security configuration of the specified device\n"
8891 "-h pwd            enhanced erase the device using the given pwd for the\n"
8892 "                  selected user\n"
8893 "-k pwd            unlock the device using the given pwd for the selected\n"
8894 "                  user\n"
8895 "-l <high|maximum> specifies which security level to set: high or maximum\n"
8896 "-q                be quiet, do not print any status messages\n"
8897 "-s pwd            password the device (enable security) using the given\n"
8898 "                  pwd for the selected user\n"
8899 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
8900 "-U <user|master>  specifies which user to set: user or master\n"
8901 "-y                don't ask any questions\n"
8902 "hpa arguments:\n"
8903 "-f                freeze the HPA configuration of the device\n"
8904 "-l                lock the HPA configuration of the device\n"
8905 "-P                make the HPA max sectors persist\n"
8906 "-p pwd            Set the HPA configuration password required for unlock\n"
8907 "                  calls\n"
8908 "-q                be quiet, do not print any status messages\n"
8909 "-s sectors        configures the maximum user accessible sectors of the\n"
8910 "                  device\n"
8911 "-U pwd            unlock the HPA configuration of the device\n"
8912 "-y                don't ask any questions\n"
8913 "persist arguments:\n"
8914 "-i action         specify read_keys, read_reservation, report_cap, or\n"
8915 "                  read_full_status\n"
8916 "-o action         specify register, register_ignore, reserve, release,\n"
8917 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
8918 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
8919 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8920 "-k key            specify the Reservation Key\n"
8921 "-K sa_key         specify the Service Action Reservation Key\n"
8922 "-p                set the Activate Persist Through Power Loss bit\n"
8923 "-R rtp            specify the Relative Target Port\n"
8924 "-s scope          specify the scope: lun, extent, element or a number\n"
8925 "-S                specify Transport ID for register, requires -I\n"
8926 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8927 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8928 "-U                unregister the current initiator for register_move\n"
8929 "attrib arguments:\n"
8930 "-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
8931 "                  supp_attr\n"
8932 "-w attr           specify an attribute to write, one -w argument per attr\n"
8933 "-a attr_num       only display this attribute number\n"
8934 "-c                get cached attributes\n"
8935 "-e elem_addr      request attributes for the given element in a changer\n"
8936 "-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
8937 "                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
8938 "                  field_none, field_desc, field_num, field_size, field_rw\n"
8939 "-p partition      request attributes for the given partition\n"
8940 "-s start_attr     request attributes starting at the given number\n"
8941 "-T elem_type      specify the element type (used with -e)\n"
8942 "-V logical_vol    specify the logical volume ID\n"
8943 "opcodes arguments:\n"
8944 "-o opcode         specify the individual opcode to list\n"
8945 "-s service_action specify the service action for the opcode\n"
8946 "-N                do not return SCSI error for unsupported SA\n"
8947 "-T                request nominal and recommended timeout values\n"
8948 );
8949 #endif /* MINIMALISTIC */
8950 }
8951
8952 int
8953 main(int argc, char **argv)
8954 {
8955         int c;
8956         char *device = NULL;
8957         int unit = 0;
8958         struct cam_device *cam_dev = NULL;
8959         int timeout = 0, retry_count = 1;
8960         camcontrol_optret optreturn;
8961         char *tstr;
8962         const char *mainopt = "C:En:t:u:v";
8963         const char *subopt = NULL;
8964         char combinedopt[256];
8965         int error = 0, optstart = 2;
8966         int devopen = 1;
8967 #ifndef MINIMALISTIC
8968         path_id_t bus;
8969         target_id_t target;
8970         lun_id_t lun;
8971 #endif /* MINIMALISTIC */
8972
8973         cmdlist = CAM_CMD_NONE;
8974         arglist = CAM_ARG_NONE;
8975
8976         if (argc < 2) {
8977                 usage(0);
8978                 exit(1);
8979         }
8980
8981         /*
8982          * Get the base option.
8983          */
8984         optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8985
8986         if (optreturn == CC_OR_AMBIGUOUS) {
8987                 warnx("ambiguous option %s", argv[1]);
8988                 usage(0);
8989                 exit(1);
8990         } else if (optreturn == CC_OR_NOT_FOUND) {
8991                 warnx("option %s not found", argv[1]);
8992                 usage(0);
8993                 exit(1);
8994         }
8995
8996         /*
8997          * Ahh, getopt(3) is a pain.
8998          *
8999          * This is a gross hack.  There really aren't many other good
9000          * options (excuse the pun) for parsing options in a situation like
9001          * this.  getopt is kinda braindead, so you end up having to run
9002          * through the options twice, and give each invocation of getopt
9003          * the option string for the other invocation.
9004          *
9005          * You would think that you could just have two groups of options.
9006          * The first group would get parsed by the first invocation of
9007          * getopt, and the second group would get parsed by the second
9008          * invocation of getopt.  It doesn't quite work out that way.  When
9009          * the first invocation of getopt finishes, it leaves optind pointing
9010          * to the argument _after_ the first argument in the second group.
9011          * So when the second invocation of getopt comes around, it doesn't
9012          * recognize the first argument it gets and then bails out.
9013          *
9014          * A nice alternative would be to have a flag for getopt that says
9015          * "just keep parsing arguments even when you encounter an unknown
9016          * argument", but there isn't one.  So there's no real clean way to
9017          * easily parse two sets of arguments without having one invocation
9018          * of getopt know about the other.
9019          *
9020          * Without this hack, the first invocation of getopt would work as
9021          * long as the generic arguments are first, but the second invocation
9022          * (in the subfunction) would fail in one of two ways.  In the case
9023          * where you don't set optreset, it would fail because optind may be
9024          * pointing to the argument after the one it should be pointing at.
9025          * In the case where you do set optreset, and reset optind, it would
9026          * fail because getopt would run into the first set of options, which
9027          * it doesn't understand.
9028          *
9029          * All of this would "sort of" work if you could somehow figure out
9030          * whether optind had been incremented one option too far.  The
9031          * mechanics of that, however, are more daunting than just giving
9032          * both invocations all of the expect options for either invocation.
9033          *
9034          * Needless to say, I wouldn't mind if someone invented a better
9035          * (non-GPL!) command line parsing interface than getopt.  I
9036          * wouldn't mind if someone added more knobs to getopt to make it
9037          * work better.  Who knows, I may talk myself into doing it someday,
9038          * if the standards weenies let me.  As it is, it just leads to
9039          * hackery like this and causes people to avoid it in some cases.
9040          *
9041          * KDM, September 8th, 1998
9042          */
9043         if (subopt != NULL)
9044                 sprintf(combinedopt, "%s%s", mainopt, subopt);
9045         else
9046                 sprintf(combinedopt, "%s", mainopt);
9047
9048         /*
9049          * For these options we do not parse optional device arguments and
9050          * we do not open a passthrough device.
9051          */
9052         if ((cmdlist == CAM_CMD_RESCAN)
9053          || (cmdlist == CAM_CMD_RESET)
9054          || (cmdlist == CAM_CMD_DEVTREE)
9055          || (cmdlist == CAM_CMD_USAGE)
9056          || (cmdlist == CAM_CMD_DEBUG))
9057                 devopen = 0;
9058
9059 #ifndef MINIMALISTIC
9060         if ((devopen == 1)
9061          && (argc > 2 && argv[2][0] != '-')) {
9062                 char name[30];
9063                 int rv;
9064
9065                 if (isdigit(argv[2][0])) {
9066                         /* device specified as bus:target[:lun] */
9067                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9068                         if (rv < 2)
9069                                 errx(1, "numeric device specification must "
9070                                      "be either bus:target, or "
9071                                      "bus:target:lun");
9072                         /* default to 0 if lun was not specified */
9073                         if ((arglist & CAM_ARG_LUN) == 0) {
9074                                 lun = 0;
9075                                 arglist |= CAM_ARG_LUN;
9076                         }
9077                         optstart++;
9078                 } else {
9079                         if (cam_get_device(argv[2], name, sizeof name, &unit)
9080                             == -1)
9081                                 errx(1, "%s", cam_errbuf);
9082                         device = strdup(name);
9083                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9084                         optstart++;
9085                 }
9086         }
9087 #endif /* MINIMALISTIC */
9088         /*
9089          * Start getopt processing at argv[2/3], since we've already
9090          * accepted argv[1..2] as the command name, and as a possible
9091          * device name.
9092          */
9093         optind = optstart;
9094
9095         /*
9096          * Now we run through the argument list looking for generic
9097          * options, and ignoring options that possibly belong to
9098          * subfunctions.
9099          */
9100         while ((c = getopt(argc, argv, combinedopt))!= -1){
9101                 switch(c) {
9102                         case 'C':
9103                                 retry_count = strtol(optarg, NULL, 0);
9104                                 if (retry_count < 0)
9105                                         errx(1, "retry count %d is < 0",
9106                                              retry_count);
9107                                 arglist |= CAM_ARG_RETRIES;
9108                                 break;
9109                         case 'E':
9110                                 arglist |= CAM_ARG_ERR_RECOVER;
9111                                 break;
9112                         case 'n':
9113                                 arglist |= CAM_ARG_DEVICE;
9114                                 tstr = optarg;
9115                                 while (isspace(*tstr) && (*tstr != '\0'))
9116                                         tstr++;
9117                                 device = (char *)strdup(tstr);
9118                                 break;
9119                         case 't':
9120                                 timeout = strtol(optarg, NULL, 0);
9121                                 if (timeout < 0)
9122                                         errx(1, "invalid timeout %d", timeout);
9123                                 /* Convert the timeout from seconds to ms */
9124                                 timeout *= 1000;
9125                                 arglist |= CAM_ARG_TIMEOUT;
9126                                 break;
9127                         case 'u':
9128                                 arglist |= CAM_ARG_UNIT;
9129                                 unit = strtol(optarg, NULL, 0);
9130                                 break;
9131                         case 'v':
9132                                 arglist |= CAM_ARG_VERBOSE;
9133                                 break;
9134                         default:
9135                                 break;
9136                 }
9137         }
9138
9139 #ifndef MINIMALISTIC
9140         /*
9141          * For most commands we'll want to open the passthrough device
9142          * associated with the specified device.  In the case of the rescan
9143          * commands, we don't use a passthrough device at all, just the
9144          * transport layer device.
9145          */
9146         if (devopen == 1) {
9147                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
9148                  && (((arglist & CAM_ARG_DEVICE) == 0)
9149                   || ((arglist & CAM_ARG_UNIT) == 0))) {
9150                         errx(1, "subcommand \"%s\" requires a valid device "
9151                              "identifier", argv[1]);
9152                 }
9153
9154                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
9155                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
9156                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
9157                      == NULL)
9158                         errx(1,"%s", cam_errbuf);
9159         }
9160 #endif /* MINIMALISTIC */
9161
9162         /*
9163          * Reset optind to 2, and reset getopt, so these routines can parse
9164          * the arguments again.
9165          */
9166         optind = optstart;
9167         optreset = 1;
9168
9169         switch(cmdlist) {
9170 #ifndef MINIMALISTIC
9171                 case CAM_CMD_DEVLIST:
9172                         error = getdevlist(cam_dev);
9173                         break;
9174                 case CAM_CMD_HPA:
9175                         error = atahpa(cam_dev, retry_count, timeout,
9176                                        argc, argv, combinedopt);
9177                         break;
9178 #endif /* MINIMALISTIC */
9179                 case CAM_CMD_DEVTREE:
9180                         error = getdevtree(argc, argv, combinedopt);
9181                         break;
9182 #ifndef MINIMALISTIC
9183                 case CAM_CMD_TUR:
9184                         error = testunitready(cam_dev, retry_count, timeout, 0);
9185                         break;
9186                 case CAM_CMD_INQUIRY:
9187                         error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
9188                                               retry_count, timeout);
9189                         break;
9190                 case CAM_CMD_IDENTIFY:
9191                         error = ataidentify(cam_dev, retry_count, timeout);
9192                         break;
9193                 case CAM_CMD_STARTSTOP:
9194                         error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
9195                                           arglist & CAM_ARG_EJECT, retry_count,
9196                                           timeout);
9197                         break;
9198 #endif /* MINIMALISTIC */
9199                 case CAM_CMD_RESCAN:
9200                         error = dorescan_or_reset(argc, argv, 1);
9201                         break;
9202                 case CAM_CMD_RESET:
9203                         error = dorescan_or_reset(argc, argv, 0);
9204                         break;
9205 #ifndef MINIMALISTIC
9206                 case CAM_CMD_READ_DEFECTS:
9207                         error = readdefects(cam_dev, argc, argv, combinedopt,
9208                                             retry_count, timeout);
9209                         break;
9210                 case CAM_CMD_MODE_PAGE:
9211                         modepage(cam_dev, argc, argv, combinedopt,
9212                                  retry_count, timeout);
9213                         break;
9214                 case CAM_CMD_SCSI_CMD:
9215                         error = scsicmd(cam_dev, argc, argv, combinedopt,
9216                                         retry_count, timeout);
9217                         break;
9218                 case CAM_CMD_SMP_CMD:
9219                         error = smpcmd(cam_dev, argc, argv, combinedopt,
9220                                        retry_count, timeout);
9221                         break;
9222                 case CAM_CMD_SMP_RG:
9223                         error = smpreportgeneral(cam_dev, argc, argv,
9224                                                  combinedopt, retry_count,
9225                                                  timeout);
9226                         break;
9227                 case CAM_CMD_SMP_PC:
9228                         error = smpphycontrol(cam_dev, argc, argv, combinedopt, 
9229                                               retry_count, timeout);
9230                         break;
9231                 case CAM_CMD_SMP_PHYLIST:
9232                         error = smpphylist(cam_dev, argc, argv, combinedopt,
9233                                            retry_count, timeout);
9234                         break;
9235                 case CAM_CMD_SMP_MANINFO:
9236                         error = smpmaninfo(cam_dev, argc, argv, combinedopt,
9237                                            retry_count, timeout);
9238                         break;
9239                 case CAM_CMD_DEBUG:
9240                         error = camdebug(argc, argv, combinedopt);
9241                         break;
9242                 case CAM_CMD_TAG:
9243                         error = tagcontrol(cam_dev, argc, argv, combinedopt);
9244                         break;
9245                 case CAM_CMD_RATE:
9246                         error = ratecontrol(cam_dev, retry_count, timeout,
9247                                             argc, argv, combinedopt);
9248                         break;
9249                 case CAM_CMD_FORMAT:
9250                         error = scsiformat(cam_dev, argc, argv,
9251                                            combinedopt, retry_count, timeout);
9252                         break;
9253                 case CAM_CMD_REPORTLUNS:
9254                         error = scsireportluns(cam_dev, argc, argv,
9255                                                combinedopt, retry_count,
9256                                                timeout);
9257                         break;
9258                 case CAM_CMD_READCAP:
9259                         error = scsireadcapacity(cam_dev, argc, argv,
9260                                                  combinedopt, retry_count,
9261                                                  timeout);
9262                         break;
9263                 case CAM_CMD_IDLE:
9264                 case CAM_CMD_STANDBY:
9265                 case CAM_CMD_SLEEP:
9266                         error = atapm(cam_dev, argc, argv,
9267                                       combinedopt, retry_count, timeout);
9268                         break;
9269                 case CAM_CMD_APM:
9270                 case CAM_CMD_AAM:
9271                         error = ataaxm(cam_dev, argc, argv,
9272                                       combinedopt, retry_count, timeout);
9273                         break;
9274                 case CAM_CMD_SECURITY:
9275                         error = atasecurity(cam_dev, retry_count, timeout,
9276                                             argc, argv, combinedopt);
9277                         break;
9278                 case CAM_CMD_DOWNLOAD_FW:
9279                         error = fwdownload(cam_dev, argc, argv, combinedopt,
9280                             arglist & CAM_ARG_VERBOSE, retry_count, timeout);
9281                         break;
9282                 case CAM_CMD_SANITIZE:
9283                         error = scsisanitize(cam_dev, argc, argv,
9284                                              combinedopt, retry_count, timeout);
9285                         break;
9286                 case CAM_CMD_PERSIST:
9287                         error = scsipersist(cam_dev, argc, argv, combinedopt,
9288                             retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9289                             arglist & CAM_ARG_ERR_RECOVER);
9290                         break;
9291                 case CAM_CMD_ATTRIB:
9292                         error = scsiattrib(cam_dev, argc, argv, combinedopt,
9293                             retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9294                             arglist & CAM_ARG_ERR_RECOVER);
9295                         break;
9296                 case CAM_CMD_OPCODES:
9297                         error = scsiopcodes(cam_dev, argc, argv, combinedopt,
9298                             retry_count, timeout, arglist & CAM_ARG_VERBOSE);
9299                         break;
9300 #endif /* MINIMALISTIC */
9301                 case CAM_CMD_USAGE:
9302                         usage(1);
9303                         break;
9304                 default:
9305                         usage(0);
9306                         error = 1;
9307                         break;
9308         }
9309
9310         if (cam_dev != NULL)
9311                 cam_close_device(cam_dev);
9312
9313         exit(error);
9314 }