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