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