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