]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sbin/camcontrol/camcontrol.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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, setpwd, persist;
2572         int security, is48bit, pwdsize;
2573         u_int64_t hpasize, maxsize;
2574
2575         actions = 0;
2576         setpwd = 0;
2577         confirm = 0;
2578         quiet = 0;
2579         maxsize = 0;
2580         persist = 0;
2581         security = 0;
2582
2583         memset(&pwd, 0, sizeof(pwd));
2584
2585         /* default action is to print hpa information */
2586         action = ATA_HPA_ACTION_PRINT;
2587         pwdsize = sizeof(pwd.password);
2588
2589         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2590                 switch(c){
2591                 case 's':
2592                         action = ATA_HPA_ACTION_SET_MAX;
2593                         maxsize = strtoumax(optarg, NULL, 0);
2594                         actions++;
2595                         break;
2596
2597                 case 'p':
2598                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2599                                 return (1);
2600                         action = ATA_HPA_ACTION_SET_PWD;
2601                         security = 1;
2602                         actions++;
2603                         break;
2604
2605                 case 'l':
2606                         action = ATA_HPA_ACTION_LOCK;
2607                         security = 1;
2608                         actions++;
2609                         break;
2610
2611                 case 'U':
2612                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2613                                 return (1);
2614                         action = ATA_HPA_ACTION_UNLOCK;
2615                         security = 1;
2616                         actions++;
2617                         break;
2618
2619                 case 'f':
2620                         action = ATA_HPA_ACTION_FREEZE_LOCK;
2621                         security = 1;
2622                         actions++;
2623                         break;
2624
2625                 case 'P':
2626                         persist = 1;
2627                         break;
2628
2629                 case 'y':
2630                         confirm++;
2631                         break;
2632
2633                 case 'q':
2634                         quiet++;
2635                         break;
2636                 }
2637         }
2638
2639         if (actions > 1) {
2640                 warnx("too many hpa actions specified");
2641                 return (1);
2642         }
2643
2644         if (get_cgd(device, &cgd) != 0) {
2645                 warnx("couldn't get CGD");
2646                 return (1);
2647         }
2648
2649         ccb = cam_getccb(device);
2650         if (ccb == NULL) {
2651                 warnx("couldn't allocate CCB");
2652                 return (1);
2653         }
2654
2655         error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2656         if (error != 0) {
2657                 cam_freeccb(ccb);
2658                 return (1);
2659         }
2660
2661         if (quiet == 0) {
2662                 printf("%s%d: ", device->device_name, device->dev_unit_num);
2663                 ata_print_ident(ident_buf);
2664                 camxferrate(device);
2665         }
2666
2667         if (action == ATA_HPA_ACTION_PRINT) {
2668                 error = ata_read_native_max(device, retry_count, timeout, ccb,
2669                                             ident_buf, &hpasize);
2670                 if (error == 0)
2671                         atahpa_print(ident_buf, hpasize, 1);
2672
2673                 cam_freeccb(ccb);
2674                 free(ident_buf);
2675                 return (error);
2676         }
2677
2678         if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) {
2679                 warnx("HPA is not supported by this device");
2680                 cam_freeccb(ccb);
2681                 free(ident_buf);
2682                 return (1);
2683         }
2684
2685         if (security && !(ident_buf->support.command1 & ATA_SUPPORT_MAXSECURITY)) {
2686                 warnx("HPA Security is not supported by this device");
2687                 cam_freeccb(ccb);
2688                 free(ident_buf);
2689                 return (1);
2690         }
2691
2692         is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48;
2693
2694         /*
2695          * The ATA spec requires:
2696          * 1. Read native max addr is called directly before set max addr
2697          * 2. Read native max addr is NOT called before any other set max call
2698          */
2699         switch(action) {
2700         case ATA_HPA_ACTION_SET_MAX:
2701                 if (confirm == 0 &&
2702                     atahpa_set_confirm(device, ident_buf, maxsize,
2703                     persist) == 0) {
2704                         cam_freeccb(ccb);
2705                         free(ident_buf);
2706                         return (1);
2707                 }
2708
2709                 error = ata_read_native_max(device, retry_count, timeout,
2710                                             ccb, ident_buf, &hpasize);
2711                 if (error == 0) {
2712                         error = atahpa_set_max(device, retry_count, timeout,
2713                                                ccb, is48bit, maxsize, persist);
2714                         if (error == 0) {
2715                                 /* redo identify to get new lba values */
2716                                 error = ata_do_identify(device, retry_count,
2717                                                         timeout, ccb,
2718                                                         &ident_buf);
2719                                 atahpa_print(ident_buf, hpasize, 1);
2720                         }
2721                 }
2722                 break;
2723
2724         case ATA_HPA_ACTION_SET_PWD:
2725                 error = atahpa_password(device, retry_count, timeout,
2726                                         ccb, is48bit, &pwd);
2727                 if (error == 0)
2728                         printf("HPA password has been set\n");
2729                 break;
2730
2731         case ATA_HPA_ACTION_LOCK:
2732                 error = atahpa_lock(device, retry_count, timeout,
2733                                     ccb, is48bit);
2734                 if (error == 0)
2735                         printf("HPA has been locked\n");
2736                 break;
2737
2738         case ATA_HPA_ACTION_UNLOCK:
2739                 error = atahpa_unlock(device, retry_count, timeout,
2740                                       ccb, is48bit, &pwd);
2741                 if (error == 0)
2742                         printf("HPA has been unlocked\n");
2743                 break;
2744
2745         case ATA_HPA_ACTION_FREEZE_LOCK:
2746                 error = atahpa_freeze_lock(device, retry_count, timeout,
2747                                            ccb, is48bit);
2748                 if (error == 0)
2749                         printf("HPA has been frozen\n");
2750                 break;
2751
2752         default:
2753                 errx(1, "Option currently not supported");
2754         }
2755
2756         cam_freeccb(ccb);
2757         free(ident_buf);
2758
2759         return (error);
2760 }
2761
2762 static int
2763 atasecurity(struct cam_device *device, int retry_count, int timeout,
2764             int argc, char **argv, char *combinedopt)
2765 {
2766         union ccb *ccb;
2767         struct ata_params *ident_buf;
2768         int error, confirm, quiet, c, action, actions, setpwd;
2769         int security_enabled, erase_timeout, pwdsize;
2770         struct ata_security_password pwd;
2771
2772         actions = 0;
2773         setpwd = 0;
2774         erase_timeout = 0;
2775         confirm = 0;
2776         quiet = 0;
2777
2778         memset(&pwd, 0, sizeof(pwd));
2779
2780         /* default action is to print security information */
2781         action = ATA_SECURITY_ACTION_PRINT;
2782
2783         /* user is master by default as its safer that way */
2784         pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2785         pwdsize = sizeof(pwd.password);
2786
2787         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2788                 switch(c){
2789                 case 'f':
2790                         action = ATA_SECURITY_ACTION_FREEZE;
2791                         actions++;
2792                         break;
2793
2794                 case 'U':
2795                         if (strcasecmp(optarg, "user") == 0) {
2796                                 pwd.ctrl |= ATA_SECURITY_PASSWORD_USER;
2797                                 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER;
2798                         } else if (strcasecmp(optarg, "master") == 0) {
2799                                 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2800                                 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER;
2801                         } else {
2802                                 warnx("-U argument '%s' is invalid (must be "
2803                                       "'user' or 'master')", optarg);
2804                                 return (1);
2805                         }
2806                         break;
2807
2808                 case 'l':
2809                         if (strcasecmp(optarg, "high") == 0) {
2810                                 pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH;
2811                                 pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM;
2812                         } else if (strcasecmp(optarg, "maximum") == 0) {
2813                                 pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM;
2814                                 pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH;
2815                         } else {
2816                                 warnx("-l argument '%s' is unknown (must be "
2817                                       "'high' or 'maximum')", optarg);
2818                                 return (1);
2819                         }
2820                         break;
2821
2822                 case 'k':
2823                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2824                                 return (1);
2825                         action = ATA_SECURITY_ACTION_UNLOCK;
2826                         actions++;
2827                         break;
2828
2829                 case 'd':
2830                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2831                                 return (1);
2832                         action = ATA_SECURITY_ACTION_DISABLE;
2833                         actions++;
2834                         break;
2835
2836                 case 'e':
2837                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2838                                 return (1);
2839                         action = ATA_SECURITY_ACTION_ERASE;
2840                         actions++;
2841                         break;
2842
2843                 case 'h':
2844                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2845                                 return (1);
2846                         pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED;
2847                         action = ATA_SECURITY_ACTION_ERASE_ENHANCED;
2848                         actions++;
2849                         break;
2850
2851                 case 's':
2852                         if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2853                                 return (1);
2854                         setpwd = 1;
2855                         if (action == ATA_SECURITY_ACTION_PRINT)
2856                                 action = ATA_SECURITY_ACTION_SET_PASSWORD;
2857                         /*
2858                          * Don't increment action as this can be combined
2859                          * with other actions.
2860                          */
2861                         break;
2862
2863                 case 'y':
2864                         confirm++;
2865                         break;
2866
2867                 case 'q':
2868                         quiet++;
2869                         break;
2870
2871                 case 'T':
2872                         erase_timeout = atoi(optarg) * 1000;
2873                         break;
2874                 }
2875         }
2876
2877         if (actions > 1) {
2878                 warnx("too many security actions specified");
2879                 return (1);
2880         }
2881
2882         if ((ccb = cam_getccb(device)) == NULL) {
2883                 warnx("couldn't allocate CCB");
2884                 return (1);
2885         }
2886
2887         error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2888         if (error != 0) {
2889                 cam_freeccb(ccb);
2890                 return (1);
2891         }
2892
2893         if (quiet == 0) {
2894                 printf("%s%d: ", device->device_name, device->dev_unit_num);
2895                 ata_print_ident(ident_buf);
2896                 camxferrate(device);
2897         }
2898
2899         if (action == ATA_SECURITY_ACTION_PRINT) {
2900                 atasecurity_print(ident_buf);
2901                 free(ident_buf);
2902                 cam_freeccb(ccb);
2903                 return (0);
2904         }
2905
2906         if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) {
2907                 warnx("Security not supported");
2908                 free(ident_buf);
2909                 cam_freeccb(ccb);
2910                 return (1);
2911         }
2912
2913         /* default timeout 15 seconds the same as linux hdparm */
2914         timeout = timeout ? timeout : 15 * 1000;
2915
2916         security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED;
2917
2918         /* first set the password if requested */
2919         if (setpwd == 1) {
2920                 /* confirm we can erase before setting the password if erasing */
2921                 if (confirm == 0 &&
2922                     (action == ATA_SECURITY_ACTION_ERASE_ENHANCED ||
2923                     action == ATA_SECURITY_ACTION_ERASE) &&
2924                     atasecurity_erase_confirm(device, ident_buf) == 0) {
2925                         cam_freeccb(ccb);
2926                         free(ident_buf);
2927                         return (error);
2928                 }
2929
2930                 if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) {
2931                         pwd.revision = ident_buf->master_passwd_revision;
2932                         if (pwd.revision != 0 && pwd.revision != 0xfff &&
2933                             --pwd.revision == 0) {
2934                                 pwd.revision = 0xfffe;
2935                         }
2936                 }
2937                 error = atasecurity_set_password(device, ccb, retry_count,
2938                                                  timeout, &pwd, quiet);
2939                 if (error != 0) {
2940                         cam_freeccb(ccb);
2941                         free(ident_buf);
2942                         return (error);
2943                 }
2944                 security_enabled = 1;
2945         }
2946
2947         switch(action) {
2948         case ATA_SECURITY_ACTION_FREEZE:
2949                 error = atasecurity_freeze(device, ccb, retry_count,
2950                                            timeout, quiet);
2951                 break;
2952
2953         case ATA_SECURITY_ACTION_UNLOCK:
2954                 if (security_enabled) {
2955                         if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2956                                 error = atasecurity_unlock(device, ccb,
2957                                         retry_count, timeout, &pwd, quiet);
2958                         } else {
2959                                 warnx("Can't unlock, drive is not locked");
2960                                 error = 1;
2961                         }
2962                 } else {
2963                         warnx("Can't unlock, security is disabled");
2964                         error = 1;
2965                 }
2966                 break;
2967
2968         case ATA_SECURITY_ACTION_DISABLE:
2969                 if (security_enabled) {
2970                         /* First unlock the drive if its locked */
2971                         if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2972                                 error = atasecurity_unlock(device, ccb,
2973                                                            retry_count,
2974                                                            timeout,
2975                                                            &pwd,
2976                                                            quiet);
2977                         }
2978
2979                         if (error == 0) {
2980                                 error = atasecurity_disable(device,
2981                                                             ccb,
2982                                                             retry_count,
2983                                                             timeout,
2984                                                             &pwd,
2985                                                             quiet);
2986                         }
2987                 } else {
2988                         warnx("Can't disable security (already disabled)");
2989                         error = 1;
2990                 }
2991                 break;
2992
2993         case ATA_SECURITY_ACTION_ERASE:
2994                 if (security_enabled) {
2995                         if (erase_timeout == 0) {
2996                                 erase_timeout = atasecurity_erase_timeout_msecs(
2997                                     ident_buf->erase_time);
2998                         }
2999
3000                         error = atasecurity_erase(device, ccb, retry_count,
3001                                                   timeout, erase_timeout, &pwd,
3002                                                   quiet);
3003                 } else {
3004                         warnx("Can't secure erase (security is disabled)");
3005                         error = 1;
3006                 }
3007                 break;
3008
3009         case ATA_SECURITY_ACTION_ERASE_ENHANCED:
3010                 if (security_enabled) {
3011                         if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) {
3012                                 if (erase_timeout == 0) {
3013                                         erase_timeout =
3014                                             atasecurity_erase_timeout_msecs(
3015                                                 ident_buf->enhanced_erase_time);
3016                                 }
3017
3018                                 error = atasecurity_erase(device, ccb,
3019                                                           retry_count, timeout,
3020                                                           erase_timeout, &pwd,
3021                                                           quiet);
3022                         } else {
3023                                 warnx("Enhanced erase is not supported");
3024                                 error = 1;
3025                         }
3026                 } else {
3027                         warnx("Can't secure erase (enhanced), "
3028                               "(security is disabled)");
3029                         error = 1;
3030                 }
3031                 break;
3032         }
3033
3034         cam_freeccb(ccb);
3035         free(ident_buf);
3036
3037         return (error);
3038 }
3039 #endif /* MINIMALISTIC */
3040
3041 /*
3042  * Parse out a bus, or a bus, target and lun in the following
3043  * format:
3044  * bus
3045  * bus:target
3046  * bus:target:lun
3047  *
3048  * Returns the number of parsed components, or 0.
3049  */
3050 static int
3051 parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun,
3052     cam_argmask *arglst)
3053 {
3054         char *tmpstr;
3055         int convs = 0;
3056
3057         while (isspace(*tstr) && (*tstr != '\0'))
3058                 tstr++;
3059
3060         tmpstr = (char *)strtok(tstr, ":");
3061         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3062                 *bus = strtol(tmpstr, NULL, 0);
3063                 *arglst |= CAM_ARG_BUS;
3064                 convs++;
3065                 tmpstr = (char *)strtok(NULL, ":");
3066                 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3067                         *target = strtol(tmpstr, NULL, 0);
3068                         *arglst |= CAM_ARG_TARGET;
3069                         convs++;
3070                         tmpstr = (char *)strtok(NULL, ":");
3071                         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3072                                 *lun = strtol(tmpstr, NULL, 0);
3073                                 *arglst |= CAM_ARG_LUN;
3074                                 convs++;
3075                         }
3076                 }
3077         }
3078
3079         return convs;
3080 }
3081
3082 static int
3083 dorescan_or_reset(int argc, char **argv, int rescan)
3084 {
3085         static const char must[] =
3086                 "you must specify \"all\", a bus, or a bus:target:lun to %s";
3087         int rv, error = 0;
3088         path_id_t bus = CAM_BUS_WILDCARD;
3089         target_id_t target = CAM_TARGET_WILDCARD;
3090         lun_id_t lun = CAM_LUN_WILDCARD;
3091         char *tstr;
3092
3093         if (argc < 3) {
3094                 warnx(must, rescan? "rescan" : "reset");
3095                 return(1);
3096         }
3097
3098         tstr = argv[optind];
3099         while (isspace(*tstr) && (*tstr != '\0'))
3100                 tstr++;
3101         if (strncasecmp(tstr, "all", strlen("all")) == 0)
3102                 arglist |= CAM_ARG_BUS;
3103         else {
3104                 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
3105                 if (rv != 1 && rv != 3) {
3106                         warnx(must, rescan? "rescan" : "reset");
3107                         return(1);
3108                 }
3109         }
3110
3111         if ((arglist & CAM_ARG_BUS)
3112             && (arglist & CAM_ARG_TARGET)
3113             && (arglist & CAM_ARG_LUN))
3114                 error = scanlun_or_reset_dev(bus, target, lun, rescan);
3115         else
3116                 error = rescan_or_reset_bus(bus, rescan);
3117
3118         return(error);
3119 }
3120
3121 static int
3122 rescan_or_reset_bus(path_id_t bus, int rescan)
3123 {
3124         union ccb ccb, matchccb;
3125         int fd, retval;
3126         int bufsize;
3127
3128         retval = 0;
3129
3130         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3131                 warnx("error opening transport layer device %s", XPT_DEVICE);
3132                 warn("%s", XPT_DEVICE);
3133                 return(1);
3134         }
3135
3136         if (bus != CAM_BUS_WILDCARD) {
3137                 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3138                 ccb.ccb_h.path_id = bus;
3139                 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3140                 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3141                 ccb.crcn.flags = CAM_FLAG_NONE;
3142
3143                 /* run this at a low priority */
3144                 ccb.ccb_h.pinfo.priority = 5;
3145
3146                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3147                         warn("CAMIOCOMMAND ioctl failed");
3148                         close(fd);
3149                         return(1);
3150                 }
3151
3152                 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3153                         fprintf(stdout, "%s of bus %d was successful\n",
3154                             rescan ? "Re-scan" : "Reset", bus);
3155                 } else {
3156                         fprintf(stdout, "%s of bus %d returned error %#x\n",
3157                                 rescan ? "Re-scan" : "Reset", bus,
3158                                 ccb.ccb_h.status & CAM_STATUS_MASK);
3159                         retval = 1;
3160                 }
3161
3162                 close(fd);
3163                 return(retval);
3164
3165         }
3166
3167
3168         /*
3169          * The right way to handle this is to modify the xpt so that it can
3170          * handle a wildcarded bus in a rescan or reset CCB.  At the moment
3171          * that isn't implemented, so instead we enumerate the busses and
3172          * send the rescan or reset to those busses in the case where the
3173          * given bus is -1 (wildcard).  We don't send a rescan or reset
3174          * to the xpt bus; sending a rescan to the xpt bus is effectively a
3175          * no-op, sending a rescan to the xpt bus would result in a status of
3176          * CAM_REQ_INVALID.
3177          */
3178         bzero(&(&matchccb.ccb_h)[1],
3179               sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
3180         matchccb.ccb_h.func_code = XPT_DEV_MATCH;
3181         matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
3182         bufsize = sizeof(struct dev_match_result) * 20;
3183         matchccb.cdm.match_buf_len = bufsize;
3184         matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
3185         if (matchccb.cdm.matches == NULL) {
3186                 warnx("can't malloc memory for matches");
3187                 retval = 1;
3188                 goto bailout;
3189         }
3190         matchccb.cdm.num_matches = 0;
3191
3192         matchccb.cdm.num_patterns = 1;
3193         matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3194
3195         matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
3196                 matchccb.cdm.pattern_buf_len);
3197         if (matchccb.cdm.patterns == NULL) {
3198                 warnx("can't malloc memory for patterns");
3199                 retval = 1;
3200                 goto bailout;
3201         }
3202         matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
3203         matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3204
3205         do {
3206                 unsigned int i;
3207
3208                 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
3209                         warn("CAMIOCOMMAND ioctl failed");
3210                         retval = 1;
3211                         goto bailout;
3212                 }
3213
3214                 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
3215                  || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
3216                    && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
3217                         warnx("got CAM error %#x, CDM error %d\n",
3218                               matchccb.ccb_h.status, matchccb.cdm.status);
3219                         retval = 1;
3220                         goto bailout;
3221                 }
3222
3223                 for (i = 0; i < matchccb.cdm.num_matches; i++) {
3224                         struct bus_match_result *bus_result;
3225
3226                         /* This shouldn't happen. */
3227                         if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
3228                                 continue;
3229
3230                         bus_result = &matchccb.cdm.matches[i].result.bus_result;
3231
3232                         /*
3233                          * We don't want to rescan or reset the xpt bus.
3234                          * See above.
3235                          */
3236                         if (bus_result->path_id == CAM_XPT_PATH_ID)
3237                                 continue;
3238
3239                         ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3240                                                        XPT_RESET_BUS;
3241                         ccb.ccb_h.path_id = bus_result->path_id;
3242                         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3243                         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3244                         ccb.crcn.flags = CAM_FLAG_NONE;
3245
3246                         /* run this at a low priority */
3247                         ccb.ccb_h.pinfo.priority = 5;
3248
3249                         if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3250                                 warn("CAMIOCOMMAND ioctl failed");
3251                                 retval = 1;
3252                                 goto bailout;
3253                         }
3254
3255                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
3256                                 fprintf(stdout, "%s of bus %d was successful\n",
3257                                         rescan? "Re-scan" : "Reset",
3258                                         bus_result->path_id);
3259                         } else {
3260                                 /*
3261                                  * Don't bail out just yet, maybe the other
3262                                  * rescan or reset commands will complete
3263                                  * successfully.
3264                                  */
3265                                 fprintf(stderr, "%s of bus %d returned error "
3266                                         "%#x\n", rescan? "Re-scan" : "Reset",
3267                                         bus_result->path_id,
3268                                         ccb.ccb_h.status & CAM_STATUS_MASK);
3269                                 retval = 1;
3270                         }
3271                 }
3272         } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
3273                  && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
3274
3275 bailout:
3276
3277         if (fd != -1)
3278                 close(fd);
3279
3280         if (matchccb.cdm.patterns != NULL)
3281                 free(matchccb.cdm.patterns);
3282         if (matchccb.cdm.matches != NULL)
3283                 free(matchccb.cdm.matches);
3284
3285         return(retval);
3286 }
3287
3288 static int
3289 scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3290 {
3291         union ccb ccb;
3292         struct cam_device *device;
3293         int fd;
3294
3295         device = NULL;
3296
3297         if (bus == CAM_BUS_WILDCARD) {
3298                 warnx("invalid bus number %d", bus);
3299                 return(1);
3300         }
3301
3302         if (target == CAM_TARGET_WILDCARD) {
3303                 warnx("invalid target number %d", target);
3304                 return(1);
3305         }
3306
3307         if (lun == CAM_LUN_WILDCARD) {
3308                 warnx("invalid lun number %jx", (uintmax_t)lun);
3309                 return(1);
3310         }
3311
3312         fd = -1;
3313
3314         bzero(&ccb, sizeof(union ccb));
3315
3316         if (scan) {
3317                 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3318                         warnx("error opening transport layer device %s\n",
3319                             XPT_DEVICE);
3320                         warn("%s", XPT_DEVICE);
3321                         return(1);
3322                 }
3323         } else {
3324                 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3325                 if (device == NULL) {
3326                         warnx("%s", cam_errbuf);
3327                         return(1);
3328                 }
3329         }
3330
3331         ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3332         ccb.ccb_h.path_id = bus;
3333         ccb.ccb_h.target_id = target;
3334         ccb.ccb_h.target_lun = lun;
3335         ccb.ccb_h.timeout = 5000;
3336         ccb.crcn.flags = CAM_FLAG_NONE;
3337
3338         /* run this at a low priority */
3339         ccb.ccb_h.pinfo.priority = 5;
3340
3341         if (scan) {
3342                 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3343                         warn("CAMIOCOMMAND ioctl failed");
3344                         close(fd);
3345                         return(1);
3346                 }
3347         } else {
3348                 if (cam_send_ccb(device, &ccb) < 0) {
3349                         warn("error sending XPT_RESET_DEV CCB");
3350                         cam_close_device(device);
3351                         return(1);
3352                 }
3353         }
3354
3355         if (scan)
3356                 close(fd);
3357         else
3358                 cam_close_device(device);
3359
3360         /*
3361          * An error code of CAM_BDR_SENT is normal for a BDR request.
3362          */
3363         if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3364          || ((!scan)
3365           && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3366                 fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3367                     scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3368                 return(0);
3369         } else {
3370                 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3371                     scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3372                     ccb.ccb_h.status & CAM_STATUS_MASK);
3373                 return(1);
3374         }
3375 }
3376
3377 #ifndef MINIMALISTIC
3378
3379 static struct scsi_nv defect_list_type_map[] = {
3380         { "block", SRDD10_BLOCK_FORMAT },
3381         { "extbfi", SRDD10_EXT_BFI_FORMAT },
3382         { "extphys", SRDD10_EXT_PHYS_FORMAT },
3383         { "longblock", SRDD10_LONG_BLOCK_FORMAT },
3384         { "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3385         { "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3386 };
3387
3388 static int
3389 readdefects(struct cam_device *device, int argc, char **argv,
3390             char *combinedopt, int retry_count, int timeout)
3391 {
3392         union ccb *ccb = NULL;
3393         struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3394         struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3395         size_t hdr_size = 0, entry_size = 0;
3396         int use_12byte = 0;
3397         int hex_format = 0;
3398         u_int8_t *defect_list = NULL;
3399         u_int8_t list_format = 0;
3400         int list_type_set = 0;
3401         u_int32_t dlist_length = 0;
3402         u_int32_t returned_length = 0, valid_len = 0;
3403         u_int32_t num_returned = 0, num_valid = 0;
3404         u_int32_t max_possible_size = 0, hdr_max = 0;
3405         u_int32_t starting_offset = 0;
3406         u_int8_t returned_format, returned_type;
3407         unsigned int i;
3408         int summary = 0, quiet = 0;
3409         int c, error = 0;
3410         int lists_specified = 0;
3411         int get_length = 1, first_pass = 1;
3412         int mads = 0;
3413
3414         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3415                 switch(c){
3416                 case 'f':
3417                 {
3418                         scsi_nv_status status;
3419                         int entry_num = 0;
3420
3421                         status = scsi_get_nv(defect_list_type_map,
3422                             sizeof(defect_list_type_map) /
3423                             sizeof(defect_list_type_map[0]), optarg,
3424                             &entry_num, SCSI_NV_FLAG_IG_CASE);
3425
3426                         if (status == SCSI_NV_FOUND) {
3427                                 list_format = defect_list_type_map[
3428                                     entry_num].value;
3429                                 list_type_set = 1;
3430                         } else {
3431                                 warnx("%s: %s %s option %s", __func__,
3432                                     (status == SCSI_NV_AMBIGUOUS) ?
3433                                     "ambiguous" : "invalid", "defect list type",
3434                                     optarg);
3435                                 error = 1;
3436                                 goto defect_bailout;
3437                         }
3438                         break;
3439                 }
3440                 case 'G':
3441                         arglist |= CAM_ARG_GLIST;
3442                         break;
3443                 case 'P':
3444                         arglist |= CAM_ARG_PLIST;
3445                         break;
3446                 case 'q':
3447                         quiet = 1;
3448                         break;
3449                 case 's':
3450                         summary = 1;
3451                         break;
3452                 case 'S': {
3453                         char *endptr;
3454
3455                         starting_offset = strtoul(optarg, &endptr, 0);
3456                         if (*endptr != '\0') {
3457                                 error = 1;
3458                                 warnx("invalid starting offset %s", optarg);
3459                                 goto defect_bailout;
3460                         }
3461                         break;
3462                 }
3463                 case 'X':
3464                         hex_format = 1;
3465                         break;
3466                 default:
3467                         break;
3468                 }
3469         }
3470
3471         if (list_type_set == 0) {
3472                 error = 1;
3473                 warnx("no defect list format specified");
3474                 goto defect_bailout;
3475         }
3476
3477         if (arglist & CAM_ARG_PLIST) {
3478                 list_format |= SRDD10_PLIST;
3479                 lists_specified++;
3480         }
3481
3482         if (arglist & CAM_ARG_GLIST) {
3483                 list_format |= SRDD10_GLIST;
3484                 lists_specified++;
3485         }
3486
3487         /*
3488          * This implies a summary, and was the previous behavior.
3489          */
3490         if (lists_specified == 0)
3491                 summary = 1;
3492
3493         ccb = cam_getccb(device);
3494
3495 retry_12byte:
3496
3497         /*
3498          * We start off asking for just the header to determine how much
3499          * defect data is available.  Some Hitachi drives return an error
3500          * if you ask for more data than the drive has.  Once we know the
3501          * length, we retry the command with the returned length.
3502          */
3503         if (use_12byte == 0)
3504                 dlist_length = sizeof(*hdr10);
3505         else
3506                 dlist_length = sizeof(*hdr12);
3507
3508 retry:
3509         if (defect_list != NULL) {
3510                 free(defect_list);
3511                 defect_list = NULL;
3512         }
3513         defect_list = malloc(dlist_length);
3514         if (defect_list == NULL) {
3515                 warnx("can't malloc memory for defect list");
3516                 error = 1;
3517                 goto defect_bailout;
3518         }
3519
3520 next_batch:
3521         bzero(defect_list, dlist_length);
3522
3523         /*
3524          * cam_getccb() zeros the CCB header only.  So we need to zero the
3525          * payload portion of the ccb.
3526          */
3527         bzero(&(&ccb->ccb_h)[1],
3528               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3529
3530         scsi_read_defects(&ccb->csio,
3531                           /*retries*/ retry_count,
3532                           /*cbfcnp*/ NULL,
3533                           /*tag_action*/ MSG_SIMPLE_Q_TAG,
3534                           /*list_format*/ list_format,
3535                           /*addr_desc_index*/ starting_offset,
3536                           /*data_ptr*/ defect_list,
3537                           /*dxfer_len*/ dlist_length,
3538                           /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3539                           /*sense_len*/ SSD_FULL_SIZE,
3540                           /*timeout*/ timeout ? timeout : 5000);
3541
3542         /* Disable freezing the device queue */
3543         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3544
3545         if (cam_send_ccb(device, ccb) < 0) {
3546                 perror("error reading defect list");
3547
3548                 if (arglist & CAM_ARG_VERBOSE) {
3549                         cam_error_print(device, ccb, CAM_ESF_ALL,
3550                                         CAM_EPF_ALL, stderr);
3551                 }
3552
3553                 error = 1;
3554                 goto defect_bailout;
3555         }
3556
3557         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3558
3559         if (use_12byte == 0) {
3560                 hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3561                 hdr_size = sizeof(*hdr10);
3562                 hdr_max = SRDDH10_MAX_LENGTH;
3563
3564                 if (valid_len >= hdr_size) {
3565                         returned_length = scsi_2btoul(hdr10->length);
3566                         returned_format = hdr10->format;
3567                 } else {
3568                         returned_length = 0;
3569                         returned_format = 0;
3570                 }
3571         } else {
3572                 hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3573                 hdr_size = sizeof(*hdr12);
3574                 hdr_max = SRDDH12_MAX_LENGTH;
3575
3576                 if (valid_len >= hdr_size) {
3577                         returned_length = scsi_4btoul(hdr12->length);
3578                         returned_format = hdr12->format;
3579                 } else {
3580                         returned_length = 0;
3581                         returned_format = 0;
3582                 }
3583         }
3584
3585         returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3586         switch (returned_type) {
3587         case SRDD10_BLOCK_FORMAT:
3588                 entry_size = sizeof(struct scsi_defect_desc_block);
3589                 break;
3590         case SRDD10_LONG_BLOCK_FORMAT:
3591                 entry_size = sizeof(struct scsi_defect_desc_long_block);
3592                 break;
3593         case SRDD10_EXT_PHYS_FORMAT:
3594         case SRDD10_PHYSICAL_SECTOR_FORMAT:
3595                 entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3596                 break;
3597         case SRDD10_EXT_BFI_FORMAT:
3598         case SRDD10_BYTES_FROM_INDEX_FORMAT:
3599                 entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3600                 break;
3601         default:
3602                 warnx("Unknown defect format 0x%x\n", returned_type);
3603                 error = 1;
3604                 goto defect_bailout;
3605                 break;
3606         } 
3607
3608         max_possible_size = (hdr_max / entry_size) * entry_size;
3609         num_returned = returned_length / entry_size;
3610         num_valid = min(returned_length, valid_len - hdr_size);
3611         num_valid /= entry_size;
3612
3613         if (get_length != 0) {
3614                 get_length = 0;
3615
3616                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3617                      CAM_SCSI_STATUS_ERROR) {
3618                         struct scsi_sense_data *sense;
3619                         int error_code, sense_key, asc, ascq;
3620
3621                         sense = &ccb->csio.sense_data;
3622                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
3623                             ccb->csio.sense_resid, &error_code, &sense_key,
3624                             &asc, &ascq, /*show_errors*/ 1);
3625
3626                         /*
3627                          * If the drive is reporting that it just doesn't
3628                          * support the defect list format, go ahead and use
3629                          * the length it reported.  Otherwise, the length
3630                          * may not be valid, so use the maximum.
3631                          */
3632                         if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3633                          && (asc == 0x1c) && (ascq == 0x00)
3634                          && (returned_length > 0)) {
3635                                 if ((use_12byte == 0)
3636                                  && (returned_length >= max_possible_size)) {
3637                                         get_length = 1;
3638                                         use_12byte = 1;
3639                                         goto retry_12byte;
3640                                 }
3641                                 dlist_length = returned_length + hdr_size;
3642                         } else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3643                                 && (asc == 0x1f) && (ascq == 0x00)
3644                                 && (returned_length > 0)) {
3645                                 /* Partial defect list transfer */
3646                                 /*
3647                                  * Hitachi drives return this error
3648                                  * along with a partial defect list if they
3649                                  * have more defects than the 10 byte
3650                                  * command can support.  Retry with the 12
3651                                  * byte command.
3652                                  */
3653                                 if (use_12byte == 0) {
3654                                         get_length = 1;
3655                                         use_12byte = 1;
3656                                         goto retry_12byte;
3657                                 }
3658                                 dlist_length = returned_length + hdr_size;
3659                         } else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3660                                 && (asc == 0x24) && (ascq == 0x00)) {
3661                                 /* Invalid field in CDB */
3662                                 /*
3663                                  * SBC-3 says that if the drive has more
3664                                  * defects than can be reported with the
3665                                  * 10 byte command, it should return this
3666                                  * error and no data.  Retry with the 12
3667                                  * byte command.
3668                                  */
3669                                 if (use_12byte == 0) {
3670                                         get_length = 1;
3671                                         use_12byte = 1;
3672                                         goto retry_12byte;
3673                                 }
3674                                 dlist_length = returned_length + hdr_size;
3675                         } else {
3676                                 /*
3677                                  * If we got a SCSI error and no valid length,
3678                                  * just use the 10 byte maximum.  The 12
3679                                  * byte maximum is too large.
3680                                  */
3681                                 if (returned_length == 0)
3682                                         dlist_length = SRDD10_MAX_LENGTH;
3683                                 else {
3684                                         if ((use_12byte == 0)
3685                                          && (returned_length >=
3686                                              max_possible_size)) {
3687                                                 get_length = 1;
3688                                                 use_12byte = 1;
3689                                                 goto retry_12byte;
3690                                         }
3691                                         dlist_length = returned_length +
3692                                             hdr_size;
3693                                 }
3694                         }
3695                 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3696                             CAM_REQ_CMP){
3697                         error = 1;
3698                         warnx("Error reading defect header");
3699                         if (arglist & CAM_ARG_VERBOSE)
3700                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3701                                                 CAM_EPF_ALL, stderr);
3702                         goto defect_bailout;
3703                 } else {
3704                         if ((use_12byte == 0)
3705                          && (returned_length >= max_possible_size)) {
3706                                 get_length = 1;
3707                                 use_12byte = 1;
3708                                 goto retry_12byte;
3709                         }
3710                         dlist_length = returned_length + hdr_size;
3711                 }
3712                 if (summary != 0) {
3713                         fprintf(stdout, "%u", num_returned);
3714                         if (quiet == 0) {
3715                                 fprintf(stdout, " defect%s",
3716                                         (num_returned != 1) ? "s" : "");
3717                         }
3718                         fprintf(stdout, "\n");
3719
3720                         goto defect_bailout;
3721                 }
3722
3723                 /*
3724                  * We always limit the list length to the 10-byte maximum
3725                  * length (0xffff).  The reason is that some controllers
3726                  * can't handle larger I/Os, and we can transfer the entire
3727                  * 10 byte list in one shot.  For drives that support the 12
3728                  * byte read defects command, we'll step through the list
3729                  * by specifying a starting offset.  For drives that don't
3730                  * support the 12 byte command's starting offset, we'll
3731                  * just display the first 64K.
3732                  */
3733                 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3734
3735                 goto retry;
3736         }
3737
3738
3739         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3740          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3741          && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3742                 struct scsi_sense_data *sense;
3743                 int error_code, sense_key, asc, ascq;
3744
3745                 sense = &ccb->csio.sense_data;
3746                 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3747                     ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3748                     &ascq, /*show_errors*/ 1);
3749
3750                 /*
3751                  * According to the SCSI spec, if the disk doesn't support
3752                  * the requested format, it will generally return a sense
3753                  * key of RECOVERED ERROR, and an additional sense code
3754                  * of "DEFECT LIST NOT FOUND".  HGST drives also return
3755                  * Primary/Grown defect list not found errors.  So just
3756                  * check for an ASC of 0x1c.
3757                  */
3758                 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3759                  && (asc == 0x1c)) {
3760                         const char *format_str;
3761
3762                         format_str = scsi_nv_to_str(defect_list_type_map,
3763                             sizeof(defect_list_type_map) /
3764                             sizeof(defect_list_type_map[0]),
3765                             list_format & SRDD10_DLIST_FORMAT_MASK);
3766                         warnx("requested defect format %s not available",
3767                             format_str ? format_str : "unknown");
3768
3769                         format_str = scsi_nv_to_str(defect_list_type_map,
3770                             sizeof(defect_list_type_map) /
3771                             sizeof(defect_list_type_map[0]), returned_type);
3772                         if (format_str != NULL) {
3773                                 warnx("Device returned %s format",
3774                                     format_str);
3775                         } else {
3776                                 error = 1;
3777                                 warnx("Device returned unknown defect"
3778                                      " data format %#x", returned_type);
3779                                 goto defect_bailout;
3780                         }
3781                 } else {
3782                         error = 1;
3783                         warnx("Error returned from read defect data command");
3784                         if (arglist & CAM_ARG_VERBOSE)
3785                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3786                                                 CAM_EPF_ALL, stderr);
3787                         goto defect_bailout;
3788                 }
3789         } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3790                 error = 1;
3791                 warnx("Error returned from read defect data command");
3792                 if (arglist & CAM_ARG_VERBOSE)
3793                         cam_error_print(device, ccb, CAM_ESF_ALL,
3794                                         CAM_EPF_ALL, stderr);
3795                 goto defect_bailout;
3796         }
3797
3798         if (first_pass != 0) {
3799                 fprintf(stderr, "Got %d defect", num_returned);
3800
3801                 if ((lists_specified == 0) || (num_returned == 0)) {
3802                         fprintf(stderr, "s.\n");
3803                         goto defect_bailout;
3804                 } else if (num_returned == 1)
3805                         fprintf(stderr, ":\n");
3806                 else
3807                         fprintf(stderr, "s:\n");
3808
3809                 first_pass = 0;
3810         }
3811
3812         /*
3813          * XXX KDM  I should probably clean up the printout format for the
3814          * disk defects.
3815          */
3816         switch (returned_type) {
3817         case SRDD10_PHYSICAL_SECTOR_FORMAT:
3818         case SRDD10_EXT_PHYS_FORMAT:
3819         {
3820                 struct scsi_defect_desc_phys_sector *dlist;
3821
3822                 dlist = (struct scsi_defect_desc_phys_sector *)
3823                         (defect_list + hdr_size);
3824
3825                 for (i = 0; i < num_valid; i++) {
3826                         uint32_t sector;
3827
3828                         sector = scsi_4btoul(dlist[i].sector);
3829                         if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
3830                                 mads = (sector & SDD_EXT_PHYS_MADS) ?
3831                                        0 : 1;
3832                                 sector &= ~SDD_EXT_PHYS_FLAG_MASK;
3833                         }
3834                         if (hex_format == 0)
3835                                 fprintf(stdout, "%d:%d:%d%s",
3836                                         scsi_3btoul(dlist[i].cylinder),
3837                                         dlist[i].head,
3838                                         scsi_4btoul(dlist[i].sector),
3839                                         mads ? " - " : "\n");
3840                         else
3841                                 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3842                                         scsi_3btoul(dlist[i].cylinder),
3843                                         dlist[i].head,
3844                                         scsi_4btoul(dlist[i].sector),
3845                                         mads ? " - " : "\n");
3846                         mads = 0;
3847                 }
3848                 if (num_valid < num_returned) {
3849                         starting_offset += num_valid;
3850                         goto next_batch;
3851                 }
3852                 break;
3853         }
3854         case SRDD10_BYTES_FROM_INDEX_FORMAT:
3855         case SRDD10_EXT_BFI_FORMAT:
3856         {
3857                 struct scsi_defect_desc_bytes_from_index *dlist;
3858
3859                 dlist = (struct scsi_defect_desc_bytes_from_index *)
3860                         (defect_list + hdr_size);
3861
3862                 for (i = 0; i < num_valid; i++) {
3863                         uint32_t bfi;
3864
3865                         bfi = scsi_4btoul(dlist[i].bytes_from_index);
3866                         if (returned_type == SRDD10_EXT_BFI_FORMAT) {
3867                                 mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
3868                                 bfi &= ~SDD_EXT_BFI_FLAG_MASK;
3869                         }
3870                         if (hex_format == 0)
3871                                 fprintf(stdout, "%d:%d:%d%s",
3872                                         scsi_3btoul(dlist[i].cylinder),
3873                                         dlist[i].head,
3874                                         scsi_4btoul(dlist[i].bytes_from_index),
3875                                         mads ? " - " : "\n");
3876                         else
3877                                 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3878                                         scsi_3btoul(dlist[i].cylinder),
3879                                         dlist[i].head,
3880                                         scsi_4btoul(dlist[i].bytes_from_index),
3881                                         mads ? " - " : "\n");
3882
3883                         mads = 0;
3884                 }
3885                 if (num_valid < num_returned) {
3886                         starting_offset += num_valid;
3887                         goto next_batch;
3888                 }
3889                 break;
3890         }
3891         case SRDDH10_BLOCK_FORMAT:
3892         {
3893                 struct scsi_defect_desc_block *dlist;
3894
3895                 dlist = (struct scsi_defect_desc_block *)
3896                         (defect_list + hdr_size);
3897
3898                 for (i = 0; i < num_valid; i++) {
3899                         if (hex_format == 0)
3900                                 fprintf(stdout, "%u\n",
3901                                         scsi_4btoul(dlist[i].address));
3902                         else
3903                                 fprintf(stdout, "0x%x\n",
3904                                         scsi_4btoul(dlist[i].address));
3905                 }
3906
3907                 if (num_valid < num_returned) {
3908                         starting_offset += num_valid;
3909                         goto next_batch;
3910                 }
3911
3912                 break;
3913         }
3914         case SRDD10_LONG_BLOCK_FORMAT:
3915         {
3916                 struct scsi_defect_desc_long_block *dlist;
3917
3918                 dlist = (struct scsi_defect_desc_long_block *)
3919                         (defect_list + hdr_size);
3920
3921                 for (i = 0; i < num_valid; i++) {
3922                         if (hex_format == 0)
3923                                 fprintf(stdout, "%ju\n",
3924                                         (uintmax_t)scsi_8btou64(
3925                                         dlist[i].address));
3926                         else
3927                                 fprintf(stdout, "0x%jx\n",
3928                                         (uintmax_t)scsi_8btou64(
3929                                         dlist[i].address));
3930                 }
3931
3932                 if (num_valid < num_returned) {
3933                         starting_offset += num_valid;
3934                         goto next_batch;
3935                 }
3936                 break;
3937         }
3938         default:
3939                 fprintf(stderr, "Unknown defect format 0x%x\n",
3940                         returned_type);
3941                 error = 1;
3942                 break;
3943         }
3944 defect_bailout:
3945
3946         if (defect_list != NULL)
3947                 free(defect_list);
3948
3949         if (ccb != NULL)
3950                 cam_freeccb(ccb);
3951
3952         return(error);
3953 }
3954 #endif /* MINIMALISTIC */
3955
3956 #if 0
3957 void
3958 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3959 {
3960         union ccb *ccb;
3961
3962         ccb = cam_getccb(device);
3963
3964         cam_freeccb(ccb);
3965 }
3966 #endif
3967
3968 #ifndef MINIMALISTIC
3969 void
3970 mode_sense(struct cam_device *device, int mode_page, int page_control,
3971            int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3972 {
3973         union ccb *ccb;
3974         int retval;
3975
3976         ccb = cam_getccb(device);
3977
3978         if (ccb == NULL)
3979                 errx(1, "mode_sense: couldn't allocate CCB");
3980
3981         bzero(&(&ccb->ccb_h)[1],
3982               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3983
3984         scsi_mode_sense(&ccb->csio,
3985                         /* retries */ retry_count,
3986                         /* cbfcnp */ NULL,
3987                         /* tag_action */ MSG_SIMPLE_Q_TAG,
3988                         /* dbd */ dbd,
3989                         /* page_code */ page_control << 6,
3990                         /* page */ mode_page,
3991                         /* param_buf */ data,
3992                         /* param_len */ datalen,
3993                         /* sense_len */ SSD_FULL_SIZE,
3994                         /* timeout */ timeout ? timeout : 5000);
3995
3996         if (arglist & CAM_ARG_ERR_RECOVER)
3997                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3998
3999         /* Disable freezing the device queue */
4000         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4001
4002         if (((retval = cam_send_ccb(device, ccb)) < 0)
4003          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4004                 if (arglist & CAM_ARG_VERBOSE) {
4005                         cam_error_print(device, ccb, CAM_ESF_ALL,
4006                                         CAM_EPF_ALL, stderr);
4007                 }
4008                 cam_freeccb(ccb);
4009                 cam_close_device(device);
4010                 if (retval < 0)
4011                         err(1, "error sending mode sense command");
4012                 else
4013                         errx(1, "error sending mode sense command");
4014         }
4015
4016         cam_freeccb(ccb);
4017 }
4018
4019 void
4020 mode_select(struct cam_device *device, int save_pages, int retry_count,
4021            int timeout, u_int8_t *data, int datalen)
4022 {
4023         union ccb *ccb;
4024         int retval;
4025
4026         ccb = cam_getccb(device);
4027
4028         if (ccb == NULL)
4029                 errx(1, "mode_select: couldn't allocate CCB");
4030
4031         bzero(&(&ccb->ccb_h)[1],
4032               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4033
4034         scsi_mode_select(&ccb->csio,
4035                          /* retries */ retry_count,
4036                          /* cbfcnp */ NULL,
4037                          /* tag_action */ MSG_SIMPLE_Q_TAG,
4038                          /* scsi_page_fmt */ 1,
4039                          /* save_pages */ save_pages,
4040                          /* param_buf */ data,
4041                          /* param_len */ datalen,
4042                          /* sense_len */ SSD_FULL_SIZE,
4043                          /* timeout */ timeout ? timeout : 5000);
4044
4045         if (arglist & CAM_ARG_ERR_RECOVER)
4046                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4047
4048         /* Disable freezing the device queue */
4049         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4050
4051         if (((retval = cam_send_ccb(device, ccb)) < 0)
4052          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4053                 if (arglist & CAM_ARG_VERBOSE) {
4054                         cam_error_print(device, ccb, CAM_ESF_ALL,
4055                                         CAM_EPF_ALL, stderr);
4056                 }
4057                 cam_freeccb(ccb);
4058                 cam_close_device(device);
4059
4060                 if (retval < 0)
4061                         err(1, "error sending mode select command");
4062                 else
4063                         errx(1, "error sending mode select command");
4064
4065         }
4066
4067         cam_freeccb(ccb);
4068 }
4069
4070 void
4071 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4072          int retry_count, int timeout)
4073 {
4074         int c, mode_page = -1, page_control = 0;
4075         int binary = 0, list = 0;
4076
4077         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4078                 switch(c) {
4079                 case 'b':
4080                         binary = 1;
4081                         break;
4082                 case 'd':
4083                         arglist |= CAM_ARG_DBD;
4084                         break;
4085                 case 'e':
4086                         arglist |= CAM_ARG_MODE_EDIT;
4087                         break;
4088                 case 'l':
4089                         list = 1;
4090                         break;
4091                 case 'm':
4092                         mode_page = strtol(optarg, NULL, 0);
4093                         if (mode_page < 0)
4094                                 errx(1, "invalid mode page %d", mode_page);
4095                         break;
4096                 case 'P':
4097                         page_control = strtol(optarg, NULL, 0);
4098                         if ((page_control < 0) || (page_control > 3))
4099                                 errx(1, "invalid page control field %d",
4100                                      page_control);
4101                         arglist |= CAM_ARG_PAGE_CNTL;
4102                         break;
4103                 default:
4104                         break;
4105                 }
4106         }
4107
4108         if (mode_page == -1 && list == 0)
4109                 errx(1, "you must specify a mode page!");
4110
4111         if (list) {
4112                 mode_list(device, page_control, arglist & CAM_ARG_DBD,
4113                     retry_count, timeout);
4114         } else {
4115                 mode_edit(device, mode_page, page_control,
4116                     arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
4117                     retry_count, timeout);
4118         }
4119 }
4120
4121 static int
4122 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4123         int retry_count, int timeout)
4124 {
4125         union ccb *ccb;
4126         u_int32_t flags = CAM_DIR_NONE;
4127         u_int8_t *data_ptr = NULL;
4128         u_int8_t cdb[20];
4129         u_int8_t atacmd[12];
4130         struct get_hook hook;
4131         int c, data_bytes = 0;
4132         int cdb_len = 0;
4133         int atacmd_len = 0;
4134         int dmacmd = 0;
4135         int fpdmacmd = 0;
4136         int need_res = 0;
4137         char *datastr = NULL, *tstr, *resstr = NULL;
4138         int error = 0;
4139         int fd_data = 0, fd_res = 0;
4140         int retval;
4141
4142         ccb = cam_getccb(device);
4143
4144         if (ccb == NULL) {
4145                 warnx("scsicmd: error allocating ccb");
4146                 return(1);
4147         }
4148
4149         bzero(&(&ccb->ccb_h)[1],
4150               sizeof(union ccb) - sizeof(struct ccb_hdr));
4151
4152         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4153                 switch(c) {
4154                 case 'a':
4155                         tstr = optarg;
4156                         while (isspace(*tstr) && (*tstr != '\0'))
4157                                 tstr++;
4158                         hook.argc = argc - optind;
4159                         hook.argv = argv + optind;
4160                         hook.got = 0;
4161                         atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4162                                                     iget, &hook);
4163                         /*
4164                          * Increment optind by the number of arguments the
4165                          * encoding routine processed.  After each call to
4166                          * getopt(3), optind points to the argument that
4167                          * getopt should process _next_.  In this case,
4168                          * that means it points to the first command string
4169                          * argument, if there is one.  Once we increment
4170                          * this, it should point to either the next command
4171                          * line argument, or it should be past the end of
4172                          * the list.
4173                          */
4174                         optind += hook.got;
4175                         break;
4176                 case 'c':
4177                         tstr = optarg;
4178                         while (isspace(*tstr) && (*tstr != '\0'))
4179                                 tstr++;
4180                         hook.argc = argc - optind;
4181                         hook.argv = argv + optind;
4182                         hook.got = 0;
4183                         cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4184                                                     iget, &hook);
4185                         /*
4186                          * Increment optind by the number of arguments the
4187                          * encoding routine processed.  After each call to
4188                          * getopt(3), optind points to the argument that
4189                          * getopt should process _next_.  In this case,
4190                          * that means it points to the first command string
4191                          * argument, if there is one.  Once we increment
4192                          * this, it should point to either the next command
4193                          * line argument, or it should be past the end of
4194                          * the list.
4195                          */
4196                         optind += hook.got;
4197                         break;
4198                 case 'd':
4199                         dmacmd = 1;
4200                         break;
4201                 case 'f':
4202                         fpdmacmd = 1;
4203                         break;
4204                 case 'i':
4205                         if (arglist & CAM_ARG_CMD_OUT) {
4206                                 warnx("command must either be "
4207                                       "read or write, not both");
4208                                 error = 1;
4209                                 goto scsicmd_bailout;
4210                         }
4211                         arglist |= CAM_ARG_CMD_IN;
4212                         flags = CAM_DIR_IN;
4213                         data_bytes = strtol(optarg, NULL, 0);
4214                         if (data_bytes <= 0) {
4215                                 warnx("invalid number of input bytes %d",
4216                                       data_bytes);
4217                                 error = 1;
4218                                 goto scsicmd_bailout;
4219                         }
4220                         hook.argc = argc - optind;
4221                         hook.argv = argv + optind;
4222                         hook.got = 0;
4223                         optind++;
4224                         datastr = cget(&hook, NULL);
4225                         /*
4226                          * If the user supplied "-" instead of a format, he
4227                          * wants the data to be written to stdout.
4228                          */
4229                         if ((datastr != NULL)
4230                          && (datastr[0] == '-'))
4231                                 fd_data = 1;
4232
4233                         data_ptr = (u_int8_t *)malloc(data_bytes);
4234                         if (data_ptr == NULL) {
4235                                 warnx("can't malloc memory for data_ptr");
4236                                 error = 1;
4237                                 goto scsicmd_bailout;
4238                         }
4239                         break;
4240                 case 'o':
4241                         if (arglist & CAM_ARG_CMD_IN) {
4242                                 warnx("command must either be "
4243                                       "read or write, not both");
4244                                 error = 1;
4245                                 goto scsicmd_bailout;
4246                         }
4247                         arglist |= CAM_ARG_CMD_OUT;
4248                         flags = CAM_DIR_OUT;
4249                         data_bytes = strtol(optarg, NULL, 0);
4250                         if (data_bytes <= 0) {
4251                                 warnx("invalid number of output bytes %d",
4252                                       data_bytes);
4253                                 error = 1;
4254                                 goto scsicmd_bailout;
4255                         }
4256                         hook.argc = argc - optind;
4257                         hook.argv = argv + optind;
4258                         hook.got = 0;
4259                         datastr = cget(&hook, NULL);
4260                         data_ptr = (u_int8_t *)malloc(data_bytes);
4261                         if (data_ptr == NULL) {
4262                                 warnx("can't malloc memory for data_ptr");
4263                                 error = 1;
4264                                 goto scsicmd_bailout;
4265                         }
4266                         bzero(data_ptr, data_bytes);
4267                         /*
4268                          * If the user supplied "-" instead of a format, he
4269                          * wants the data to be read from stdin.
4270                          */
4271                         if ((datastr != NULL)
4272                          && (datastr[0] == '-'))
4273                                 fd_data = 1;
4274                         else
4275                                 buff_encode_visit(data_ptr, data_bytes, datastr,
4276                                                   iget, &hook);
4277                         optind += hook.got;
4278                         break;
4279                 case 'r':
4280                         need_res = 1;
4281                         hook.argc = argc - optind;
4282                         hook.argv = argv + optind;
4283                         hook.got = 0;
4284                         resstr = cget(&hook, NULL);
4285                         if ((resstr != NULL) && (resstr[0] == '-'))
4286                                 fd_res = 1;
4287                         optind += hook.got;
4288                         break;
4289                 default:
4290                         break;
4291                 }
4292         }
4293
4294         /*
4295          * If fd_data is set, and we're writing to the device, we need to
4296          * read the data the user wants written from stdin.
4297          */
4298         if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4299                 ssize_t amt_read;
4300                 int amt_to_read = data_bytes;
4301                 u_int8_t *buf_ptr = data_ptr;
4302
4303                 for (amt_read = 0; amt_to_read > 0;
4304                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4305                         if (amt_read == -1) {
4306                                 warn("error reading data from stdin");
4307                                 error = 1;
4308                                 goto scsicmd_bailout;
4309                         }
4310                         amt_to_read -= amt_read;
4311                         buf_ptr += amt_read;
4312                 }
4313         }
4314
4315         if (arglist & CAM_ARG_ERR_RECOVER)
4316                 flags |= CAM_PASS_ERR_RECOVER;
4317
4318         /* Disable freezing the device queue */
4319         flags |= CAM_DEV_QFRZDIS;
4320
4321         if (cdb_len) {
4322                 /*
4323                  * This is taken from the SCSI-3 draft spec.
4324                  * (T10/1157D revision 0.3)
4325                  * The top 3 bits of an opcode are the group code.
4326                  * The next 5 bits are the command code.
4327                  * Group 0:  six byte commands
4328                  * Group 1:  ten byte commands
4329                  * Group 2:  ten byte commands
4330                  * Group 3:  reserved
4331                  * Group 4:  sixteen byte commands
4332                  * Group 5:  twelve byte commands
4333                  * Group 6:  vendor specific
4334                  * Group 7:  vendor specific
4335                  */
4336                 switch((cdb[0] >> 5) & 0x7) {
4337                         case 0:
4338                                 cdb_len = 6;
4339                                 break;
4340                         case 1:
4341                         case 2:
4342                                 cdb_len = 10;
4343                                 break;
4344                         case 3:
4345                         case 6:
4346                         case 7:
4347                                 /* computed by buff_encode_visit */
4348                                 break;
4349                         case 4:
4350                                 cdb_len = 16;
4351                                 break;
4352                         case 5:
4353                                 cdb_len = 12;
4354                                 break;
4355                 }
4356
4357                 /*
4358                  * We should probably use csio_build_visit or something like that
4359                  * here, but it's easier to encode arguments as you go.  The
4360                  * alternative would be skipping the CDB argument and then encoding
4361                  * it here, since we've got the data buffer argument by now.
4362                  */
4363                 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4364
4365                 cam_fill_csio(&ccb->csio,
4366                       /*retries*/ retry_count,
4367                       /*cbfcnp*/ NULL,
4368                       /*flags*/ flags,
4369                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
4370                       /*data_ptr*/ data_ptr,
4371                       /*dxfer_len*/ data_bytes,
4372                       /*sense_len*/ SSD_FULL_SIZE,
4373                       /*cdb_len*/ cdb_len,
4374                       /*timeout*/ timeout ? timeout : 5000);
4375         } else {
4376                 atacmd_len = 12;
4377                 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4378                 if (need_res)
4379                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4380                 if (dmacmd)
4381                         ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4382                 if (fpdmacmd)
4383                         ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4384
4385                 cam_fill_ataio(&ccb->ataio,
4386                       /*retries*/ retry_count,
4387                       /*cbfcnp*/ NULL,
4388                       /*flags*/ flags,
4389                       /*tag_action*/ 0,
4390                       /*data_ptr*/ data_ptr,
4391                       /*dxfer_len*/ data_bytes,
4392                       /*timeout*/ timeout ? timeout : 5000);
4393         }
4394
4395         if (((retval = cam_send_ccb(device, ccb)) < 0)
4396          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4397                 const char warnstr[] = "error sending command";
4398
4399                 if (retval < 0)
4400                         warn(warnstr);
4401                 else
4402                         warnx(warnstr);
4403
4404                 if (arglist & CAM_ARG_VERBOSE) {
4405                         cam_error_print(device, ccb, CAM_ESF_ALL,
4406                                         CAM_EPF_ALL, stderr);
4407                 }
4408
4409                 error = 1;
4410                 goto scsicmd_bailout;
4411         }
4412
4413         if (atacmd_len && need_res) {
4414                 if (fd_res == 0) {
4415                         buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4416                                           arg_put, NULL);
4417                         fprintf(stdout, "\n");
4418                 } else {
4419                         fprintf(stdout,
4420                             "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4421                             ccb->ataio.res.status,
4422                             ccb->ataio.res.error,
4423                             ccb->ataio.res.lba_low,
4424                             ccb->ataio.res.lba_mid,
4425                             ccb->ataio.res.lba_high,
4426                             ccb->ataio.res.device,
4427                             ccb->ataio.res.lba_low_exp,
4428                             ccb->ataio.res.lba_mid_exp,
4429                             ccb->ataio.res.lba_high_exp,
4430                             ccb->ataio.res.sector_count,
4431                             ccb->ataio.res.sector_count_exp);
4432                         fflush(stdout);
4433                 }
4434         }
4435
4436         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4437          && (arglist & CAM_ARG_CMD_IN)
4438          && (data_bytes > 0)) {
4439                 if (fd_data == 0) {
4440                         buff_decode_visit(data_ptr, data_bytes, datastr,
4441                                           arg_put, NULL);
4442                         fprintf(stdout, "\n");
4443                 } else {
4444                         ssize_t amt_written;
4445                         int amt_to_write = data_bytes;
4446                         u_int8_t *buf_ptr = data_ptr;
4447
4448                         for (amt_written = 0; (amt_to_write > 0) &&
4449                              (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4450                                 amt_to_write -= amt_written;
4451                                 buf_ptr += amt_written;
4452                         }
4453                         if (amt_written == -1) {
4454                                 warn("error writing data to stdout");
4455                                 error = 1;
4456                                 goto scsicmd_bailout;
4457                         } else if ((amt_written == 0)
4458                                 && (amt_to_write > 0)) {
4459                                 warnx("only wrote %u bytes out of %u",
4460                                       data_bytes - amt_to_write, data_bytes);
4461                         }
4462                 }
4463         }
4464
4465 scsicmd_bailout:
4466
4467         if ((data_bytes > 0) && (data_ptr != NULL))
4468                 free(data_ptr);
4469
4470         cam_freeccb(ccb);
4471
4472         return(error);
4473 }
4474
4475 static int
4476 camdebug(int argc, char **argv, char *combinedopt)
4477 {
4478         int c, fd;
4479         path_id_t bus = CAM_BUS_WILDCARD;
4480         target_id_t target = CAM_TARGET_WILDCARD;
4481         lun_id_t lun = CAM_LUN_WILDCARD;
4482         char *tstr, *tmpstr = NULL;
4483         union ccb ccb;
4484         int error = 0;
4485
4486         bzero(&ccb, sizeof(union ccb));
4487
4488         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4489                 switch(c) {
4490                 case 'I':
4491                         arglist |= CAM_ARG_DEBUG_INFO;
4492                         ccb.cdbg.flags |= CAM_DEBUG_INFO;
4493                         break;
4494                 case 'P':
4495                         arglist |= CAM_ARG_DEBUG_PERIPH;
4496                         ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4497                         break;
4498                 case 'S':
4499                         arglist |= CAM_ARG_DEBUG_SUBTRACE;
4500                         ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4501                         break;
4502                 case 'T':
4503                         arglist |= CAM_ARG_DEBUG_TRACE;
4504                         ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4505                         break;
4506                 case 'X':
4507                         arglist |= CAM_ARG_DEBUG_XPT;
4508                         ccb.cdbg.flags |= CAM_DEBUG_XPT;
4509                         break;
4510                 case 'c':
4511                         arglist |= CAM_ARG_DEBUG_CDB;
4512                         ccb.cdbg.flags |= CAM_DEBUG_CDB;
4513                         break;
4514                 case 'p':
4515                         arglist |= CAM_ARG_DEBUG_PROBE;
4516                         ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4517                         break;
4518                 default:
4519                         break;
4520                 }
4521         }
4522
4523         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4524                 warnx("error opening transport layer device %s", XPT_DEVICE);
4525                 warn("%s", XPT_DEVICE);
4526                 return(1);
4527         }
4528         argc -= optind;
4529         argv += optind;
4530
4531         if (argc <= 0) {
4532                 warnx("you must specify \"off\", \"all\" or a bus,");
4533                 warnx("bus:target, or bus:target:lun");
4534                 close(fd);
4535                 return(1);
4536         }
4537
4538         tstr = *argv;
4539
4540         while (isspace(*tstr) && (*tstr != '\0'))
4541                 tstr++;
4542
4543         if (strncmp(tstr, "off", 3) == 0) {
4544                 ccb.cdbg.flags = CAM_DEBUG_NONE;
4545                 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4546                              CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4547                              CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4548         } else if (strncmp(tstr, "all", 3) != 0) {
4549                 tmpstr = (char *)strtok(tstr, ":");
4550                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4551                         bus = strtol(tmpstr, NULL, 0);
4552                         arglist |= CAM_ARG_BUS;
4553                         tmpstr = (char *)strtok(NULL, ":");
4554                         if ((tmpstr != NULL) && (*tmpstr != '\0')){
4555                                 target = strtol(tmpstr, NULL, 0);
4556                                 arglist |= CAM_ARG_TARGET;
4557                                 tmpstr = (char *)strtok(NULL, ":");
4558                                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4559                                         lun = strtol(tmpstr, NULL, 0);
4560                                         arglist |= CAM_ARG_LUN;
4561                                 }
4562                         }
4563                 } else {
4564                         error = 1;
4565                         warnx("you must specify \"all\", \"off\", or a bus,");
4566                         warnx("bus:target, or bus:target:lun to debug");
4567                 }
4568         }
4569
4570         if (error == 0) {
4571
4572                 ccb.ccb_h.func_code = XPT_DEBUG;
4573                 ccb.ccb_h.path_id = bus;
4574                 ccb.ccb_h.target_id = target;
4575                 ccb.ccb_h.target_lun = lun;
4576
4577                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4578                         warn("CAMIOCOMMAND ioctl failed");
4579                         error = 1;
4580                 }
4581
4582                 if (error == 0) {
4583                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4584                              CAM_FUNC_NOTAVAIL) {
4585                                 warnx("CAM debugging not available");
4586                                 warnx("you need to put options CAMDEBUG in"
4587                                       " your kernel config file!");
4588                                 error = 1;
4589                         } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4590                                     CAM_REQ_CMP) {
4591                                 warnx("XPT_DEBUG CCB failed with status %#x",
4592                                       ccb.ccb_h.status);
4593                                 error = 1;
4594                         } else {
4595                                 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4596                                         fprintf(stderr,
4597                                                 "Debugging turned off\n");
4598                                 } else {
4599                                         fprintf(stderr,
4600                                                 "Debugging enabled for "
4601                                                 "%d:%d:%jx\n",
4602                                                 bus, target, (uintmax_t)lun);
4603                                 }
4604                         }
4605                 }
4606                 close(fd);
4607         }
4608
4609         return(error);
4610 }
4611
4612 static int
4613 tagcontrol(struct cam_device *device, int argc, char **argv,
4614            char *combinedopt)
4615 {
4616         int c;
4617         union ccb *ccb;
4618         int numtags = -1;
4619         int retval = 0;
4620         int quiet = 0;
4621         char pathstr[1024];
4622
4623         ccb = cam_getccb(device);
4624
4625         if (ccb == NULL) {
4626                 warnx("tagcontrol: error allocating ccb");
4627                 return(1);
4628         }
4629
4630         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4631                 switch(c) {
4632                 case 'N':
4633                         numtags = strtol(optarg, NULL, 0);
4634                         if (numtags < 0) {
4635                                 warnx("tag count %d is < 0", numtags);
4636                                 retval = 1;
4637                                 goto tagcontrol_bailout;
4638                         }
4639                         break;
4640                 case 'q':
4641                         quiet++;
4642                         break;
4643                 default:
4644                         break;
4645                 }
4646         }
4647
4648         cam_path_string(device, pathstr, sizeof(pathstr));
4649
4650         if (numtags >= 0) {
4651                 bzero(&(&ccb->ccb_h)[1],
4652                       sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4653                 ccb->ccb_h.func_code = XPT_REL_SIMQ;
4654                 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4655                 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4656                 ccb->crs.openings = numtags;
4657
4658
4659                 if (cam_send_ccb(device, ccb) < 0) {
4660                         perror("error sending XPT_REL_SIMQ CCB");
4661                         retval = 1;
4662                         goto tagcontrol_bailout;
4663                 }
4664
4665                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4666                         warnx("XPT_REL_SIMQ CCB failed");
4667                         cam_error_print(device, ccb, CAM_ESF_ALL,
4668                                         CAM_EPF_ALL, stderr);
4669                         retval = 1;
4670                         goto tagcontrol_bailout;
4671                 }
4672
4673
4674                 if (quiet == 0)
4675                         fprintf(stdout, "%stagged openings now %d\n",
4676                                 pathstr, ccb->crs.openings);
4677         }
4678
4679         bzero(&(&ccb->ccb_h)[1],
4680               sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4681
4682         ccb->ccb_h.func_code = XPT_GDEV_STATS;
4683
4684         if (cam_send_ccb(device, ccb) < 0) {
4685                 perror("error sending XPT_GDEV_STATS CCB");
4686                 retval = 1;
4687                 goto tagcontrol_bailout;
4688         }
4689
4690         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4691                 warnx("XPT_GDEV_STATS CCB failed");
4692                 cam_error_print(device, ccb, CAM_ESF_ALL,
4693                                 CAM_EPF_ALL, stderr);
4694                 retval = 1;
4695                 goto tagcontrol_bailout;
4696         }
4697
4698         if (arglist & CAM_ARG_VERBOSE) {
4699                 fprintf(stdout, "%s", pathstr);
4700                 fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4701                 fprintf(stdout, "%s", pathstr);
4702                 fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4703                 fprintf(stdout, "%s", pathstr);
4704                 fprintf(stdout, "allocated     %d\n", ccb->cgds.allocated);
4705                 fprintf(stdout, "%s", pathstr);
4706                 fprintf(stdout, "queued        %d\n", ccb->cgds.queued);
4707                 fprintf(stdout, "%s", pathstr);
4708                 fprintf(stdout, "held          %d\n", ccb->cgds.held);
4709                 fprintf(stdout, "%s", pathstr);
4710                 fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4711                 fprintf(stdout, "%s", pathstr);
4712                 fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4713         } else {
4714                 if (quiet == 0) {
4715                         fprintf(stdout, "%s", pathstr);
4716                         fprintf(stdout, "device openings: ");
4717                 }
4718                 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4719                         ccb->cgds.dev_active);
4720         }
4721
4722 tagcontrol_bailout:
4723
4724         cam_freeccb(ccb);
4725         return(retval);
4726 }
4727
4728 static void
4729 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4730 {
4731         char pathstr[1024];
4732
4733         cam_path_string(device, pathstr, sizeof(pathstr));
4734
4735         if (cts->transport == XPORT_SPI) {
4736                 struct ccb_trans_settings_spi *spi =
4737                     &cts->xport_specific.spi;
4738
4739                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4740
4741                         fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4742                                 spi->sync_period);
4743
4744                         if (spi->sync_offset != 0) {
4745                                 u_int freq;
4746
4747                                 freq = scsi_calc_syncsrate(spi->sync_period);
4748                                 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4749                                         pathstr, freq / 1000, freq % 1000);
4750                         }
4751                 }
4752
4753                 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4754                         fprintf(stdout, "%soffset: %d\n", pathstr,
4755                             spi->sync_offset);
4756                 }
4757
4758                 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4759                         fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4760                                 (0x01 << spi->bus_width) * 8);
4761                 }
4762
4763                 if (spi->valid & CTS_SPI_VALID_DISC) {
4764                         fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4765                                 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4766                                 "enabled" : "disabled");
4767                 }
4768         }
4769         if (cts->transport == XPORT_FC) {
4770                 struct ccb_trans_settings_fc *fc =
4771                     &cts->xport_specific.fc;
4772
4773                 if (fc->valid & CTS_FC_VALID_WWNN)
4774                         fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4775                             (long long) fc->wwnn);
4776                 if (fc->valid & CTS_FC_VALID_WWPN)
4777                         fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4778                             (long long) fc->wwpn);
4779                 if (fc->valid & CTS_FC_VALID_PORT)
4780                         fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4781                 if (fc->valid & CTS_FC_VALID_SPEED)
4782                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4783                             pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4784         }
4785         if (cts->transport == XPORT_SAS) {
4786                 struct ccb_trans_settings_sas *sas =
4787                     &cts->xport_specific.sas;
4788
4789                 if (sas->valid & CTS_SAS_VALID_SPEED)
4790                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4791                             pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4792         }
4793         if (cts->transport == XPORT_ATA) {
4794                 struct ccb_trans_settings_pata *pata =
4795                     &cts->xport_specific.ata;
4796
4797                 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4798                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4799                                 ata_mode2string(pata->mode));
4800                 }
4801                 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4802                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4803                                 pata->atapi);
4804                 }
4805                 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4806                         fprintf(stdout, "%sPIO transaction length: %d\n",
4807                                 pathstr, pata->bytecount);
4808                 }
4809         }
4810         if (cts->transport == XPORT_SATA) {
4811                 struct ccb_trans_settings_sata *sata =
4812                     &cts->xport_specific.sata;
4813
4814                 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4815                         fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4816                                 sata->revision);
4817                 }
4818                 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4819                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4820                                 ata_mode2string(sata->mode));
4821                 }
4822                 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4823                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4824                                 sata->atapi);
4825                 }
4826                 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4827                         fprintf(stdout, "%sPIO transaction length: %d\n",
4828                                 pathstr, sata->bytecount);
4829                 }
4830                 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4831                         fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4832                                 sata->pm_present);
4833                 }
4834                 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4835                         fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4836                                 sata->tags);
4837                 }
4838                 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4839                         fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4840                                 sata->caps);
4841                 }
4842         }
4843         if (cts->protocol == PROTO_ATA) {
4844                 struct ccb_trans_settings_ata *ata=
4845                     &cts->proto_specific.ata;
4846
4847                 if (ata->valid & CTS_ATA_VALID_TQ) {
4848                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4849                                 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4850                                 "enabled" : "disabled");
4851                 }
4852         }
4853         if (cts->protocol == PROTO_SCSI) {
4854                 struct ccb_trans_settings_scsi *scsi=
4855                     &cts->proto_specific.scsi;
4856
4857                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
4858                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4859                                 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4860                                 "enabled" : "disabled");
4861                 }
4862         }
4863
4864 }
4865
4866 /*
4867  * Get a path inquiry CCB for the specified device.
4868  */
4869 static int
4870 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4871 {
4872         union ccb *ccb;
4873         int retval = 0;
4874
4875         ccb = cam_getccb(device);
4876         if (ccb == NULL) {
4877                 warnx("get_cpi: couldn't allocate CCB");
4878                 return(1);
4879         }
4880         bzero(&(&ccb->ccb_h)[1],
4881               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4882         ccb->ccb_h.func_code = XPT_PATH_INQ;
4883         if (cam_send_ccb(device, ccb) < 0) {
4884                 warn("get_cpi: error sending Path Inquiry CCB");
4885                 if (arglist & CAM_ARG_VERBOSE)
4886                         cam_error_print(device, ccb, CAM_ESF_ALL,
4887                                         CAM_EPF_ALL, stderr);
4888                 retval = 1;
4889                 goto get_cpi_bailout;
4890         }
4891         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4892                 if (arglist & CAM_ARG_VERBOSE)
4893                         cam_error_print(device, ccb, CAM_ESF_ALL,
4894                                         CAM_EPF_ALL, stderr);
4895                 retval = 1;
4896                 goto get_cpi_bailout;
4897         }
4898         bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4899
4900 get_cpi_bailout:
4901         cam_freeccb(ccb);
4902         return(retval);
4903 }
4904
4905 /*
4906  * Get a get device CCB for the specified device.
4907  */
4908 static int
4909 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4910 {
4911         union ccb *ccb;
4912         int retval = 0;
4913
4914         ccb = cam_getccb(device);
4915         if (ccb == NULL) {
4916                 warnx("get_cgd: couldn't allocate CCB");
4917                 return(1);
4918         }
4919         bzero(&(&ccb->ccb_h)[1],
4920               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4921         ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4922         if (cam_send_ccb(device, ccb) < 0) {
4923                 warn("get_cgd: error sending Path Inquiry CCB");
4924                 if (arglist & CAM_ARG_VERBOSE)
4925                         cam_error_print(device, ccb, CAM_ESF_ALL,
4926                                         CAM_EPF_ALL, stderr);
4927                 retval = 1;
4928                 goto get_cgd_bailout;
4929         }
4930         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4931                 if (arglist & CAM_ARG_VERBOSE)
4932                         cam_error_print(device, ccb, CAM_ESF_ALL,
4933                                         CAM_EPF_ALL, stderr);
4934                 retval = 1;
4935                 goto get_cgd_bailout;
4936         }
4937         bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4938
4939 get_cgd_bailout:
4940         cam_freeccb(ccb);
4941         return(retval);
4942 }
4943
4944 /* return the type of disk (really the command type) */
4945 static const char *
4946 get_disk_type(struct cam_device *device)
4947 {
4948         struct ccb_getdev       cgd;
4949
4950         (void) memset(&cgd, 0x0, sizeof(cgd));
4951         get_cgd(device, &cgd);
4952         switch(cgd.protocol) {
4953         case PROTO_SCSI:
4954                 return "scsi";
4955         case PROTO_ATA:
4956         case PROTO_ATAPI:
4957         case PROTO_SATAPM:
4958                 return "ata";
4959         default:
4960                 return "unknown";
4961         }
4962 }
4963
4964 static void
4965 cpi_print(struct ccb_pathinq *cpi)
4966 {
4967         char adapter_str[1024];
4968         int i;
4969
4970         snprintf(adapter_str, sizeof(adapter_str),
4971                  "%s%d:", cpi->dev_name, cpi->unit_number);
4972
4973         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
4974                 cpi->version_num);
4975
4976         for (i = 1; i < 0xff; i = i << 1) {
4977                 const char *str;
4978
4979                 if ((i & cpi->hba_inquiry) == 0)
4980                         continue;
4981
4982                 fprintf(stdout, "%s supports ", adapter_str);
4983
4984                 switch(i) {
4985                 case PI_MDP_ABLE:
4986                         str = "MDP message";
4987                         break;
4988                 case PI_WIDE_32:
4989                         str = "32 bit wide SCSI";
4990                         break;
4991                 case PI_WIDE_16:
4992                         str = "16 bit wide SCSI";
4993                         break;
4994                 case PI_SDTR_ABLE:
4995                         str = "SDTR message";
4996                         break;
4997                 case PI_LINKED_CDB:
4998                         str = "linked CDBs";
4999                         break;
5000                 case PI_TAG_ABLE:
5001                         str = "tag queue messages";
5002                         break;
5003                 case PI_SOFT_RST:
5004                         str = "soft reset alternative";
5005                         break;
5006                 case PI_SATAPM:
5007                         str = "SATA Port Multiplier";
5008                         break;
5009                 default:
5010                         str = "unknown PI bit set";
5011                         break;
5012                 }
5013                 fprintf(stdout, "%s\n", str);
5014         }
5015
5016         for (i = 1; i < 0xff; i = i << 1) {
5017                 const char *str;
5018
5019                 if ((i & cpi->hba_misc) == 0)
5020                         continue;
5021
5022                 fprintf(stdout, "%s ", adapter_str);
5023
5024                 switch(i) {
5025                 case PIM_SCANHILO:
5026                         str = "bus scans from high ID to low ID";
5027                         break;
5028                 case PIM_NOREMOVE:
5029                         str = "removable devices not included in scan";
5030                         break;
5031                 case PIM_NOINITIATOR:
5032                         str = "initiator role not supported";
5033                         break;
5034                 case PIM_NOBUSRESET:
5035                         str = "user has disabled initial BUS RESET or"
5036                               " controller is in target/mixed mode";
5037                         break;
5038                 case PIM_NO_6_BYTE:
5039                         str = "do not send 6-byte commands";
5040                         break;
5041                 case PIM_SEQSCAN:
5042                         str = "scan bus sequentially";
5043                         break;
5044                 default:
5045                         str = "unknown PIM bit set";
5046                         break;
5047                 }
5048                 fprintf(stdout, "%s\n", str);
5049         }
5050
5051         for (i = 1; i < 0xff; i = i << 1) {
5052                 const char *str;
5053
5054                 if ((i & cpi->target_sprt) == 0)
5055                         continue;
5056
5057                 fprintf(stdout, "%s supports ", adapter_str);
5058                 switch(i) {
5059                 case PIT_PROCESSOR:
5060                         str = "target mode processor mode";
5061                         break;
5062                 case PIT_PHASE:
5063                         str = "target mode phase cog. mode";
5064                         break;
5065                 case PIT_DISCONNECT:
5066                         str = "disconnects in target mode";
5067                         break;
5068                 case PIT_TERM_IO:
5069                         str = "terminate I/O message in target mode";
5070                         break;
5071                 case PIT_GRP_6:
5072                         str = "group 6 commands in target mode";
5073                         break;
5074                 case PIT_GRP_7:
5075                         str = "group 7 commands in target mode";
5076                         break;
5077                 default:
5078                         str = "unknown PIT bit set";
5079                         break;
5080                 }
5081
5082                 fprintf(stdout, "%s\n", str);
5083         }
5084         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5085                 cpi->hba_eng_cnt);
5086         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5087                 cpi->max_target);
5088         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5089                 cpi->max_lun);
5090         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5091                 adapter_str, cpi->hpath_id);
5092         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5093                 cpi->initiator_id);
5094         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5095         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5096         fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5097             adapter_str, cpi->hba_vendor);
5098         fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5099             adapter_str, cpi->hba_device);
5100         fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5101             adapter_str, cpi->hba_subvendor);
5102         fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5103             adapter_str, cpi->hba_subdevice);
5104         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5105         fprintf(stdout, "%s base transfer speed: ", adapter_str);
5106         if (cpi->base_transfer_speed > 1000)
5107                 fprintf(stdout, "%d.%03dMB/sec\n",
5108                         cpi->base_transfer_speed / 1000,
5109                         cpi->base_transfer_speed % 1000);
5110         else
5111                 fprintf(stdout, "%dKB/sec\n",
5112                         (cpi->base_transfer_speed % 1000) * 1000);
5113         fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5114             adapter_str, cpi->maxio);
5115 }
5116
5117 static int
5118 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5119               struct ccb_trans_settings *cts)
5120 {
5121         int retval;
5122         union ccb *ccb;
5123
5124         retval = 0;
5125         ccb = cam_getccb(device);
5126
5127         if (ccb == NULL) {
5128                 warnx("get_print_cts: error allocating ccb");
5129                 return(1);
5130         }
5131
5132         bzero(&(&ccb->ccb_h)[1],
5133               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5134
5135         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5136
5137         if (user_settings == 0)
5138                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5139         else
5140                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5141
5142         if (cam_send_ccb(device, ccb) < 0) {
5143                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5144                 if (arglist & CAM_ARG_VERBOSE)
5145                         cam_error_print(device, ccb, CAM_ESF_ALL,
5146                                         CAM_EPF_ALL, stderr);
5147                 retval = 1;
5148                 goto get_print_cts_bailout;
5149         }
5150
5151         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5152                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5153                 if (arglist & CAM_ARG_VERBOSE)
5154                         cam_error_print(device, ccb, CAM_ESF_ALL,
5155                                         CAM_EPF_ALL, stderr);
5156                 retval = 1;
5157                 goto get_print_cts_bailout;
5158         }
5159
5160         if (quiet == 0)
5161                 cts_print(device, &ccb->cts);
5162
5163         if (cts != NULL)
5164                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5165
5166 get_print_cts_bailout:
5167
5168         cam_freeccb(ccb);
5169
5170         return(retval);
5171 }
5172
5173 static int
5174 ratecontrol(struct cam_device *device, int retry_count, int timeout,
5175             int argc, char **argv, char *combinedopt)
5176 {
5177         int c;
5178         union ccb *ccb;
5179         int user_settings = 0;
5180         int retval = 0;
5181         int disc_enable = -1, tag_enable = -1;
5182         int mode = -1;
5183         int offset = -1;
5184         double syncrate = -1;
5185         int bus_width = -1;
5186         int quiet = 0;
5187         int change_settings = 0, send_tur = 0;
5188         struct ccb_pathinq cpi;
5189
5190         ccb = cam_getccb(device);
5191         if (ccb == NULL) {
5192                 warnx("ratecontrol: error allocating ccb");
5193                 return(1);
5194         }
5195         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5196                 switch(c){
5197                 case 'a':
5198                         send_tur = 1;
5199                         break;
5200                 case 'c':
5201                         user_settings = 0;
5202                         break;
5203                 case 'D':
5204                         if (strncasecmp(optarg, "enable", 6) == 0)
5205                                 disc_enable = 1;
5206                         else if (strncasecmp(optarg, "disable", 7) == 0)
5207                                 disc_enable = 0;
5208                         else {
5209                                 warnx("-D argument \"%s\" is unknown", optarg);
5210                                 retval = 1;
5211                                 goto ratecontrol_bailout;
5212                         }
5213                         change_settings = 1;
5214                         break;
5215                 case 'M':
5216                         mode = ata_string2mode(optarg);
5217                         if (mode < 0) {
5218                                 warnx("unknown mode '%s'", optarg);
5219                                 retval = 1;
5220                                 goto ratecontrol_bailout;
5221                         }
5222                         change_settings = 1;
5223                         break;
5224                 case 'O':
5225                         offset = strtol(optarg, NULL, 0);
5226                         if (offset < 0) {
5227                                 warnx("offset value %d is < 0", offset);
5228                                 retval = 1;
5229                                 goto ratecontrol_bailout;
5230                         }
5231                         change_settings = 1;
5232                         break;
5233                 case 'q':
5234                         quiet++;
5235                         break;
5236                 case 'R':
5237                         syncrate = atof(optarg);
5238                         if (syncrate < 0) {
5239                                 warnx("sync rate %f is < 0", syncrate);
5240                                 retval = 1;
5241                                 goto ratecontrol_bailout;
5242                         }
5243                         change_settings = 1;
5244                         break;
5245                 case 'T':
5246                         if (strncasecmp(optarg, "enable", 6) == 0)
5247                                 tag_enable = 1;
5248                         else if (strncasecmp(optarg, "disable", 7) == 0)
5249                                 tag_enable = 0;
5250                         else {
5251                                 warnx("-T argument \"%s\" is unknown", optarg);
5252                                 retval = 1;
5253                                 goto ratecontrol_bailout;
5254                         }
5255                         change_settings = 1;
5256                         break;
5257                 case 'U':
5258                         user_settings = 1;
5259                         break;
5260                 case 'W':
5261                         bus_width = strtol(optarg, NULL, 0);
5262                         if (bus_width < 0) {
5263                                 warnx("bus width %d is < 0", bus_width);
5264                                 retval = 1;
5265                                 goto ratecontrol_bailout;
5266                         }
5267                         change_settings = 1;
5268                         break;
5269                 default:
5270                         break;
5271                 }
5272         }
5273         bzero(&(&ccb->ccb_h)[1],
5274               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5275         /*
5276          * Grab path inquiry information, so we can determine whether
5277          * or not the initiator is capable of the things that the user
5278          * requests.
5279          */
5280         ccb->ccb_h.func_code = XPT_PATH_INQ;
5281         if (cam_send_ccb(device, ccb) < 0) {
5282                 perror("error sending XPT_PATH_INQ CCB");
5283                 if (arglist & CAM_ARG_VERBOSE) {
5284                         cam_error_print(device, ccb, CAM_ESF_ALL,
5285                                         CAM_EPF_ALL, stderr);
5286                 }
5287                 retval = 1;
5288                 goto ratecontrol_bailout;
5289         }
5290         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5291                 warnx("XPT_PATH_INQ CCB failed");
5292                 if (arglist & CAM_ARG_VERBOSE) {
5293                         cam_error_print(device, ccb, CAM_ESF_ALL,
5294                                         CAM_EPF_ALL, stderr);
5295                 }
5296                 retval = 1;
5297                 goto ratecontrol_bailout;
5298         }
5299         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5300         bzero(&(&ccb->ccb_h)[1],
5301               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5302         if (quiet == 0) {
5303                 fprintf(stdout, "%s parameters:\n",
5304                     user_settings ? "User" : "Current");
5305         }
5306         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5307         if (retval != 0)
5308                 goto ratecontrol_bailout;
5309
5310         if (arglist & CAM_ARG_VERBOSE)
5311                 cpi_print(&cpi);
5312
5313         if (change_settings) {
5314                 int didsettings = 0;
5315                 struct ccb_trans_settings_spi *spi = NULL;
5316                 struct ccb_trans_settings_pata *pata = NULL;
5317                 struct ccb_trans_settings_sata *sata = NULL;
5318                 struct ccb_trans_settings_ata *ata = NULL;
5319                 struct ccb_trans_settings_scsi *scsi = NULL;
5320
5321                 if (ccb->cts.transport == XPORT_SPI)
5322                         spi = &ccb->cts.xport_specific.spi;
5323                 if (ccb->cts.transport == XPORT_ATA)
5324                         pata = &ccb->cts.xport_specific.ata;
5325                 if (ccb->cts.transport == XPORT_SATA)
5326                         sata = &ccb->cts.xport_specific.sata;
5327                 if (ccb->cts.protocol == PROTO_ATA)
5328                         ata = &ccb->cts.proto_specific.ata;
5329                 if (ccb->cts.protocol == PROTO_SCSI)
5330                         scsi = &ccb->cts.proto_specific.scsi;
5331                 ccb->cts.xport_specific.valid = 0;
5332                 ccb->cts.proto_specific.valid = 0;
5333                 if (spi && disc_enable != -1) {
5334                         spi->valid |= CTS_SPI_VALID_DISC;
5335                         if (disc_enable == 0)
5336                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5337                         else
5338                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5339                         didsettings++;
5340                 }
5341                 if (tag_enable != -1) {
5342                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5343                                 warnx("HBA does not support tagged queueing, "
5344                                       "so you cannot modify tag settings");
5345                                 retval = 1;
5346                                 goto ratecontrol_bailout;
5347                         }
5348                         if (ata) {
5349                                 ata->valid |= CTS_SCSI_VALID_TQ;
5350                                 if (tag_enable == 0)
5351                                         ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5352                                 else
5353                                         ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5354                                 didsettings++;
5355                         } else if (scsi) {
5356                                 scsi->valid |= CTS_SCSI_VALID_TQ;
5357                                 if (tag_enable == 0)
5358                                         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5359                                 else
5360                                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5361                                 didsettings++;
5362                         }
5363                 }
5364                 if (spi && offset != -1) {
5365                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5366                                 warnx("HBA is not capable of changing offset");
5367                                 retval = 1;
5368                                 goto ratecontrol_bailout;
5369                         }
5370                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5371                         spi->sync_offset = offset;
5372                         didsettings++;
5373                 }
5374                 if (spi && syncrate != -1) {
5375                         int prelim_sync_period;
5376
5377                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5378                                 warnx("HBA is not capable of changing "
5379                                       "transfer rates");
5380                                 retval = 1;
5381                                 goto ratecontrol_bailout;
5382                         }
5383                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5384                         /*
5385                          * The sync rate the user gives us is in MHz.
5386                          * We need to translate it into KHz for this
5387                          * calculation.
5388                          */
5389                         syncrate *= 1000;
5390                         /*
5391                          * Next, we calculate a "preliminary" sync period
5392                          * in tenths of a nanosecond.
5393                          */
5394                         if (syncrate == 0)
5395                                 prelim_sync_period = 0;
5396                         else
5397                                 prelim_sync_period = 10000000 / syncrate;
5398                         spi->sync_period =
5399                                 scsi_calc_syncparam(prelim_sync_period);
5400                         didsettings++;
5401                 }
5402                 if (sata && syncrate != -1) {
5403                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5404                                 warnx("HBA is not capable of changing "
5405                                       "transfer rates");
5406                                 retval = 1;
5407                                 goto ratecontrol_bailout;
5408                         }
5409                         if  (!user_settings) {
5410                                 warnx("You can modify only user rate "
5411                                     "settings for SATA");
5412                                 retval = 1;
5413                                 goto ratecontrol_bailout;
5414                         }
5415                         sata->revision = ata_speed2revision(syncrate * 100);
5416                         if (sata->revision < 0) {
5417                                 warnx("Invalid rate %f", syncrate);
5418                                 retval = 1;
5419                                 goto ratecontrol_bailout;
5420                         }
5421                         sata->valid |= CTS_SATA_VALID_REVISION;
5422                         didsettings++;
5423                 }
5424                 if ((pata || sata) && mode != -1) {
5425                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5426                                 warnx("HBA is not capable of changing "
5427                                       "transfer rates");
5428                                 retval = 1;
5429                                 goto ratecontrol_bailout;
5430                         }
5431                         if  (!user_settings) {
5432                                 warnx("You can modify only user mode "
5433                                     "settings for ATA/SATA");
5434                                 retval = 1;
5435                                 goto ratecontrol_bailout;
5436                         }
5437                         if (pata) {
5438                                 pata->mode = mode;
5439                                 pata->valid |= CTS_ATA_VALID_MODE;
5440                         } else {
5441                                 sata->mode = mode;
5442                                 sata->valid |= CTS_SATA_VALID_MODE;
5443                         }
5444                         didsettings++;
5445                 }
5446                 /*
5447                  * The bus_width argument goes like this:
5448                  * 0 == 8 bit
5449                  * 1 == 16 bit
5450                  * 2 == 32 bit
5451                  * Therefore, if you shift the number of bits given on the
5452                  * command line right by 4, you should get the correct
5453                  * number.
5454                  */
5455                 if (spi && bus_width != -1) {
5456                         /*
5457                          * We might as well validate things here with a
5458                          * decipherable error message, rather than what
5459                          * will probably be an indecipherable error message
5460                          * by the time it gets back to us.
5461                          */
5462                         if ((bus_width == 16)
5463                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5464                                 warnx("HBA does not support 16 bit bus width");
5465                                 retval = 1;
5466                                 goto ratecontrol_bailout;
5467                         } else if ((bus_width == 32)
5468                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5469                                 warnx("HBA does not support 32 bit bus width");
5470                                 retval = 1;
5471                                 goto ratecontrol_bailout;
5472                         } else if ((bus_width != 8)
5473                                 && (bus_width != 16)
5474                                 && (bus_width != 32)) {
5475                                 warnx("Invalid bus width %d", bus_width);
5476                                 retval = 1;
5477                                 goto ratecontrol_bailout;
5478                         }
5479                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5480                         spi->bus_width = bus_width >> 4;
5481                         didsettings++;
5482                 }
5483                 if  (didsettings == 0) {
5484                         goto ratecontrol_bailout;
5485                 }
5486                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5487                 if (cam_send_ccb(device, ccb) < 0) {
5488                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5489                         if (arglist & CAM_ARG_VERBOSE) {
5490                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5491                                                 CAM_EPF_ALL, stderr);
5492                         }
5493                         retval = 1;
5494                         goto ratecontrol_bailout;
5495                 }
5496                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5497                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5498                         if (arglist & CAM_ARG_VERBOSE) {
5499                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5500                                                 CAM_EPF_ALL, stderr);
5501                         }
5502                         retval = 1;
5503                         goto ratecontrol_bailout;
5504                 }
5505         }
5506         if (send_tur) {
5507                 retval = testunitready(device, retry_count, timeout,
5508                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5509                 /*
5510                  * If the TUR didn't succeed, just bail.
5511                  */
5512                 if (retval != 0) {
5513                         if (quiet == 0)
5514                                 fprintf(stderr, "Test Unit Ready failed\n");
5515                         goto ratecontrol_bailout;
5516                 }
5517         }
5518         if ((change_settings || send_tur) && !quiet &&
5519             (ccb->cts.transport == XPORT_ATA ||
5520              ccb->cts.transport == XPORT_SATA || send_tur)) {
5521                 fprintf(stdout, "New parameters:\n");
5522                 retval = get_print_cts(device, user_settings, 0, NULL);
5523         }
5524
5525 ratecontrol_bailout:
5526         cam_freeccb(ccb);
5527         return(retval);
5528 }
5529
5530 static int
5531 scsiformat(struct cam_device *device, int argc, char **argv,
5532            char *combinedopt, int retry_count, int timeout)
5533 {
5534         union ccb *ccb;
5535         int c;
5536         int ycount = 0, quiet = 0;
5537         int error = 0, retval = 0;
5538         int use_timeout = 10800 * 1000;
5539         int immediate = 1;
5540         struct format_defect_list_header fh;
5541         u_int8_t *data_ptr = NULL;
5542         u_int32_t dxfer_len = 0;
5543         u_int8_t byte2 = 0;
5544         int num_warnings = 0;
5545         int reportonly = 0;
5546
5547         ccb = cam_getccb(device);
5548
5549         if (ccb == NULL) {
5550                 warnx("scsiformat: error allocating ccb");
5551                 return(1);
5552         }
5553
5554         bzero(&(&ccb->ccb_h)[1],
5555               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5556
5557         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5558                 switch(c) {
5559                 case 'q':
5560                         quiet++;
5561                         break;
5562                 case 'r':
5563                         reportonly = 1;
5564                         break;
5565                 case 'w':
5566                         immediate = 0;
5567                         break;
5568                 case 'y':
5569                         ycount++;
5570                         break;
5571                 }
5572         }
5573
5574         if (reportonly)
5575                 goto doreport;
5576
5577         if (quiet == 0) {
5578                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5579                         "following device:\n");
5580
5581                 error = scsidoinquiry(device, argc, argv, combinedopt,
5582                                       retry_count, timeout);
5583
5584                 if (error != 0) {
5585                         warnx("scsiformat: error sending inquiry");
5586                         goto scsiformat_bailout;
5587                 }
5588         }
5589
5590         if (ycount == 0) {
5591                 if (!get_confirmation()) {
5592                         error = 1;
5593                         goto scsiformat_bailout;
5594                 }
5595         }
5596
5597         if (timeout != 0)
5598                 use_timeout = timeout;
5599
5600         if (quiet == 0) {
5601                 fprintf(stdout, "Current format timeout is %d seconds\n",
5602                         use_timeout / 1000);
5603         }
5604
5605         /*
5606          * If the user hasn't disabled questions and didn't specify a
5607          * timeout on the command line, ask them if they want the current
5608          * timeout.
5609          */
5610         if ((ycount == 0)
5611          && (timeout == 0)) {
5612                 char str[1024];
5613                 int new_timeout = 0;
5614
5615                 fprintf(stdout, "Enter new timeout in seconds or press\n"
5616                         "return to keep the current timeout [%d] ",
5617                         use_timeout / 1000);
5618
5619                 if (fgets(str, sizeof(str), stdin) != NULL) {
5620                         if (str[0] != '\0')
5621                                 new_timeout = atoi(str);
5622                 }
5623
5624                 if (new_timeout != 0) {
5625                         use_timeout = new_timeout * 1000;
5626                         fprintf(stdout, "Using new timeout value %d\n",
5627                                 use_timeout / 1000);
5628                 }
5629         }
5630
5631         /*
5632          * Keep this outside the if block below to silence any unused
5633          * variable warnings.
5634          */
5635         bzero(&fh, sizeof(fh));
5636
5637         /*
5638          * If we're in immediate mode, we've got to include the format
5639          * header
5640          */
5641         if (immediate != 0) {
5642                 fh.byte2 = FU_DLH_IMMED;
5643                 data_ptr = (u_int8_t *)&fh;
5644                 dxfer_len = sizeof(fh);
5645                 byte2 = FU_FMT_DATA;
5646         } else if (quiet == 0) {
5647                 fprintf(stdout, "Formatting...");
5648                 fflush(stdout);
5649         }
5650
5651         scsi_format_unit(&ccb->csio,
5652                          /* retries */ retry_count,
5653                          /* cbfcnp */ NULL,
5654                          /* tag_action */ MSG_SIMPLE_Q_TAG,
5655                          /* byte2 */ byte2,
5656                          /* ileave */ 0,
5657                          /* data_ptr */ data_ptr,
5658                          /* dxfer_len */ dxfer_len,
5659                          /* sense_len */ SSD_FULL_SIZE,
5660                          /* timeout */ use_timeout);
5661
5662         /* Disable freezing the device queue */
5663         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5664
5665         if (arglist & CAM_ARG_ERR_RECOVER)
5666                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5667
5668         if (((retval = cam_send_ccb(device, ccb)) < 0)
5669          || ((immediate == 0)
5670            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5671                 const char errstr[] = "error sending format command";
5672
5673                 if (retval < 0)
5674                         warn(errstr);
5675                 else
5676                         warnx(errstr);
5677
5678                 if (arglist & CAM_ARG_VERBOSE) {
5679                         cam_error_print(device, ccb, CAM_ESF_ALL,
5680                                         CAM_EPF_ALL, stderr);
5681                 }
5682                 error = 1;
5683                 goto scsiformat_bailout;
5684         }
5685
5686         /*
5687          * If we ran in non-immediate mode, we already checked for errors
5688          * above and printed out any necessary information.  If we're in
5689          * immediate mode, we need to loop through and get status
5690          * information periodically.
5691          */
5692         if (immediate == 0) {
5693                 if (quiet == 0) {
5694                         fprintf(stdout, "Format Complete\n");
5695                 }
5696                 goto scsiformat_bailout;
5697         }
5698
5699 doreport:
5700         do {
5701                 cam_status status;
5702
5703                 bzero(&(&ccb->ccb_h)[1],
5704                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5705
5706                 /*
5707                  * There's really no need to do error recovery or
5708                  * retries here, since we're just going to sit in a
5709                  * loop and wait for the device to finish formatting.
5710                  */
5711                 scsi_test_unit_ready(&ccb->csio,
5712                                      /* retries */ 0,
5713                                      /* cbfcnp */ NULL,
5714                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
5715                                      /* sense_len */ SSD_FULL_SIZE,
5716                                      /* timeout */ 5000);
5717
5718                 /* Disable freezing the device queue */
5719                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5720
5721                 retval = cam_send_ccb(device, ccb);
5722
5723                 /*
5724                  * If we get an error from the ioctl, bail out.  SCSI
5725                  * errors are expected.
5726                  */
5727                 if (retval < 0) {
5728                         warn("error sending CAMIOCOMMAND ioctl");
5729                         if (arglist & CAM_ARG_VERBOSE) {
5730                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5731                                                 CAM_EPF_ALL, stderr);
5732                         }
5733                         error = 1;
5734                         goto scsiformat_bailout;
5735                 }
5736
5737                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5738
5739                 if ((status != CAM_REQ_CMP)
5740                  && (status == CAM_SCSI_STATUS_ERROR)
5741                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5742                         struct scsi_sense_data *sense;
5743                         int error_code, sense_key, asc, ascq;
5744
5745                         sense = &ccb->csio.sense_data;
5746                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
5747                             ccb->csio.sense_resid, &error_code, &sense_key,
5748                             &asc, &ascq, /*show_errors*/ 1);
5749
5750                         /*
5751                          * According to the SCSI-2 and SCSI-3 specs, a
5752                          * drive that is in the middle of a format should
5753                          * return NOT READY with an ASC of "logical unit
5754                          * not ready, format in progress".  The sense key
5755                          * specific bytes will then be a progress indicator.
5756                          */
5757                         if ((sense_key == SSD_KEY_NOT_READY)
5758                          && (asc == 0x04) && (ascq == 0x04)) {
5759                                 uint8_t sks[3];
5760
5761                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5762                                      ccb->csio.sense_resid, sks) == 0)
5763                                  && (quiet == 0)) {
5764                                         int val;
5765                                         u_int64_t percentage;
5766
5767                                         val = scsi_2btoul(&sks[1]);
5768                                         percentage = 10000 * val;
5769
5770                                         fprintf(stdout,
5771                                                 "\rFormatting:  %ju.%02u %% "
5772                                                 "(%d/%d) done",
5773                                                 (uintmax_t)(percentage /
5774                                                 (0x10000 * 100)),
5775                                                 (unsigned)((percentage /
5776                                                 0x10000) % 100),
5777                                                 val, 0x10000);
5778                                         fflush(stdout);
5779                                 } else if ((quiet == 0)
5780                                         && (++num_warnings <= 1)) {
5781                                         warnx("Unexpected SCSI Sense Key "
5782                                               "Specific value returned "
5783                                               "during format:");
5784                                         scsi_sense_print(device, &ccb->csio,
5785                                                          stderr);
5786                                         warnx("Unable to print status "
5787                                               "information, but format will "
5788                                               "proceed.");
5789                                         warnx("will exit when format is "
5790                                               "complete");
5791                                 }
5792                                 sleep(1);
5793                         } else {
5794                                 warnx("Unexpected SCSI error during format");
5795                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5796                                                 CAM_EPF_ALL, stderr);
5797                                 error = 1;
5798                                 goto scsiformat_bailout;
5799                         }
5800
5801                 } else if (status != CAM_REQ_CMP) {
5802                         warnx("Unexpected CAM status %#x", status);
5803                         if (arglist & CAM_ARG_VERBOSE)
5804                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5805                                                 CAM_EPF_ALL, stderr);
5806                         error = 1;
5807                         goto scsiformat_bailout;
5808                 }
5809
5810         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5811
5812         if (quiet == 0)
5813                 fprintf(stdout, "\nFormat Complete\n");
5814
5815 scsiformat_bailout:
5816
5817         cam_freeccb(ccb);
5818
5819         return(error);
5820 }
5821
5822 static int
5823 scsisanitize(struct cam_device *device, int argc, char **argv,
5824              char *combinedopt, int retry_count, int timeout)
5825 {
5826         union ccb *ccb;
5827         u_int8_t action = 0;
5828         int c;
5829         int ycount = 0, quiet = 0;
5830         int error = 0, retval = 0;
5831         int use_timeout = 10800 * 1000;
5832         int immediate = 1;
5833         int invert = 0;
5834         int passes = 0;
5835         int ause = 0;
5836         int fd = -1;
5837         const char *pattern = NULL;
5838         u_int8_t *data_ptr = NULL;
5839         u_int32_t dxfer_len = 0;
5840         u_int8_t byte2 = 0;
5841         int num_warnings = 0;
5842         int reportonly = 0;
5843
5844         ccb = cam_getccb(device);
5845
5846         if (ccb == NULL) {
5847                 warnx("scsisanitize: error allocating ccb");
5848                 return(1);
5849         }
5850
5851         bzero(&(&ccb->ccb_h)[1],
5852               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5853
5854         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5855                 switch(c) {
5856                 case 'a':
5857                         if (strcasecmp(optarg, "overwrite") == 0)
5858                                 action = SSZ_SERVICE_ACTION_OVERWRITE;
5859                         else if (strcasecmp(optarg, "block") == 0)
5860                                 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
5861                         else if (strcasecmp(optarg, "crypto") == 0)
5862                                 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
5863                         else if (strcasecmp(optarg, "exitfailure") == 0)
5864                                 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
5865                         else {
5866                                 warnx("invalid service operation \"%s\"",
5867                                       optarg);
5868                                 error = 1;
5869                                 goto scsisanitize_bailout;
5870                         }
5871                         break;
5872                 case 'c':
5873                         passes = strtol(optarg, NULL, 0);
5874                         if (passes < 1 || passes > 31) {
5875                                 warnx("invalid passes value %d", passes);
5876                                 error = 1;
5877                                 goto scsisanitize_bailout;
5878                         }
5879                         break;
5880                 case 'I':
5881                         invert = 1;
5882                         break;
5883                 case 'P':
5884                         pattern = optarg;
5885                         break;
5886                 case 'q':
5887                         quiet++;
5888                         break;
5889                 case 'U':
5890                         ause = 1;
5891                         break;
5892                 case 'r':
5893                         reportonly = 1;
5894                         break;
5895                 case 'w':
5896                         immediate = 0;
5897                         break;
5898                 case 'y':
5899                         ycount++;
5900                         break;
5901                 }
5902         }
5903
5904         if (reportonly)
5905                 goto doreport;
5906
5907         if (action == 0) {
5908                 warnx("an action is required");
5909                 error = 1;
5910                 goto scsisanitize_bailout;
5911         } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
5912                 struct scsi_sanitize_parameter_list *pl;
5913                 struct stat sb;
5914                 ssize_t sz, amt;
5915
5916                 if (pattern == NULL) {
5917                         warnx("overwrite action requires -P argument");
5918                         error = 1;
5919                         goto scsisanitize_bailout;
5920                 }
5921                 fd = open(pattern, O_RDONLY);
5922                 if (fd < 0) {
5923                         warn("cannot open pattern file %s", pattern);
5924                         error = 1;
5925                         goto scsisanitize_bailout;
5926                 }
5927                 if (fstat(fd, &sb) < 0) {
5928                         warn("cannot stat pattern file %s", pattern);
5929                         error = 1;
5930                         goto scsisanitize_bailout;
5931                 }
5932                 sz = sb.st_size;
5933                 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
5934                         warnx("pattern file size exceeds maximum value %d",
5935                               SSZPL_MAX_PATTERN_LENGTH);
5936                         error = 1;
5937                         goto scsisanitize_bailout;
5938                 }
5939                 dxfer_len = sizeof(*pl) + sz;
5940                 data_ptr = calloc(1, dxfer_len);
5941                 if (data_ptr == NULL) {
5942                         warnx("cannot allocate parameter list buffer");
5943                         error = 1;
5944                         goto scsisanitize_bailout;
5945                 }
5946
5947                 amt = read(fd, data_ptr + sizeof(*pl), sz);
5948                 if (amt < 0) {
5949                         warn("cannot read pattern file");
5950                         error = 1;
5951                         goto scsisanitize_bailout;
5952                 } else if (amt != sz) {
5953                         warnx("short pattern file read");
5954                         error = 1;
5955                         goto scsisanitize_bailout;
5956                 }
5957
5958                 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
5959                 if (passes == 0)
5960                         pl->byte1 = 1;
5961                 else
5962                         pl->byte1 = passes;
5963                 if (invert != 0)
5964                         pl->byte1 |= SSZPL_INVERT;
5965                 scsi_ulto2b(sz, pl->length);
5966         } else {
5967                 const char *arg;
5968
5969                 if (passes != 0)
5970                         arg = "-c";
5971                 else if (invert != 0)
5972                         arg = "-I";
5973                 else if (pattern != NULL)
5974                         arg = "-P";
5975                 else
5976                         arg = NULL;
5977                 if (arg != NULL) {
5978                         warnx("%s argument only valid with overwrite "
5979                               "operation", arg);
5980                         error = 1;
5981                         goto scsisanitize_bailout;
5982                 }
5983         }
5984
5985         if (quiet == 0) {
5986                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5987                         "following device:\n");
5988
5989                 error = scsidoinquiry(device, argc, argv, combinedopt,
5990                                       retry_count, timeout);
5991
5992                 if (error != 0) {
5993                         warnx("scsisanitize: error sending inquiry");
5994                         goto scsisanitize_bailout;
5995                 }
5996         }
5997
5998         if (ycount == 0) {
5999                 if (!get_confirmation()) {
6000                         error = 1;
6001                         goto scsisanitize_bailout;
6002                 }
6003         }
6004
6005         if (timeout != 0)
6006                 use_timeout = timeout;
6007
6008         if (quiet == 0) {
6009                 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6010                         use_timeout / 1000);
6011         }
6012
6013         /*
6014          * If the user hasn't disabled questions and didn't specify a
6015          * timeout on the command line, ask them if they want the current
6016          * timeout.
6017          */
6018         if ((ycount == 0)
6019          && (timeout == 0)) {
6020                 char str[1024];
6021                 int new_timeout = 0;
6022
6023                 fprintf(stdout, "Enter new timeout in seconds or press\n"
6024                         "return to keep the current timeout [%d] ",
6025                         use_timeout / 1000);
6026
6027                 if (fgets(str, sizeof(str), stdin) != NULL) {
6028                         if (str[0] != '\0')
6029                                 new_timeout = atoi(str);
6030                 }
6031
6032                 if (new_timeout != 0) {
6033                         use_timeout = new_timeout * 1000;
6034                         fprintf(stdout, "Using new timeout value %d\n",
6035                                 use_timeout / 1000);
6036                 }
6037         }
6038
6039         byte2 = action;
6040         if (ause != 0)
6041                 byte2 |= SSZ_UNRESTRICTED_EXIT;
6042         if (immediate != 0)
6043                 byte2 |= SSZ_IMMED;
6044
6045         scsi_sanitize(&ccb->csio,
6046                       /* retries */ retry_count,
6047                       /* cbfcnp */ NULL,
6048                       /* tag_action */ MSG_SIMPLE_Q_TAG,
6049                       /* byte2 */ byte2,
6050                       /* control */ 0,
6051                       /* data_ptr */ data_ptr,
6052                       /* dxfer_len */ dxfer_len,
6053                       /* sense_len */ SSD_FULL_SIZE,
6054                       /* timeout */ use_timeout);
6055
6056         /* Disable freezing the device queue */
6057         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6058
6059         if (arglist & CAM_ARG_ERR_RECOVER)
6060                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6061
6062         if (cam_send_ccb(device, ccb) < 0) {
6063                 warn("error sending sanitize command");
6064                 error = 1;
6065                 goto scsisanitize_bailout;
6066         }
6067
6068         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6069                 struct scsi_sense_data *sense;
6070                 int error_code, sense_key, asc, ascq;
6071
6072                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6073                     CAM_SCSI_STATUS_ERROR) {
6074                         sense = &ccb->csio.sense_data;
6075                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6076                             ccb->csio.sense_resid, &error_code, &sense_key,
6077                             &asc, &ascq, /*show_errors*/ 1);
6078
6079                         if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6080                             asc == 0x20 && ascq == 0x00)
6081                                 warnx("sanitize is not supported by "
6082                                       "this device");
6083                         else
6084                                 warnx("error sanitizing this device");
6085                 } else
6086                         warnx("error sanitizing this device");
6087
6088                 if (arglist & CAM_ARG_VERBOSE) {
6089                         cam_error_print(device, ccb, CAM_ESF_ALL,
6090                                         CAM_EPF_ALL, stderr);
6091                 }
6092                 error = 1;
6093                 goto scsisanitize_bailout;
6094         }
6095
6096         /*
6097          * If we ran in non-immediate mode, we already checked for errors
6098          * above and printed out any necessary information.  If we're in
6099          * immediate mode, we need to loop through and get status
6100          * information periodically.
6101          */
6102         if (immediate == 0) {
6103                 if (quiet == 0) {
6104                         fprintf(stdout, "Sanitize Complete\n");
6105                 }
6106                 goto scsisanitize_bailout;
6107         }
6108
6109 doreport:
6110         do {
6111                 cam_status status;
6112
6113                 bzero(&(&ccb->ccb_h)[1],
6114                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6115
6116                 /*
6117                  * There's really no need to do error recovery or
6118                  * retries here, since we're just going to sit in a
6119                  * loop and wait for the device to finish sanitizing.
6120                  */
6121                 scsi_test_unit_ready(&ccb->csio,
6122                                      /* retries */ 0,
6123                                      /* cbfcnp */ NULL,
6124                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
6125                                      /* sense_len */ SSD_FULL_SIZE,
6126                                      /* timeout */ 5000);
6127
6128                 /* Disable freezing the device queue */
6129                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6130
6131                 retval = cam_send_ccb(device, ccb);
6132
6133                 /*
6134                  * If we get an error from the ioctl, bail out.  SCSI
6135                  * errors are expected.
6136                  */
6137                 if (retval < 0) {
6138                         warn("error sending CAMIOCOMMAND ioctl");
6139                         if (arglist & CAM_ARG_VERBOSE) {
6140                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6141                                                 CAM_EPF_ALL, stderr);
6142                         }
6143                         error = 1;
6144                         goto scsisanitize_bailout;
6145                 }
6146
6147                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6148
6149                 if ((status != CAM_REQ_CMP)
6150                  && (status == CAM_SCSI_STATUS_ERROR)
6151                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6152                         struct scsi_sense_data *sense;
6153                         int error_code, sense_key, asc, ascq;
6154
6155                         sense = &ccb->csio.sense_data;
6156                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6157                             ccb->csio.sense_resid, &error_code, &sense_key,
6158                             &asc, &ascq, /*show_errors*/ 1);
6159
6160                         /*
6161                          * According to the SCSI-3 spec, a drive that is in the
6162                          * middle of a sanitize should return NOT READY with an
6163                          * ASC of "logical unit not ready, sanitize in
6164                          * progress". The sense key specific bytes will then
6165                          * be a progress indicator.
6166                          */
6167                         if ((sense_key == SSD_KEY_NOT_READY)
6168                          && (asc == 0x04) && (ascq == 0x1b)) {
6169                                 uint8_t sks[3];
6170
6171                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6172                                      ccb->csio.sense_resid, sks) == 0)
6173                                  && (quiet == 0)) {
6174                                         int val;
6175                                         u_int64_t percentage;
6176
6177                                         val = scsi_2btoul(&sks[1]);
6178                                         percentage = 10000 * val;
6179
6180                                         fprintf(stdout,
6181                                                 "\rSanitizing:  %ju.%02u %% "
6182                                                 "(%d/%d) done",
6183                                                 (uintmax_t)(percentage /
6184                                                 (0x10000 * 100)),
6185                                                 (unsigned)((percentage /
6186                                                 0x10000) % 100),
6187                                                 val, 0x10000);
6188                                         fflush(stdout);
6189                                 } else if ((quiet == 0)
6190                                         && (++num_warnings <= 1)) {
6191                                         warnx("Unexpected SCSI Sense Key "
6192                                               "Specific value returned "
6193                                               "during sanitize:");
6194                                         scsi_sense_print(device, &ccb->csio,
6195                                                          stderr);
6196                                         warnx("Unable to print status "
6197                                               "information, but sanitze will "
6198                                               "proceed.");
6199                                         warnx("will exit when sanitize is "
6200                                               "complete");
6201                                 }
6202                                 sleep(1);
6203                         } else {
6204                                 warnx("Unexpected SCSI error during sanitize");
6205                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6206                                                 CAM_EPF_ALL, stderr);
6207                                 error = 1;
6208                                 goto scsisanitize_bailout;
6209                         }
6210
6211                 } else if (status != CAM_REQ_CMP) {
6212                         warnx("Unexpected CAM status %#x", status);
6213                         if (arglist & CAM_ARG_VERBOSE)
6214                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6215                                                 CAM_EPF_ALL, stderr);
6216                         error = 1;
6217                         goto scsisanitize_bailout;
6218                 }
6219         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6220
6221         if (quiet == 0)
6222                 fprintf(stdout, "\nSanitize Complete\n");
6223
6224 scsisanitize_bailout:
6225         if (fd >= 0)
6226                 close(fd);
6227         if (data_ptr != NULL)
6228                 free(data_ptr);
6229         cam_freeccb(ccb);
6230
6231         return(error);
6232 }
6233
6234 static int
6235 scsireportluns(struct cam_device *device, int argc, char **argv,
6236                char *combinedopt, int retry_count, int timeout)
6237 {
6238         union ccb *ccb;
6239         int c, countonly, lunsonly;
6240         struct scsi_report_luns_data *lundata;
6241         int alloc_len;
6242         uint8_t report_type;
6243         uint32_t list_len, i, j;
6244         int retval;
6245
6246         retval = 0;
6247         lundata = NULL;
6248         report_type = RPL_REPORT_DEFAULT;
6249         ccb = cam_getccb(device);
6250
6251         if (ccb == NULL) {
6252                 warnx("%s: error allocating ccb", __func__);
6253                 return (1);
6254         }
6255
6256         bzero(&(&ccb->ccb_h)[1],
6257               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6258
6259         countonly = 0;
6260         lunsonly = 0;
6261
6262         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6263                 switch (c) {
6264                 case 'c':
6265                         countonly++;
6266                         break;
6267                 case 'l':
6268                         lunsonly++;
6269                         break;
6270                 case 'r':
6271                         if (strcasecmp(optarg, "default") == 0)
6272                                 report_type = RPL_REPORT_DEFAULT;
6273                         else if (strcasecmp(optarg, "wellknown") == 0)
6274                                 report_type = RPL_REPORT_WELLKNOWN;
6275                         else if (strcasecmp(optarg, "all") == 0)
6276                                 report_type = RPL_REPORT_ALL;
6277                         else {
6278                                 warnx("%s: invalid report type \"%s\"",
6279                                       __func__, optarg);
6280                                 retval = 1;
6281                                 goto bailout;
6282                         }
6283                         break;
6284                 default:
6285                         break;
6286                 }
6287         }
6288
6289         if ((countonly != 0)
6290          && (lunsonly != 0)) {
6291                 warnx("%s: you can only specify one of -c or -l", __func__);
6292                 retval = 1;
6293                 goto bailout;
6294         }
6295         /*
6296          * According to SPC-4, the allocation length must be at least 16
6297          * bytes -- enough for the header and one LUN.
6298          */
6299         alloc_len = sizeof(*lundata) + 8;
6300
6301 retry:
6302
6303         lundata = malloc(alloc_len);
6304
6305         if (lundata == NULL) {
6306                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6307                 retval = 1;
6308                 goto bailout;
6309         }
6310
6311         scsi_report_luns(&ccb->csio,
6312                          /*retries*/ retry_count,
6313                          /*cbfcnp*/ NULL,
6314                          /*tag_action*/ MSG_SIMPLE_Q_TAG,
6315                          /*select_report*/ report_type,
6316                          /*rpl_buf*/ lundata,
6317                          /*alloc_len*/ alloc_len,
6318                          /*sense_len*/ SSD_FULL_SIZE,
6319                          /*timeout*/ timeout ? timeout : 5000);
6320
6321         /* Disable freezing the device queue */
6322         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6323
6324         if (arglist & CAM_ARG_ERR_RECOVER)
6325                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6326
6327         if (cam_send_ccb(device, ccb) < 0) {
6328                 warn("error sending REPORT LUNS command");
6329
6330                 if (arglist & CAM_ARG_VERBOSE)
6331                         cam_error_print(device, ccb, CAM_ESF_ALL,
6332                                         CAM_EPF_ALL, stderr);
6333
6334                 retval = 1;
6335                 goto bailout;
6336         }
6337
6338         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6339                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6340                 retval = 1;
6341                 goto bailout;
6342         }
6343
6344
6345         list_len = scsi_4btoul(lundata->length);
6346
6347         /*
6348          * If we need to list the LUNs, and our allocation
6349          * length was too short, reallocate and retry.
6350          */
6351         if ((countonly == 0)
6352          && (list_len > (alloc_len - sizeof(*lundata)))) {
6353                 alloc_len = list_len + sizeof(*lundata);
6354                 free(lundata);
6355                 goto retry;
6356         }
6357
6358         if (lunsonly == 0)
6359                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6360                         ((list_len / 8) > 1) ? "s" : "");
6361
6362         if (countonly != 0)
6363                 goto bailout;
6364
6365         for (i = 0; i < (list_len / 8); i++) {
6366                 int no_more;
6367
6368                 no_more = 0;
6369                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6370                         if (j != 0)
6371                                 fprintf(stdout, ",");
6372                         switch (lundata->luns[i].lundata[j] &
6373                                 RPL_LUNDATA_ATYP_MASK) {
6374                         case RPL_LUNDATA_ATYP_PERIPH:
6375                                 if ((lundata->luns[i].lundata[j] &
6376                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6377                                         fprintf(stdout, "%d:",
6378                                                 lundata->luns[i].lundata[j] &
6379                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
6380                                 else if ((j == 0)
6381                                       && ((lundata->luns[i].lundata[j+2] &
6382                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6383                                         no_more = 1;
6384
6385                                 fprintf(stdout, "%d",
6386                                         lundata->luns[i].lundata[j+1]);
6387                                 break;
6388                         case RPL_LUNDATA_ATYP_FLAT: {
6389                                 uint8_t tmplun[2];
6390                                 tmplun[0] = lundata->luns[i].lundata[j] &
6391                                         RPL_LUNDATA_FLAT_LUN_MASK;
6392                                 tmplun[1] = lundata->luns[i].lundata[j+1];
6393
6394                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6395                                 no_more = 1;
6396                                 break;
6397                         }
6398                         case RPL_LUNDATA_ATYP_LUN:
6399                                 fprintf(stdout, "%d:%d:%d",
6400                                         (lundata->luns[i].lundata[j+1] &
6401                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6402                                         lundata->luns[i].lundata[j] &
6403                                         RPL_LUNDATA_LUN_TARG_MASK,
6404                                         lundata->luns[i].lundata[j+1] &
6405                                         RPL_LUNDATA_LUN_LUN_MASK);
6406                                 break;
6407                         case RPL_LUNDATA_ATYP_EXTLUN: {
6408                                 int field_len_code, eam_code;
6409
6410                                 eam_code = lundata->luns[i].lundata[j] &
6411                                         RPL_LUNDATA_EXT_EAM_MASK;
6412                                 field_len_code = (lundata->luns[i].lundata[j] &
6413                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6414
6415                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6416                                  && (field_len_code == 0x00)) {
6417                                         fprintf(stdout, "%d",
6418                                                 lundata->luns[i].lundata[j+1]);
6419                                 } else if ((eam_code ==
6420                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6421                                         && (field_len_code == 0x03)) {
6422                                         uint8_t tmp_lun[8];
6423
6424                                         /*
6425                                          * This format takes up all 8 bytes.
6426                                          * If we aren't starting at offset 0,
6427                                          * that's a bug.
6428                                          */
6429                                         if (j != 0) {
6430                                                 fprintf(stdout, "Invalid "
6431                                                         "offset %d for "
6432                                                         "Extended LUN not "
6433                                                         "specified format", j);
6434                                                 no_more = 1;
6435                                                 break;
6436                                         }
6437                                         bzero(tmp_lun, sizeof(tmp_lun));
6438                                         bcopy(&lundata->luns[i].lundata[j+1],
6439                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
6440                                         fprintf(stdout, "%#jx",
6441                                                (intmax_t)scsi_8btou64(tmp_lun));
6442                                         no_more = 1;
6443                                 } else {
6444                                         fprintf(stderr, "Unknown Extended LUN"
6445                                                 "Address method %#x, length "
6446                                                 "code %#x", eam_code,
6447                                                 field_len_code);
6448                                         no_more = 1;
6449                                 }
6450                                 break;
6451                         }
6452                         default:
6453                                 fprintf(stderr, "Unknown LUN address method "
6454                                         "%#x\n", lundata->luns[i].lundata[0] &
6455                                         RPL_LUNDATA_ATYP_MASK);
6456                                 break;
6457                         }
6458                         /*
6459                          * For the flat addressing method, there are no
6460                          * other levels after it.
6461                          */
6462                         if (no_more != 0)
6463                                 break;
6464                 }
6465                 fprintf(stdout, "\n");
6466         }
6467
6468 bailout:
6469
6470         cam_freeccb(ccb);
6471
6472         free(lundata);
6473
6474         return (retval);
6475 }
6476
6477 static int
6478 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6479                  char *combinedopt, int retry_count, int timeout)
6480 {
6481         union ccb *ccb;
6482         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6483         struct scsi_read_capacity_data rcap;
6484         struct scsi_read_capacity_data_long rcaplong;
6485         uint64_t maxsector;
6486         uint32_t block_len;
6487         int retval;
6488         int c;
6489
6490         blocksizeonly = 0;
6491         humanize = 0;
6492         numblocks = 0;
6493         quiet = 0;
6494         sizeonly = 0;
6495         baseten = 0;
6496         retval = 0;
6497
6498         ccb = cam_getccb(device);
6499
6500         if (ccb == NULL) {
6501                 warnx("%s: error allocating ccb", __func__);
6502                 return (1);
6503         }
6504
6505         bzero(&(&ccb->ccb_h)[1],
6506               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6507
6508         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6509                 switch (c) {
6510                 case 'b':
6511                         blocksizeonly++;
6512                         break;
6513                 case 'h':
6514                         humanize++;
6515                         baseten = 0;
6516                         break;
6517                 case 'H':
6518                         humanize++;
6519                         baseten++;
6520                         break;
6521                 case 'N':
6522                         numblocks++;
6523                         break;
6524                 case 'q':
6525                         quiet++;
6526                         break;
6527                 case 's':
6528                         sizeonly++;
6529                         break;
6530                 default:
6531                         break;
6532                 }
6533         }
6534
6535         if ((blocksizeonly != 0)
6536          && (numblocks != 0)) {
6537                 warnx("%s: you can only specify one of -b or -N", __func__);
6538                 retval = 1;
6539                 goto bailout;
6540         }
6541
6542         if ((blocksizeonly != 0)
6543          && (sizeonly != 0)) {
6544                 warnx("%s: you can only specify one of -b or -s", __func__);
6545                 retval = 1;
6546                 goto bailout;
6547         }
6548
6549         if ((humanize != 0)
6550          && (quiet != 0)) {
6551                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6552                 retval = 1;
6553                 goto bailout;
6554         }
6555
6556         if ((humanize != 0)
6557          && (blocksizeonly != 0)) {
6558                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6559                 retval = 1;
6560                 goto bailout;
6561         }
6562
6563         scsi_read_capacity(&ccb->csio,
6564                            /*retries*/ retry_count,
6565                            /*cbfcnp*/ NULL,
6566                            /*tag_action*/ MSG_SIMPLE_Q_TAG,
6567                            &rcap,
6568                            SSD_FULL_SIZE,
6569                            /*timeout*/ timeout ? timeout : 5000);
6570
6571         /* Disable freezing the device queue */
6572         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6573
6574         if (arglist & CAM_ARG_ERR_RECOVER)
6575                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6576
6577         if (cam_send_ccb(device, ccb) < 0) {
6578                 warn("error sending READ CAPACITY command");
6579
6580                 if (arglist & CAM_ARG_VERBOSE)
6581                         cam_error_print(device, ccb, CAM_ESF_ALL,
6582                                         CAM_EPF_ALL, stderr);
6583
6584                 retval = 1;
6585                 goto bailout;
6586         }
6587
6588         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6589                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6590                 retval = 1;
6591                 goto bailout;
6592         }
6593
6594         maxsector = scsi_4btoul(rcap.addr);
6595         block_len = scsi_4btoul(rcap.length);
6596
6597         /*
6598          * A last block of 2^32-1 means that the true capacity is over 2TB,
6599          * and we need to issue the long READ CAPACITY to get the real
6600          * capacity.  Otherwise, we're all set.
6601          */
6602         if (maxsector != 0xffffffff)
6603                 goto do_print;
6604
6605         scsi_read_capacity_16(&ccb->csio,
6606                               /*retries*/ retry_count,
6607                               /*cbfcnp*/ NULL,
6608                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
6609                               /*lba*/ 0,
6610                               /*reladdr*/ 0,
6611                               /*pmi*/ 0,
6612                               /*rcap_buf*/ (uint8_t *)&rcaplong,
6613                               /*rcap_buf_len*/ sizeof(rcaplong),
6614                               /*sense_len*/ SSD_FULL_SIZE,
6615                               /*timeout*/ timeout ? timeout : 5000);
6616
6617         /* Disable freezing the device queue */
6618         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6619
6620         if (arglist & CAM_ARG_ERR_RECOVER)
6621                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6622
6623         if (cam_send_ccb(device, ccb) < 0) {
6624                 warn("error sending READ CAPACITY (16) command");
6625
6626                 if (arglist & CAM_ARG_VERBOSE)
6627                         cam_error_print(device, ccb, CAM_ESF_ALL,
6628                                         CAM_EPF_ALL, stderr);
6629
6630                 retval = 1;
6631                 goto bailout;
6632         }
6633
6634         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6635                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6636                 retval = 1;
6637                 goto bailout;
6638         }
6639
6640         maxsector = scsi_8btou64(rcaplong.addr);
6641         block_len = scsi_4btoul(rcaplong.length);
6642
6643 do_print:
6644         if (blocksizeonly == 0) {
6645                 /*
6646                  * Humanize implies !quiet, and also implies numblocks.
6647                  */
6648                 if (humanize != 0) {
6649                         char tmpstr[6];
6650                         int64_t tmpbytes;
6651                         int ret;
6652
6653                         tmpbytes = (maxsector + 1) * block_len;
6654                         ret = humanize_number(tmpstr, sizeof(tmpstr),
6655                                               tmpbytes, "", HN_AUTOSCALE,
6656                                               HN_B | HN_DECIMAL |
6657                                               ((baseten != 0) ?
6658                                               HN_DIVISOR_1000 : 0));
6659                         if (ret == -1) {
6660                                 warnx("%s: humanize_number failed!", __func__);
6661                                 retval = 1;
6662                                 goto bailout;
6663                         }
6664                         fprintf(stdout, "Device Size: %s%s", tmpstr,
6665                                 (sizeonly == 0) ?  ", " : "\n");
6666                 } else if (numblocks != 0) {
6667                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6668                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
6669                                 (sizeonly == 0) ? ", " : "\n");
6670                 } else {
6671                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6672                                 "Last Block: " : "", (uintmax_t)maxsector,
6673                                 (sizeonly == 0) ? ", " : "\n");
6674                 }
6675         }
6676         if (sizeonly == 0)
6677                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6678                         "Block Length: " : "", block_len, (quiet == 0) ?
6679                         " bytes" : "");
6680 bailout:
6681         cam_freeccb(ccb);
6682
6683         return (retval);
6684 }
6685
6686 static int
6687 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6688        int retry_count, int timeout)
6689 {
6690         int c, error = 0;
6691         union ccb *ccb;
6692         uint8_t *smp_request = NULL, *smp_response = NULL;
6693         int request_size = 0, response_size = 0;
6694         int fd_request = 0, fd_response = 0;
6695         char *datastr = NULL;
6696         struct get_hook hook;
6697         int retval;
6698         int flags = 0;
6699
6700         /*
6701          * Note that at the moment we don't support sending SMP CCBs to
6702          * devices that aren't probed by CAM.
6703          */
6704         ccb = cam_getccb(device);
6705         if (ccb == NULL) {
6706                 warnx("%s: error allocating CCB", __func__);
6707                 return (1);
6708         }
6709
6710         bzero(&(&ccb->ccb_h)[1],
6711               sizeof(union ccb) - sizeof(struct ccb_hdr));
6712
6713         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6714                 switch (c) {
6715                 case 'R':
6716                         arglist |= CAM_ARG_CMD_IN;
6717                         response_size = strtol(optarg, NULL, 0);
6718                         if (response_size <= 0) {
6719                                 warnx("invalid number of response bytes %d",
6720                                       response_size);
6721                                 error = 1;
6722                                 goto smpcmd_bailout;
6723                         }
6724                         hook.argc = argc - optind;
6725                         hook.argv = argv + optind;
6726                         hook.got = 0;
6727                         optind++;
6728                         datastr = cget(&hook, NULL);
6729                         /*
6730                          * If the user supplied "-" instead of a format, he
6731                          * wants the data to be written to stdout.
6732                          */
6733                         if ((datastr != NULL)
6734                          && (datastr[0] == '-'))
6735                                 fd_response = 1;
6736
6737                         smp_response = (u_int8_t *)malloc(response_size);
6738                         if (smp_response == NULL) {
6739                                 warn("can't malloc memory for SMP response");
6740                                 error = 1;
6741                                 goto smpcmd_bailout;
6742                         }
6743                         break;
6744                 case 'r':
6745                         arglist |= CAM_ARG_CMD_OUT;
6746                         request_size = strtol(optarg, NULL, 0);
6747                         if (request_size <= 0) {
6748                                 warnx("invalid number of request bytes %d",
6749                                       request_size);
6750                                 error = 1;
6751                                 goto smpcmd_bailout;
6752                         }
6753                         hook.argc = argc - optind;
6754                         hook.argv = argv + optind;
6755                         hook.got = 0;
6756                         datastr = cget(&hook, NULL);
6757                         smp_request = (u_int8_t *)malloc(request_size);
6758                         if (smp_request == NULL) {
6759                                 warn("can't malloc memory for SMP request");
6760                                 error = 1;
6761                                 goto smpcmd_bailout;
6762                         }
6763                         bzero(smp_request, request_size);
6764                         /*
6765                          * If the user supplied "-" instead of a format, he
6766                          * wants the data to be read from stdin.
6767                          */
6768                         if ((datastr != NULL)
6769                          && (datastr[0] == '-'))
6770                                 fd_request = 1;
6771                         else
6772                                 buff_encode_visit(smp_request, request_size,
6773                                                   datastr,
6774                                                   iget, &hook);
6775                         optind += hook.got;
6776                         break;
6777                 default:
6778                         break;
6779                 }
6780         }
6781
6782         /*
6783          * If fd_data is set, and we're writing to the device, we need to
6784          * read the data the user wants written from stdin.
6785          */
6786         if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6787                 ssize_t amt_read;
6788                 int amt_to_read = request_size;
6789                 u_int8_t *buf_ptr = smp_request;
6790
6791                 for (amt_read = 0; amt_to_read > 0;
6792                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6793                         if (amt_read == -1) {
6794                                 warn("error reading data from stdin");
6795                                 error = 1;
6796                                 goto smpcmd_bailout;
6797                         }
6798                         amt_to_read -= amt_read;
6799                         buf_ptr += amt_read;
6800                 }
6801         }
6802
6803         if (((arglist & CAM_ARG_CMD_IN) == 0)
6804          || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6805                 warnx("%s: need both the request (-r) and response (-R) "
6806                       "arguments", __func__);
6807                 error = 1;
6808                 goto smpcmd_bailout;
6809         }
6810
6811         flags |= CAM_DEV_QFRZDIS;
6812
6813         cam_fill_smpio(&ccb->smpio,
6814                        /*retries*/ retry_count,
6815                        /*cbfcnp*/ NULL,
6816                        /*flags*/ flags,
6817                        /*smp_request*/ smp_request,
6818                        /*smp_request_len*/ request_size,
6819                        /*smp_response*/ smp_response,
6820                        /*smp_response_len*/ response_size,
6821                        /*timeout*/ timeout ? timeout : 5000);
6822
6823         ccb->smpio.flags = SMP_FLAG_NONE;
6824
6825         if (((retval = cam_send_ccb(device, ccb)) < 0)
6826          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6827                 const char warnstr[] = "error sending command";
6828
6829                 if (retval < 0)
6830                         warn(warnstr);
6831                 else
6832                         warnx(warnstr);
6833
6834                 if (arglist & CAM_ARG_VERBOSE) {
6835                         cam_error_print(device, ccb, CAM_ESF_ALL,
6836                                         CAM_EPF_ALL, stderr);
6837                 }
6838         }
6839
6840         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6841          && (response_size > 0)) {
6842                 if (fd_response == 0) {
6843                         buff_decode_visit(smp_response, response_size,
6844                                           datastr, arg_put, NULL);
6845                         fprintf(stdout, "\n");
6846                 } else {
6847                         ssize_t amt_written;
6848                         int amt_to_write = response_size;
6849                         u_int8_t *buf_ptr = smp_response;
6850
6851                         for (amt_written = 0; (amt_to_write > 0) &&
6852                              (amt_written = write(STDOUT_FILENO, buf_ptr,
6853                                                   amt_to_write)) > 0;){
6854                                 amt_to_write -= amt_written;
6855                                 buf_ptr += amt_written;
6856                         }
6857                         if (amt_written == -1) {
6858                                 warn("error writing data to stdout");
6859                                 error = 1;
6860                                 goto smpcmd_bailout;
6861                         } else if ((amt_written == 0)
6862                                 && (amt_to_write > 0)) {
6863                                 warnx("only wrote %u bytes out of %u",
6864                                       response_size - amt_to_write, 
6865                                       response_size);
6866                         }
6867                 }
6868         }
6869 smpcmd_bailout:
6870         if (ccb != NULL)
6871                 cam_freeccb(ccb);
6872
6873         if (smp_request != NULL)
6874                 free(smp_request);
6875
6876         if (smp_response != NULL)
6877                 free(smp_response);
6878
6879         return (error);
6880 }
6881
6882 static int
6883 smpreportgeneral(struct cam_device *device, int argc, char **argv,
6884                  char *combinedopt, int retry_count, int timeout)
6885 {
6886         union ccb *ccb;
6887         struct smp_report_general_request *request = NULL;
6888         struct smp_report_general_response *response = NULL;
6889         struct sbuf *sb = NULL;
6890         int error = 0;
6891         int c, long_response = 0;
6892         int retval;
6893
6894         /*
6895          * Note that at the moment we don't support sending SMP CCBs to
6896          * devices that aren't probed by CAM.
6897          */
6898         ccb = cam_getccb(device);
6899         if (ccb == NULL) {
6900                 warnx("%s: error allocating CCB", __func__);
6901                 return (1);
6902         }
6903
6904         bzero(&(&ccb->ccb_h)[1],
6905               sizeof(union ccb) - sizeof(struct ccb_hdr));
6906
6907         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6908                 switch (c) {
6909                 case 'l':
6910                         long_response = 1;
6911                         break;
6912                 default:
6913                         break;
6914                 }
6915         }
6916         request = malloc(sizeof(*request));
6917         if (request == NULL) {
6918                 warn("%s: unable to allocate %zd bytes", __func__,
6919                      sizeof(*request));
6920                 error = 1;
6921                 goto bailout;
6922         }
6923
6924         response = malloc(sizeof(*response));
6925         if (response == NULL) {
6926                 warn("%s: unable to allocate %zd bytes", __func__,
6927                      sizeof(*response));
6928                 error = 1;
6929                 goto bailout;
6930         }
6931
6932 try_long:
6933         smp_report_general(&ccb->smpio,
6934                            retry_count,
6935                            /*cbfcnp*/ NULL,
6936                            request,
6937                            /*request_len*/ sizeof(*request),
6938                            (uint8_t *)response,
6939                            /*response_len*/ sizeof(*response),
6940                            /*long_response*/ long_response,
6941                            timeout);
6942
6943         if (((retval = cam_send_ccb(device, ccb)) < 0)
6944          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6945                 const char warnstr[] = "error sending command";
6946
6947                 if (retval < 0)
6948                         warn(warnstr);
6949                 else
6950                         warnx(warnstr);
6951
6952                 if (arglist & CAM_ARG_VERBOSE) {
6953                         cam_error_print(device, ccb, CAM_ESF_ALL,
6954                                         CAM_EPF_ALL, stderr);
6955                 }
6956                 error = 1;
6957                 goto bailout;
6958         }
6959
6960         /*
6961          * If the device supports the long response bit, try again and see
6962          * if we can get all of the data.
6963          */
6964         if ((response->long_response & SMP_RG_LONG_RESPONSE)
6965          && (long_response == 0)) {
6966                 ccb->ccb_h.status = CAM_REQ_INPROG;
6967                 bzero(&(&ccb->ccb_h)[1],
6968                       sizeof(union ccb) - sizeof(struct ccb_hdr));
6969                 long_response = 1;
6970                 goto try_long;
6971         }
6972
6973         /*
6974          * XXX KDM detect and decode SMP errors here.
6975          */
6976         sb = sbuf_new_auto();
6977         if (sb == NULL) {
6978                 warnx("%s: error allocating sbuf", __func__);
6979                 goto bailout;
6980         }
6981
6982         smp_report_general_sbuf(response, sizeof(*response), sb);
6983
6984         if (sbuf_finish(sb) != 0) {
6985                 warnx("%s: sbuf_finish", __func__);
6986                 goto bailout;
6987         }
6988
6989         printf("%s", sbuf_data(sb));
6990
6991 bailout:
6992         if (ccb != NULL)
6993                 cam_freeccb(ccb);
6994
6995         if (request != NULL)
6996                 free(request);
6997
6998         if (response != NULL)
6999                 free(response);
7000
7001         if (sb != NULL)
7002                 sbuf_delete(sb);
7003
7004         return (error);
7005 }
7006
7007 static struct camcontrol_opts phy_ops[] = {
7008         {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7009         {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7010         {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7011         {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7012         {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7013         {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7014         {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7015         {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7016         {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7017         {NULL, 0, 0, NULL}
7018 };
7019
7020 static int
7021 smpphycontrol(struct cam_device *device, int argc, char **argv,
7022               char *combinedopt, int retry_count, int timeout)
7023 {
7024         union ccb *ccb;
7025         struct smp_phy_control_request *request = NULL;
7026         struct smp_phy_control_response *response = NULL;
7027         int long_response = 0;
7028         int retval = 0;
7029         int phy = -1;
7030         uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7031         int phy_op_set = 0;
7032         uint64_t attached_dev_name = 0;
7033         int dev_name_set = 0;
7034         uint32_t min_plr = 0, max_plr = 0;
7035         uint32_t pp_timeout_val = 0;
7036         int slumber_partial = 0;
7037         int set_pp_timeout_val = 0;
7038         int c;
7039
7040         /*
7041          * Note that at the moment we don't support sending SMP CCBs to
7042          * devices that aren't probed by CAM.
7043          */
7044         ccb = cam_getccb(device);
7045         if (ccb == NULL) {
7046                 warnx("%s: error allocating CCB", __func__);
7047                 return (1);
7048         }
7049
7050         bzero(&(&ccb->ccb_h)[1],
7051               sizeof(union ccb) - sizeof(struct ccb_hdr));
7052
7053         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7054                 switch (c) {
7055                 case 'a':
7056                 case 'A':
7057                 case 's':
7058                 case 'S': {
7059                         int enable = -1;
7060
7061                         if (strcasecmp(optarg, "enable") == 0)
7062                                 enable = 1;
7063                         else if (strcasecmp(optarg, "disable") == 0)
7064                                 enable = 2;
7065                         else {
7066                                 warnx("%s: Invalid argument %s", __func__,
7067                                       optarg);
7068                                 retval = 1;
7069                                 goto bailout;
7070                         }
7071                         switch (c) {
7072                         case 's':
7073                                 slumber_partial |= enable <<
7074                                                    SMP_PC_SAS_SLUMBER_SHIFT;
7075                                 break;
7076                         case 'S':
7077                                 slumber_partial |= enable <<
7078                                                    SMP_PC_SAS_PARTIAL_SHIFT;
7079                                 break;
7080                         case 'a':
7081                                 slumber_partial |= enable <<
7082                                                    SMP_PC_SATA_SLUMBER_SHIFT;
7083                                 break;
7084                         case 'A':
7085                                 slumber_partial |= enable <<
7086                                                    SMP_PC_SATA_PARTIAL_SHIFT;
7087                                 break;
7088                         default:
7089                                 warnx("%s: programmer error", __func__);
7090                                 retval = 1;
7091                                 goto bailout;
7092                                 break; /*NOTREACHED*/
7093                         }
7094                         break;
7095                 }
7096                 case 'd':
7097                         attached_dev_name = (uintmax_t)strtoumax(optarg,
7098                                                                  NULL,0);
7099                         dev_name_set = 1;
7100                         break;
7101                 case 'l':
7102                         long_response = 1;
7103                         break;
7104                 case 'm':
7105                         /*
7106                          * We don't do extensive checking here, so this
7107                          * will continue to work when new speeds come out.
7108                          */
7109                         min_plr = strtoul(optarg, NULL, 0);
7110                         if ((min_plr == 0)
7111                          || (min_plr > 0xf)) {
7112                                 warnx("%s: invalid link rate %x",
7113                                       __func__, min_plr);
7114                                 retval = 1;
7115                                 goto bailout;
7116                         }
7117                         break;
7118                 case 'M':
7119                         /*
7120                          * We don't do extensive checking here, so this
7121                          * will continue to work when new speeds come out.
7122                          */
7123                         max_plr = strtoul(optarg, NULL, 0);
7124                         if ((max_plr == 0)
7125                          || (max_plr > 0xf)) {
7126                                 warnx("%s: invalid link rate %x",
7127                                       __func__, max_plr);
7128                                 retval = 1;
7129                                 goto bailout;
7130                         }
7131                         break;
7132                 case 'o': {
7133                         camcontrol_optret optreturn;
7134                         cam_argmask argnums;
7135                         const char *subopt;
7136
7137                         if (phy_op_set != 0) {
7138                                 warnx("%s: only one phy operation argument "
7139                                       "(-o) allowed", __func__);
7140                                 retval = 1;
7141                                 goto bailout;
7142                         }
7143
7144                         phy_op_set = 1;
7145
7146                         /*
7147                          * Allow the user to specify the phy operation
7148                          * numerically, as well as with a name.  This will
7149                          * future-proof it a bit, so options that are added
7150                          * in future specs can be used.
7151                          */
7152                         if (isdigit(optarg[0])) {
7153                                 phy_operation = strtoul(optarg, NULL, 0);
7154                                 if ((phy_operation == 0)
7155                                  || (phy_operation > 0xff)) {
7156                                         warnx("%s: invalid phy operation %#x",
7157                                               __func__, phy_operation);
7158                                         retval = 1;
7159                                         goto bailout;
7160                                 }
7161                                 break;
7162                         }
7163                         optreturn = getoption(phy_ops, optarg, &phy_operation,
7164                                               &argnums, &subopt);
7165
7166                         if (optreturn == CC_OR_AMBIGUOUS) {
7167                                 warnx("%s: ambiguous option %s", __func__,
7168                                       optarg);
7169                                 usage(0);
7170                                 retval = 1;
7171                                 goto bailout;
7172                         } else if (optreturn == CC_OR_NOT_FOUND) {
7173                                 warnx("%s: option %s not found", __func__,
7174                                       optarg);
7175                                 usage(0);
7176                                 retval = 1;
7177                                 goto bailout;
7178                         }
7179                         break;
7180                 }
7181                 case 'p':
7182                         phy = atoi(optarg);
7183                         break;
7184                 case 'T':
7185                         pp_timeout_val = strtoul(optarg, NULL, 0);
7186                         if (pp_timeout_val > 15) {
7187                                 warnx("%s: invalid partial pathway timeout "
7188                                       "value %u, need a value less than 16",
7189                                       __func__, pp_timeout_val);
7190                                 retval = 1;
7191                                 goto bailout;
7192                         }
7193                         set_pp_timeout_val = 1;
7194                         break;
7195                 default:
7196                         break;
7197                 }
7198         }
7199
7200         if (phy == -1) {
7201                 warnx("%s: a PHY (-p phy) argument is required",__func__);
7202                 retval = 1;
7203                 goto bailout;
7204         }
7205
7206         if (((dev_name_set != 0)
7207           && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7208          || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7209           && (dev_name_set == 0))) {
7210                 warnx("%s: -d name and -o setdevname arguments both "
7211                       "required to set device name", __func__);
7212                 retval = 1;
7213                 goto bailout;
7214         }
7215
7216         request = malloc(sizeof(*request));
7217         if (request == NULL) {
7218                 warn("%s: unable to allocate %zd bytes", __func__,
7219                      sizeof(*request));
7220                 retval = 1;
7221                 goto bailout;
7222         }
7223
7224         response = malloc(sizeof(*response));
7225         if (response == NULL) {
7226                 warn("%s: unable to allocate %zd bytes", __func__,
7227                      sizeof(*request));
7228                 retval = 1;
7229                 goto bailout;
7230         }
7231
7232         smp_phy_control(&ccb->smpio,
7233                         retry_count,
7234                         /*cbfcnp*/ NULL,
7235                         request,
7236                         sizeof(*request),
7237                         (uint8_t *)response,
7238                         sizeof(*response),
7239                         long_response,
7240                         /*expected_exp_change_count*/ 0,
7241                         phy,
7242                         phy_operation,
7243                         (set_pp_timeout_val != 0) ? 1 : 0,
7244                         attached_dev_name,
7245                         min_plr,
7246                         max_plr,
7247                         slumber_partial,
7248                         pp_timeout_val,
7249                         timeout);
7250
7251         if (((retval = cam_send_ccb(device, ccb)) < 0)
7252          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7253                 const char warnstr[] = "error sending command";
7254
7255                 if (retval < 0)
7256                         warn(warnstr);
7257                 else
7258                         warnx(warnstr);
7259
7260                 if (arglist & CAM_ARG_VERBOSE) {
7261                         /*
7262                          * Use CAM_EPF_NORMAL so we only get one line of
7263                          * SMP command decoding.
7264                          */
7265                         cam_error_print(device, ccb, CAM_ESF_ALL,
7266                                         CAM_EPF_NORMAL, stderr);
7267                 }
7268                 retval = 1;
7269                 goto bailout;
7270         }
7271
7272         /* XXX KDM print out something here for success? */
7273 bailout:
7274         if (ccb != NULL)
7275                 cam_freeccb(ccb);
7276
7277         if (request != NULL)
7278                 free(request);
7279
7280         if (response != NULL)
7281                 free(response);
7282
7283         return (retval);
7284 }
7285
7286 static int
7287 smpmaninfo(struct cam_device *device, int argc, char **argv,
7288            char *combinedopt, int retry_count, int timeout)
7289 {
7290         union ccb *ccb;
7291         struct smp_report_manuf_info_request request;
7292         struct smp_report_manuf_info_response response;
7293         struct sbuf *sb = NULL;
7294         int long_response = 0;
7295         int retval = 0;
7296         int c;
7297
7298         /*
7299          * Note that at the moment we don't support sending SMP CCBs to
7300          * devices that aren't probed by CAM.
7301          */
7302         ccb = cam_getccb(device);
7303         if (ccb == NULL) {
7304                 warnx("%s: error allocating CCB", __func__);
7305                 return (1);
7306         }
7307
7308         bzero(&(&ccb->ccb_h)[1],
7309               sizeof(union ccb) - sizeof(struct ccb_hdr));
7310
7311         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7312                 switch (c) {
7313                 case 'l':
7314                         long_response = 1;
7315                         break;
7316                 default:
7317                         break;
7318                 }
7319         }
7320         bzero(&request, sizeof(request));
7321         bzero(&response, sizeof(response));
7322
7323         smp_report_manuf_info(&ccb->smpio,
7324                               retry_count,
7325                               /*cbfcnp*/ NULL,
7326                               &request,
7327                               sizeof(request),
7328                               (uint8_t *)&response,
7329                               sizeof(response),
7330                               long_response,
7331                               timeout);
7332
7333         if (((retval = cam_send_ccb(device, ccb)) < 0)
7334          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7335                 const char warnstr[] = "error sending command";
7336
7337                 if (retval < 0)
7338                         warn(warnstr);
7339                 else
7340                         warnx(warnstr);
7341
7342                 if (arglist & CAM_ARG_VERBOSE) {
7343                         cam_error_print(device, ccb, CAM_ESF_ALL,
7344                                         CAM_EPF_ALL, stderr);
7345                 }
7346                 retval = 1;
7347                 goto bailout;
7348         }
7349
7350         sb = sbuf_new_auto();
7351         if (sb == NULL) {
7352                 warnx("%s: error allocating sbuf", __func__);
7353                 goto bailout;
7354         }
7355
7356         smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7357
7358         if (sbuf_finish(sb) != 0) {
7359                 warnx("%s: sbuf_finish", __func__);
7360                 goto bailout;
7361         }
7362
7363         printf("%s", sbuf_data(sb));
7364
7365 bailout:
7366
7367         if (ccb != NULL)
7368                 cam_freeccb(ccb);
7369
7370         if (sb != NULL)
7371                 sbuf_delete(sb);
7372
7373         return (retval);
7374 }
7375
7376 static int
7377 getdevid(struct cam_devitem *item)
7378 {
7379         int retval = 0;
7380         union ccb *ccb = NULL;
7381
7382         struct cam_device *dev;
7383
7384         dev = cam_open_btl(item->dev_match.path_id,
7385                            item->dev_match.target_id,
7386                            item->dev_match.target_lun, O_RDWR, NULL);
7387
7388         if (dev == NULL) {
7389                 warnx("%s", cam_errbuf);
7390                 retval = 1;
7391                 goto bailout;
7392         }
7393
7394         item->device_id_len = 0;
7395
7396         ccb = cam_getccb(dev);
7397         if (ccb == NULL) {
7398                 warnx("%s: error allocating CCB", __func__);
7399                 retval = 1;
7400                 goto bailout;
7401         }
7402
7403         bzero(&(&ccb->ccb_h)[1],
7404               sizeof(union ccb) - sizeof(struct ccb_hdr));
7405
7406         /*
7407          * On the first try, we just probe for the size of the data, and
7408          * then allocate that much memory and try again.
7409          */
7410 retry:
7411         ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7412         ccb->ccb_h.flags = CAM_DIR_IN;
7413         ccb->cdai.flags = CDAI_FLAG_NONE;
7414         ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7415         ccb->cdai.bufsiz = item->device_id_len;
7416         if (item->device_id_len != 0)
7417                 ccb->cdai.buf = (uint8_t *)item->device_id;
7418
7419         if (cam_send_ccb(dev, ccb) < 0) {
7420                 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7421                 retval = 1;
7422                 goto bailout;
7423         }
7424
7425         if (ccb->ccb_h.status != CAM_REQ_CMP) {
7426                 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7427                 retval = 1;
7428                 goto bailout;
7429         }
7430
7431         if (item->device_id_len == 0) {
7432                 /*
7433                  * This is our first time through.  Allocate the buffer,
7434                  * and then go back to get the data.
7435                  */
7436                 if (ccb->cdai.provsiz == 0) {
7437                         warnx("%s: invalid .provsiz field returned with "
7438                              "XPT_GDEV_ADVINFO CCB", __func__);
7439                         retval = 1;
7440                         goto bailout;
7441                 }
7442                 item->device_id_len = ccb->cdai.provsiz;
7443                 item->device_id = malloc(item->device_id_len);
7444                 if (item->device_id == NULL) {
7445                         warn("%s: unable to allocate %d bytes", __func__,
7446                              item->device_id_len);
7447                         retval = 1;
7448                         goto bailout;
7449                 }
7450                 ccb->ccb_h.status = CAM_REQ_INPROG;
7451                 goto retry;
7452         }
7453
7454 bailout:
7455         if (dev != NULL)
7456                 cam_close_device(dev);
7457
7458         if (ccb != NULL)
7459                 cam_freeccb(ccb);
7460
7461         return (retval);
7462 }
7463
7464 /*
7465  * XXX KDM merge this code with getdevtree()?
7466  */
7467 static int
7468 buildbusdevlist(struct cam_devlist *devlist)
7469 {
7470         union ccb ccb;
7471         int bufsize, fd = -1;
7472         struct dev_match_pattern *patterns;
7473         struct cam_devitem *item = NULL;
7474         int skip_device = 0;
7475         int retval = 0;
7476
7477         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7478                 warn("couldn't open %s", XPT_DEVICE);
7479                 return(1);
7480         }
7481
7482         bzero(&ccb, sizeof(union ccb));
7483
7484         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7485         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7486         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7487
7488         ccb.ccb_h.func_code = XPT_DEV_MATCH;
7489         bufsize = sizeof(struct dev_match_result) * 100;
7490         ccb.cdm.match_buf_len = bufsize;
7491         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7492         if (ccb.cdm.matches == NULL) {
7493                 warnx("can't malloc memory for matches");
7494                 close(fd);
7495                 return(1);
7496         }
7497         ccb.cdm.num_matches = 0;
7498         ccb.cdm.num_patterns = 2;
7499         ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7500                 ccb.cdm.num_patterns;
7501
7502         patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7503         if (patterns == NULL) {
7504                 warnx("can't malloc memory for patterns");
7505                 retval = 1;
7506                 goto bailout;
7507         }
7508
7509         ccb.cdm.patterns = patterns;
7510         bzero(patterns, ccb.cdm.pattern_buf_len);
7511
7512         patterns[0].type = DEV_MATCH_DEVICE;
7513         patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7514         patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7515         patterns[1].type = DEV_MATCH_PERIPH;
7516         patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7517         patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7518
7519         /*
7520          * We do the ioctl multiple times if necessary, in case there are
7521          * more than 100 nodes in the EDT.
7522          */
7523         do {
7524                 unsigned int i;
7525
7526                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7527                         warn("error sending CAMIOCOMMAND ioctl");
7528                         retval = 1;
7529                         goto bailout;
7530                 }
7531
7532                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7533                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7534                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7535                         warnx("got CAM error %#x, CDM error %d\n",
7536                               ccb.ccb_h.status, ccb.cdm.status);
7537                         retval = 1;
7538                         goto bailout;
7539                 }
7540
7541                 for (i = 0; i < ccb.cdm.num_matches; i++) {
7542                         switch (ccb.cdm.matches[i].type) {
7543                         case DEV_MATCH_DEVICE: {
7544                                 struct device_match_result *dev_result;
7545
7546                                 dev_result = 
7547                                      &ccb.cdm.matches[i].result.device_result;
7548
7549                                 if (dev_result->flags &
7550                                     DEV_RESULT_UNCONFIGURED) {
7551                                         skip_device = 1;
7552                                         break;
7553                                 } else
7554                                         skip_device = 0;
7555
7556                                 item = malloc(sizeof(*item));
7557                                 if (item == NULL) {
7558                                         warn("%s: unable to allocate %zd bytes",
7559                                              __func__, sizeof(*item));
7560                                         retval = 1;
7561                                         goto bailout;
7562                                 }
7563                                 bzero(item, sizeof(*item));
7564                                 bcopy(dev_result, &item->dev_match,
7565                                       sizeof(*dev_result));
7566                                 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7567                                                    links);
7568
7569                                 if (getdevid(item) != 0) {
7570                                         retval = 1;
7571                                         goto bailout;
7572                                 }
7573                                 break;
7574                         }
7575                         case DEV_MATCH_PERIPH: {
7576                                 struct periph_match_result *periph_result;
7577
7578                                 periph_result =
7579                                       &ccb.cdm.matches[i].result.periph_result;
7580
7581                                 if (skip_device != 0)
7582                                         break;
7583                                 item->num_periphs++;
7584                                 item->periph_matches = realloc(
7585                                         item->periph_matches,
7586                                         item->num_periphs *
7587                                         sizeof(struct periph_match_result));
7588                                 if (item->periph_matches == NULL) {
7589                                         warn("%s: error allocating periph "
7590                                              "list", __func__);
7591                                         retval = 1;
7592                                         goto bailout;
7593                                 }
7594                                 bcopy(periph_result, &item->periph_matches[
7595                                       item->num_periphs - 1],
7596                                       sizeof(*periph_result));
7597                                 break;
7598                         }
7599                         default:
7600                                 fprintf(stderr, "%s: unexpected match "
7601                                         "type %d\n", __func__,
7602                                         ccb.cdm.matches[i].type);
7603                                 retval = 1;
7604                                 goto bailout;
7605                                 break; /*NOTREACHED*/
7606                         }
7607                 }
7608         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7609                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7610 bailout:
7611
7612         if (fd != -1)
7613                 close(fd);
7614
7615         free(patterns);
7616
7617         free(ccb.cdm.matches);
7618
7619         if (retval != 0)
7620                 freebusdevlist(devlist);
7621
7622         return (retval);
7623 }
7624
7625 static void
7626 freebusdevlist(struct cam_devlist *devlist)
7627 {
7628         struct cam_devitem *item, *item2;
7629
7630         STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7631                 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7632                               links);
7633                 free(item->device_id);
7634                 free(item->periph_matches);
7635                 free(item);
7636         }
7637 }
7638
7639 static struct cam_devitem *
7640 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7641 {
7642         struct cam_devitem *item;
7643
7644         STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7645                 struct scsi_vpd_id_descriptor *idd;
7646
7647                 /*
7648                  * XXX KDM look for LUN IDs as well?
7649                  */
7650                 idd = scsi_get_devid(item->device_id,
7651                                            item->device_id_len,
7652                                            scsi_devid_is_sas_target);
7653                 if (idd == NULL)
7654                         continue;
7655
7656                 if (scsi_8btou64(idd->identifier) == sasaddr)
7657                         return (item);
7658         }
7659
7660         return (NULL);
7661 }
7662
7663 static int
7664 smpphylist(struct cam_device *device, int argc, char **argv,
7665            char *combinedopt, int retry_count, int timeout)
7666 {
7667         struct smp_report_general_request *rgrequest = NULL;
7668         struct smp_report_general_response *rgresponse = NULL;
7669         struct smp_discover_request *disrequest = NULL;
7670         struct smp_discover_response *disresponse = NULL;
7671         struct cam_devlist devlist;
7672         union ccb *ccb;
7673         int long_response = 0;
7674         int num_phys = 0;
7675         int quiet = 0;
7676         int retval;
7677         int i, c;
7678
7679         /*
7680          * Note that at the moment we don't support sending SMP CCBs to
7681          * devices that aren't probed by CAM.
7682          */
7683         ccb = cam_getccb(device);
7684         if (ccb == NULL) {
7685                 warnx("%s: error allocating CCB", __func__);
7686                 return (1);
7687         }
7688
7689         bzero(&(&ccb->ccb_h)[1],
7690               sizeof(union ccb) - sizeof(struct ccb_hdr));
7691         STAILQ_INIT(&devlist.dev_queue);
7692
7693         rgrequest = malloc(sizeof(*rgrequest));
7694         if (rgrequest == NULL) {
7695                 warn("%s: unable to allocate %zd bytes", __func__,
7696                      sizeof(*rgrequest));
7697                 retval = 1;
7698                 goto bailout;
7699         }
7700
7701         rgresponse = malloc(sizeof(*rgresponse));
7702         if (rgresponse == NULL) {
7703                 warn("%s: unable to allocate %zd bytes", __func__,
7704                      sizeof(*rgresponse));
7705                 retval = 1;
7706                 goto bailout;
7707         }
7708
7709         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7710                 switch (c) {
7711                 case 'l':
7712                         long_response = 1;
7713                         break;
7714                 case 'q':
7715                         quiet = 1;
7716                         break;
7717                 default:
7718                         break;
7719                 }
7720         }
7721
7722         smp_report_general(&ccb->smpio,
7723                            retry_count,
7724                            /*cbfcnp*/ NULL,
7725                            rgrequest,
7726                            /*request_len*/ sizeof(*rgrequest),
7727                            (uint8_t *)rgresponse,
7728                            /*response_len*/ sizeof(*rgresponse),
7729                            /*long_response*/ long_response,
7730                            timeout);
7731
7732         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7733
7734         if (((retval = cam_send_ccb(device, ccb)) < 0)
7735          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7736                 const char warnstr[] = "error sending command";
7737
7738                 if (retval < 0)
7739                         warn(warnstr);
7740                 else
7741                         warnx(warnstr);
7742
7743                 if (arglist & CAM_ARG_VERBOSE) {
7744                         cam_error_print(device, ccb, CAM_ESF_ALL,
7745                                         CAM_EPF_ALL, stderr);
7746                 }
7747                 retval = 1;
7748                 goto bailout;
7749         }
7750
7751         num_phys = rgresponse->num_phys;
7752
7753         if (num_phys == 0) {
7754                 if (quiet == 0)
7755                         fprintf(stdout, "%s: No Phys reported\n", __func__);
7756                 retval = 1;
7757                 goto bailout;
7758         }
7759
7760         devlist.path_id = device->path_id;
7761
7762         retval = buildbusdevlist(&devlist);
7763         if (retval != 0)
7764                 goto bailout;
7765
7766         if (quiet == 0) {
7767                 fprintf(stdout, "%d PHYs:\n", num_phys);
7768                 fprintf(stdout, "PHY  Attached SAS Address\n");
7769         }
7770
7771         disrequest = malloc(sizeof(*disrequest));
7772         if (disrequest == NULL) {
7773                 warn("%s: unable to allocate %zd bytes", __func__,
7774                      sizeof(*disrequest));
7775                 retval = 1;
7776                 goto bailout;
7777         }
7778
7779         disresponse = malloc(sizeof(*disresponse));
7780         if (disresponse == NULL) {
7781                 warn("%s: unable to allocate %zd bytes", __func__,
7782                      sizeof(*disresponse));
7783                 retval = 1;
7784                 goto bailout;
7785         }
7786
7787         for (i = 0; i < num_phys; i++) {
7788                 struct cam_devitem *item;
7789                 struct device_match_result *dev_match;
7790                 char vendor[16], product[48], revision[16];
7791                 char tmpstr[256];
7792                 int j;
7793
7794                 bzero(&(&ccb->ccb_h)[1],
7795                       sizeof(union ccb) - sizeof(struct ccb_hdr));
7796
7797                 ccb->ccb_h.status = CAM_REQ_INPROG;
7798                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7799
7800                 smp_discover(&ccb->smpio,
7801                              retry_count,
7802                              /*cbfcnp*/ NULL,
7803                              disrequest,
7804                              sizeof(*disrequest),
7805                              (uint8_t *)disresponse,
7806                              sizeof(*disresponse),
7807                              long_response,
7808                              /*ignore_zone_group*/ 0,
7809                              /*phy*/ i,
7810                              timeout);
7811
7812                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7813                  || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7814                   && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7815                         const char warnstr[] = "error sending command";
7816
7817                         if (retval < 0)
7818                                 warn(warnstr);
7819                         else
7820                                 warnx(warnstr);
7821
7822                         if (arglist & CAM_ARG_VERBOSE) {
7823                                 cam_error_print(device, ccb, CAM_ESF_ALL,
7824                                                 CAM_EPF_ALL, stderr);
7825                         }
7826                         retval = 1;
7827                         goto bailout;
7828                 }
7829
7830                 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7831                         if (quiet == 0)
7832                                 fprintf(stdout, "%3d  <vacant>\n", i);
7833                         continue;
7834                 }
7835
7836                 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7837                         item = NULL;
7838                 } else {
7839                         item = findsasdevice(&devlist,
7840                             scsi_8btou64(disresponse->attached_sas_address));
7841                 }
7842
7843                 if ((quiet == 0)
7844                  || (item != NULL)) {
7845                         fprintf(stdout, "%3d  0x%016jx", i,
7846                                 (uintmax_t)scsi_8btou64(
7847                                 disresponse->attached_sas_address));
7848                         if (item == NULL) {
7849                                 fprintf(stdout, "\n");
7850                                 continue;
7851                         }
7852                 } else if (quiet != 0)
7853                         continue;
7854
7855                 dev_match = &item->dev_match;
7856
7857                 if (dev_match->protocol == PROTO_SCSI) {
7858                         cam_strvis(vendor, dev_match->inq_data.vendor,
7859                                    sizeof(dev_match->inq_data.vendor),
7860                                    sizeof(vendor));
7861                         cam_strvis(product, dev_match->inq_data.product,
7862                                    sizeof(dev_match->inq_data.product),
7863                                    sizeof(product));
7864                         cam_strvis(revision, dev_match->inq_data.revision,
7865                                    sizeof(dev_match->inq_data.revision),
7866                                    sizeof(revision));
7867                         sprintf(tmpstr, "<%s %s %s>", vendor, product,
7868                                 revision);
7869                 } else if ((dev_match->protocol == PROTO_ATA)
7870                         || (dev_match->protocol == PROTO_SATAPM)) {
7871                         cam_strvis(product, dev_match->ident_data.model,
7872                                    sizeof(dev_match->ident_data.model),
7873                                    sizeof(product));
7874                         cam_strvis(revision, dev_match->ident_data.revision,
7875                                    sizeof(dev_match->ident_data.revision),
7876                                    sizeof(revision));
7877                         sprintf(tmpstr, "<%s %s>", product, revision);
7878                 } else {
7879                         sprintf(tmpstr, "<>");
7880                 }
7881                 fprintf(stdout, "   %-33s ", tmpstr);
7882
7883                 /*
7884                  * If we have 0 periphs, that's a bug...
7885                  */
7886                 if (item->num_periphs == 0) {
7887                         fprintf(stdout, "\n");
7888                         continue;
7889                 }
7890
7891                 fprintf(stdout, "(");
7892                 for (j = 0; j < item->num_periphs; j++) {
7893                         if (j > 0)
7894                                 fprintf(stdout, ",");
7895
7896                         fprintf(stdout, "%s%d",
7897                                 item->periph_matches[j].periph_name,
7898                                 item->periph_matches[j].unit_number);
7899                                 
7900                 }
7901                 fprintf(stdout, ")\n");
7902         }
7903 bailout:
7904         if (ccb != NULL)
7905                 cam_freeccb(ccb);
7906
7907         free(rgrequest);
7908
7909         free(rgresponse);
7910
7911         free(disrequest);
7912
7913         free(disresponse);
7914
7915         freebusdevlist(&devlist);
7916
7917         return (retval);
7918 }
7919
7920 static int
7921 atapm(struct cam_device *device, int argc, char **argv,
7922                  char *combinedopt, int retry_count, int timeout)
7923 {
7924         union ccb *ccb;
7925         int retval = 0;
7926         int t = -1;
7927         int c;
7928         u_char cmd, sc;
7929
7930         ccb = cam_getccb(device);
7931
7932         if (ccb == NULL) {
7933                 warnx("%s: error allocating ccb", __func__);
7934                 return (1);
7935         }
7936
7937         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7938                 switch (c) {
7939                 case 't':
7940                         t = atoi(optarg);
7941                         break;
7942                 default:
7943                         break;
7944                 }
7945         }
7946         if (strcmp(argv[1], "idle") == 0) {
7947                 if (t == -1)
7948                         cmd = ATA_IDLE_IMMEDIATE;
7949                 else
7950                         cmd = ATA_IDLE_CMD;
7951         } else if (strcmp(argv[1], "standby") == 0) {
7952                 if (t == -1)
7953                         cmd = ATA_STANDBY_IMMEDIATE;
7954                 else
7955                         cmd = ATA_STANDBY_CMD;
7956         } else {
7957                 cmd = ATA_SLEEP;
7958                 t = -1;
7959         }
7960
7961         if (t < 0)
7962                 sc = 0;
7963         else if (t <= (240 * 5))
7964                 sc = (t + 4) / 5;
7965         else if (t <= (252 * 5))
7966                 /* special encoding for 21 minutes */
7967                 sc = 252;
7968         else if (t <= (11 * 30 * 60))
7969                 sc = (t - 1) / (30 * 60) + 241;
7970         else
7971                 sc = 253;
7972
7973         retval = ata_do_28bit_cmd(device,
7974             ccb,
7975             /*retries*/retry_count,
7976             /*flags*/CAM_DIR_NONE,
7977             /*protocol*/AP_PROTO_NON_DATA,
7978             /*tag_action*/MSG_SIMPLE_Q_TAG,
7979             /*command*/cmd,
7980             /*features*/0,
7981             /*lba*/0,
7982             /*sector_count*/sc,
7983             /*data_ptr*/NULL,
7984             /*dxfer_len*/0,
7985             /*timeout*/timeout ? timeout : 30 * 1000,
7986             /*quiet*/1);
7987
7988         cam_freeccb(ccb);
7989         return (retval);
7990 }
7991
7992 static int
7993 ataaxm(struct cam_device *device, int argc, char **argv,
7994                  char *combinedopt, int retry_count, int timeout)
7995 {
7996         union ccb *ccb;
7997         int retval = 0;
7998         int l = -1;
7999         int c;
8000         u_char cmd, sc;
8001
8002         ccb = cam_getccb(device);
8003
8004         if (ccb == NULL) {
8005                 warnx("%s: error allocating ccb", __func__);
8006                 return (1);
8007         }
8008
8009         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8010                 switch (c) {
8011                 case 'l':
8012                         l = atoi(optarg);
8013                         break;
8014                 default:
8015                         break;
8016                 }
8017         }
8018         sc = 0;
8019         if (strcmp(argv[1], "apm") == 0) {
8020                 if (l == -1)
8021                         cmd = 0x85;
8022                 else {
8023                         cmd = 0x05;
8024                         sc = l;
8025                 }
8026         } else /* aam */ {
8027                 if (l == -1)
8028                         cmd = 0xC2;
8029                 else {
8030                         cmd = 0x42;
8031                         sc = l;
8032                 }
8033         }
8034
8035         retval = ata_do_28bit_cmd(device,
8036             ccb,
8037             /*retries*/retry_count,
8038             /*flags*/CAM_DIR_NONE,
8039             /*protocol*/AP_PROTO_NON_DATA,
8040             /*tag_action*/MSG_SIMPLE_Q_TAG,
8041             /*command*/ATA_SETFEATURES,
8042             /*features*/cmd,
8043             /*lba*/0,
8044             /*sector_count*/sc,
8045             /*data_ptr*/NULL,
8046             /*dxfer_len*/0,
8047             /*timeout*/timeout ? timeout : 30 * 1000,
8048             /*quiet*/1);
8049
8050         cam_freeccb(ccb);
8051         return (retval);
8052 }
8053
8054 #endif /* MINIMALISTIC */
8055
8056 void
8057 usage(int printlong)
8058 {
8059
8060         fprintf(printlong ? stdout : stderr,
8061 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
8062 "        camcontrol devlist    [-b] [-v]\n"
8063 #ifndef MINIMALISTIC
8064 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8065 "        camcontrol tur        [dev_id][generic args]\n"
8066 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
8067 "        camcontrol identify   [dev_id][generic args] [-v]\n"
8068 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8069 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8070 "                              [-q] [-s]\n"
8071 "        camcontrol start      [dev_id][generic args]\n"
8072 "        camcontrol stop       [dev_id][generic args]\n"
8073 "        camcontrol load       [dev_id][generic args]\n"
8074 "        camcontrol eject      [dev_id][generic args]\n"
8075 #endif /* MINIMALISTIC */
8076 "        camcontrol rescan     <all | bus[:target:lun]>\n"
8077 "        camcontrol reset      <all | bus[:target:lun]>\n"
8078 #ifndef MINIMALISTIC
8079 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
8080 "                              [-q][-s][-S offset][-X]\n"
8081 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
8082 "                              [-P pagectl][-e | -b][-d]\n"
8083 "        camcontrol cmd        [dev_id][generic args]\n"
8084 "                              <-a cmd [args] | -c cmd [args]>\n"
8085 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8086 "        camcontrol smpcmd     [dev_id][generic args]\n"
8087 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
8088 "        camcontrol smprg      [dev_id][generic args][-l]\n"
8089 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
8090 "                              [-o operation][-d name][-m rate][-M rate]\n"
8091 "                              [-T pp_timeout][-a enable|disable]\n"
8092 "                              [-A enable|disable][-s enable|disable]\n"
8093 "                              [-S enable|disable]\n"
8094 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8095 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8096 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
8097 "                              <all|bus[:target[:lun]]|off>\n"
8098 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
8099 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
8100 "                              [-D <enable|disable>][-M mode][-O offset]\n"
8101 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
8102 "                              [-U][-W bus_width]\n"
8103 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
8104 "        camcontrol sanitize   [dev_id][generic args]\n"
8105 "                              [-a overwrite|block|crypto|exitfailure]\n"
8106 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8107 "                              [-y]\n"
8108 "        camcontrol idle       [dev_id][generic args][-t time]\n"
8109 "        camcontrol standby    [dev_id][generic args][-t time]\n"
8110 "        camcontrol sleep      [dev_id][generic args]\n"
8111 "        camcontrol apm        [dev_id][generic args][-l level]\n"
8112 "        camcontrol aam        [dev_id][generic args][-l level]\n"
8113 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
8114 "        camcontrol security   [dev_id][generic args]\n"
8115 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8116 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8117 "                              [-U <user|master>] [-y]\n"
8118 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8119 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
8120 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
8121 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8122 "                              [-s scope][-S][-T type][-U]\n"
8123 "        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
8124 "                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
8125 "                              [-p part][-s start][-T type][-V vol]\n"
8126 #endif /* MINIMALISTIC */
8127 "        camcontrol help\n");
8128         if (!printlong)
8129                 return;
8130 #ifndef MINIMALISTIC
8131         fprintf(stdout,
8132 "Specify one of the following options:\n"
8133 "devlist     list all CAM devices\n"
8134 "periphlist  list all CAM peripheral drivers attached to a device\n"
8135 "tur         send a test unit ready to the named device\n"
8136 "inquiry     send a SCSI inquiry command to the named device\n"
8137 "identify    send a ATA identify command to the named device\n"
8138 "reportluns  send a SCSI report luns command to the device\n"
8139 "readcap     send a SCSI read capacity command to the device\n"
8140 "start       send a Start Unit command to the device\n"
8141 "stop        send a Stop Unit command to the device\n"
8142 "load        send a Start Unit command to the device with the load bit set\n"
8143 "eject       send a Stop Unit command to the device with the eject bit set\n"
8144 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
8145 "reset       reset all busses, the given bus, or bus:target:lun\n"
8146 "defects     read the defect list of the specified device\n"
8147 "modepage    display or edit (-e) the given mode page\n"
8148 "cmd         send the given SCSI command, may need -i or -o as well\n"
8149 "smpcmd      send the given SMP command, requires -o and -i\n"
8150 "smprg       send the SMP Report General command\n"
8151 "smppc       send the SMP PHY Control command, requires -p\n"
8152 "smpphylist  display phys attached to a SAS expander\n"
8153 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
8154 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
8155 "tags        report or set the number of transaction slots for a device\n"
8156 "negotiate   report or set device negotiation parameters\n"
8157 "format      send the SCSI FORMAT UNIT command to the named device\n"
8158 "sanitize    send the SCSI SANITIZE command to the named device\n"
8159 "idle        send the ATA IDLE command to the named device\n"
8160 "standby     send the ATA STANDBY command to the named device\n"
8161 "sleep       send the ATA SLEEP command to the named device\n"
8162 "fwdownload  program firmware of the named device with the given image\n"
8163 "security    report or send ATA security commands to the named device\n"
8164 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8165 "attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
8166 "help        this message\n"
8167 "Device Identifiers:\n"
8168 "bus:target        specify the bus and target, lun defaults to 0\n"
8169 "bus:target:lun    specify the bus, target and lun\n"
8170 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
8171 "Generic arguments:\n"
8172 "-v                be verbose, print out sense information\n"
8173 "-t timeout        command timeout in seconds, overrides default timeout\n"
8174 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
8175 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
8176 "-E                have the kernel attempt to perform SCSI error recovery\n"
8177 "-C count          specify the SCSI command retry count (needs -E to work)\n"
8178 "modepage arguments:\n"
8179 "-l                list all available mode pages\n"
8180 "-m page           specify the mode page to view or edit\n"
8181 "-e                edit the specified mode page\n"
8182 "-b                force view to binary mode\n"
8183 "-d                disable block descriptors for mode sense\n"
8184 "-P pgctl          page control field 0-3\n"
8185 "defects arguments:\n"
8186 "-f format         specify defect list format (block, bfi or phys)\n"
8187 "-G                get the grown defect list\n"
8188 "-P                get the permanent defect list\n"
8189 "inquiry arguments:\n"
8190 "-D                get the standard inquiry data\n"
8191 "-S                get the serial number\n"
8192 "-R                get the transfer rate, etc.\n"
8193 "reportluns arguments:\n"
8194 "-c                only report a count of available LUNs\n"
8195 "-l                only print out luns, and not a count\n"
8196 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
8197 "readcap arguments\n"
8198 "-b                only report the blocksize\n"
8199 "-h                human readable device size, base 2\n"
8200 "-H                human readable device size, base 10\n"
8201 "-N                print the number of blocks instead of last block\n"
8202 "-q                quiet, print numbers only\n"
8203 "-s                only report the last block/device size\n"
8204 "cmd arguments:\n"
8205 "-c cdb [args]     specify the SCSI CDB\n"
8206 "-i len fmt        specify input data and input data format\n"
8207 "-o len fmt [args] specify output data and output data fmt\n"
8208 "smpcmd arguments:\n"
8209 "-r len fmt [args] specify the SMP command to be sent\n"
8210 "-R len fmt [args] specify SMP response format\n"
8211 "smprg arguments:\n"
8212 "-l                specify the long response format\n"
8213 "smppc arguments:\n"
8214 "-p phy            specify the PHY to operate on\n"
8215 "-l                specify the long request/response format\n"
8216 "-o operation      specify the phy control operation\n"
8217 "-d name           set the attached device name\n"
8218 "-m rate           set the minimum physical link rate\n"
8219 "-M rate           set the maximum physical link rate\n"
8220 "-T pp_timeout     set the partial pathway timeout value\n"
8221 "-a enable|disable enable or disable SATA slumber\n"
8222 "-A enable|disable enable or disable SATA partial phy power\n"
8223 "-s enable|disable enable or disable SAS slumber\n"
8224 "-S enable|disable enable or disable SAS partial phy power\n"
8225 "smpphylist arguments:\n"
8226 "-l                specify the long response format\n"
8227 "-q                only print phys with attached devices\n"
8228 "smpmaninfo arguments:\n"
8229 "-l                specify the long response format\n"
8230 "debug arguments:\n"
8231 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
8232 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
8233 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
8234 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
8235 "tags arguments:\n"
8236 "-N tags           specify the number of tags to use for this device\n"
8237 "-q                be quiet, don't report the number of tags\n"
8238 "-v                report a number of tag-related parameters\n"
8239 "negotiate arguments:\n"
8240 "-a                send a test unit ready after negotiation\n"
8241 "-c                report/set current negotiation settings\n"
8242 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
8243 "-M mode           set ATA mode\n"
8244 "-O offset         set command delay offset\n"
8245 "-q                be quiet, don't report anything\n"
8246 "-R syncrate       synchronization rate in MHz\n"
8247 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
8248 "-U                report/set user negotiation settings\n"
8249 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
8250 "-v                also print a Path Inquiry CCB for the controller\n"
8251 "format arguments:\n"
8252 "-q                be quiet, don't print status messages\n"
8253 "-r                run in report only mode\n"
8254 "-w                don't send immediate format command\n"
8255 "-y                don't ask any questions\n"
8256 "sanitize arguments:\n"
8257 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
8258 "-c passes         overwrite passes to perform (1 to 31)\n"
8259 "-I                invert overwrite pattern after each pass\n"
8260 "-P pattern        path to overwrite pattern file\n"
8261 "-q                be quiet, don't print status messages\n"
8262 "-r                run in report only mode\n"
8263 "-U                run operation in unrestricted completion exit mode\n"
8264 "-w                don't send immediate sanitize command\n"
8265 "-y                don't ask any questions\n"
8266 "idle/standby arguments:\n"
8267 "-t <arg>          number of seconds before respective state.\n"
8268 "fwdownload arguments:\n"
8269 "-f fw_image       path to firmware image file\n"
8270 "-y                don't ask any questions\n"
8271 "-s                run in simulation mode\n"
8272 "-v                print info for every firmware segment sent to device\n"
8273 "security arguments:\n"
8274 "-d pwd            disable security using the given password for the selected\n"
8275 "                  user\n"
8276 "-e pwd            erase the device using the given pwd for the selected user\n"
8277 "-f                freeze the security configuration of the specified device\n"
8278 "-h pwd            enhanced erase the device using the given pwd for the\n"
8279 "                  selected user\n"
8280 "-k pwd            unlock the device using the given pwd for the selected\n"
8281 "                  user\n"
8282 "-l <high|maximum> specifies which security level to set: high or maximum\n"
8283 "-q                be quiet, do not print any status messages\n"
8284 "-s pwd            password the device (enable security) using the given\n"
8285 "                  pwd for the selected user\n"
8286 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
8287 "-U <user|master>  specifies which user to set: user or master\n"
8288 "-y                don't ask any questions\n"
8289 "hpa arguments:\n"
8290 "-f                freeze the HPA configuration of the device\n"
8291 "-l                lock the HPA configuration of the device\n"
8292 "-P                make the HPA max sectors persist\n"
8293 "-p pwd            Set the HPA configuration password required for unlock\n"
8294 "                  calls\n"
8295 "-q                be quiet, do not print any status messages\n"
8296 "-s sectors        configures the maximum user accessible sectors of the\n"
8297 "                  device\n"
8298 "-U pwd            unlock the HPA configuration of the device\n"
8299 "-y                don't ask any questions\n"
8300 "persist arguments:\n"
8301 "-i action         specify read_keys, read_reservation, report_cap, or\n"
8302 "                  read_full_status\n"
8303 "-o action         specify register, register_ignore, reserve, release,\n"
8304 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
8305 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
8306 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8307 "-k key            specify the Reservation Key\n"
8308 "-K sa_key         specify the Service Action Reservation Key\n"
8309 "-p                set the Activate Persist Through Power Loss bit\n"
8310 "-R rtp            specify the Relative Target Port\n"
8311 "-s scope          specify the scope: lun, extent, element or a number\n"
8312 "-S                specify Transport ID for register, requires -I\n"
8313 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8314 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8315 "-U                unregister the current initiator for register_move\n"
8316 "attrib arguments:\n"
8317 "-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
8318 "                  supp_attr\n"
8319 "-w attr           specify an attribute to write, one -w argument per attr\n"
8320 "-a attr_num       only display this attribute number\n"
8321 "-c                get cached attributes\n"
8322 "-e elem_addr      request attributes for the given element in a changer\n"
8323 "-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
8324 "                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
8325 "                  field_none, field_desc, field_num, field_size, field_rw\n"
8326 "-p partition      request attributes for the given partition\n"
8327 "-s start_attr     request attributes starting at the given number\n"
8328 "-T elem_type      specify the element type (used with -e)\n"
8329 "-V logical_vol    specify the logical volume ID\n"
8330 );
8331 #endif /* MINIMALISTIC */
8332 }
8333
8334 int
8335 main(int argc, char **argv)
8336 {
8337         int c;
8338         char *device = NULL;
8339         int unit = 0;
8340         struct cam_device *cam_dev = NULL;
8341         int timeout = 0, retry_count = 1;
8342         camcontrol_optret optreturn;
8343         char *tstr;
8344         const char *mainopt = "C:En:t:u:v";
8345         const char *subopt = NULL;
8346         char combinedopt[256];
8347         int error = 0, optstart = 2;
8348         int devopen = 1;
8349 #ifndef MINIMALISTIC
8350         path_id_t bus;
8351         target_id_t target;
8352         lun_id_t lun;
8353 #endif /* MINIMALISTIC */
8354
8355         cmdlist = CAM_CMD_NONE;
8356         arglist = CAM_ARG_NONE;
8357
8358         if (argc < 2) {
8359                 usage(0);
8360                 exit(1);
8361         }
8362
8363         /*
8364          * Get the base option.
8365          */
8366         optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8367
8368         if (optreturn == CC_OR_AMBIGUOUS) {
8369                 warnx("ambiguous option %s", argv[1]);
8370                 usage(0);
8371                 exit(1);
8372         } else if (optreturn == CC_OR_NOT_FOUND) {
8373                 warnx("option %s not found", argv[1]);
8374                 usage(0);
8375                 exit(1);
8376         }
8377
8378         /*
8379          * Ahh, getopt(3) is a pain.
8380          *
8381          * This is a gross hack.  There really aren't many other good
8382          * options (excuse the pun) for parsing options in a situation like
8383          * this.  getopt is kinda braindead, so you end up having to run
8384          * through the options twice, and give each invocation of getopt
8385          * the option string for the other invocation.
8386          *
8387          * You would think that you could just have two groups of options.
8388          * The first group would get parsed by the first invocation of
8389          * getopt, and the second group would get parsed by the second
8390          * invocation of getopt.  It doesn't quite work out that way.  When
8391          * the first invocation of getopt finishes, it leaves optind pointing
8392          * to the argument _after_ the first argument in the second group.
8393          * So when the second invocation of getopt comes around, it doesn't
8394          * recognize the first argument it gets and then bails out.
8395          *
8396          * A nice alternative would be to have a flag for getopt that says
8397          * "just keep parsing arguments even when you encounter an unknown
8398          * argument", but there isn't one.  So there's no real clean way to
8399          * easily parse two sets of arguments without having one invocation
8400          * of getopt know about the other.
8401          *
8402          * Without this hack, the first invocation of getopt would work as
8403          * long as the generic arguments are first, but the second invocation
8404          * (in the subfunction) would fail in one of two ways.  In the case
8405          * where you don't set optreset, it would fail because optind may be
8406          * pointing to the argument after the one it should be pointing at.
8407          * In the case where you do set optreset, and reset optind, it would
8408          * fail because getopt would run into the first set of options, which
8409          * it doesn't understand.
8410          *
8411          * All of this would "sort of" work if you could somehow figure out
8412          * whether optind had been incremented one option too far.  The
8413          * mechanics of that, however, are more daunting than just giving
8414          * both invocations all of the expect options for either invocation.
8415          *
8416          * Needless to say, I wouldn't mind if someone invented a better
8417          * (non-GPL!) command line parsing interface than getopt.  I
8418          * wouldn't mind if someone added more knobs to getopt to make it
8419          * work better.  Who knows, I may talk myself into doing it someday,
8420          * if the standards weenies let me.  As it is, it just leads to
8421          * hackery like this and causes people to avoid it in some cases.
8422          *
8423          * KDM, September 8th, 1998
8424          */
8425         if (subopt != NULL)
8426                 sprintf(combinedopt, "%s%s", mainopt, subopt);
8427         else
8428                 sprintf(combinedopt, "%s", mainopt);
8429
8430         /*
8431          * For these options we do not parse optional device arguments and
8432          * we do not open a passthrough device.
8433          */
8434         if ((cmdlist == CAM_CMD_RESCAN)
8435          || (cmdlist == CAM_CMD_RESET)
8436          || (cmdlist == CAM_CMD_DEVTREE)
8437          || (cmdlist == CAM_CMD_USAGE)
8438          || (cmdlist == CAM_CMD_DEBUG))
8439                 devopen = 0;
8440
8441 #ifndef MINIMALISTIC
8442         if ((devopen == 1)
8443          && (argc > 2 && argv[2][0] != '-')) {
8444                 char name[30];
8445                 int rv;
8446
8447                 if (isdigit(argv[2][0])) {
8448                         /* device specified as bus:target[:lun] */
8449                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
8450                         if (rv < 2)
8451                                 errx(1, "numeric device specification must "
8452                                      "be either bus:target, or "
8453                                      "bus:target:lun");
8454                         /* default to 0 if lun was not specified */
8455                         if ((arglist & CAM_ARG_LUN) == 0) {
8456                                 lun = 0;
8457                                 arglist |= CAM_ARG_LUN;
8458                         }
8459                         optstart++;
8460                 } else {
8461                         if (cam_get_device(argv[2], name, sizeof name, &unit)
8462                             == -1)
8463                                 errx(1, "%s", cam_errbuf);
8464                         device = strdup(name);
8465                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
8466                         optstart++;
8467                 }
8468         }
8469 #endif /* MINIMALISTIC */
8470         /*
8471          * Start getopt processing at argv[2/3], since we've already
8472          * accepted argv[1..2] as the command name, and as a possible
8473          * device name.
8474          */
8475         optind = optstart;
8476
8477         /*
8478          * Now we run through the argument list looking for generic
8479          * options, and ignoring options that possibly belong to
8480          * subfunctions.
8481          */
8482         while ((c = getopt(argc, argv, combinedopt))!= -1){
8483                 switch(c) {
8484                         case 'C':
8485                                 retry_count = strtol(optarg, NULL, 0);
8486                                 if (retry_count < 0)
8487                                         errx(1, "retry count %d is < 0",
8488                                              retry_count);
8489                                 arglist |= CAM_ARG_RETRIES;
8490                                 break;
8491                         case 'E':
8492                                 arglist |= CAM_ARG_ERR_RECOVER;
8493                                 break;
8494                         case 'n':
8495                                 arglist |= CAM_ARG_DEVICE;
8496                                 tstr = optarg;
8497                                 while (isspace(*tstr) && (*tstr != '\0'))
8498                                         tstr++;
8499                                 device = (char *)strdup(tstr);
8500                                 break;
8501                         case 't':
8502                                 timeout = strtol(optarg, NULL, 0);
8503                                 if (timeout < 0)
8504                                         errx(1, "invalid timeout %d", timeout);
8505                                 /* Convert the timeout from seconds to ms */
8506                                 timeout *= 1000;
8507                                 arglist |= CAM_ARG_TIMEOUT;
8508                                 break;
8509                         case 'u':
8510                                 arglist |= CAM_ARG_UNIT;
8511                                 unit = strtol(optarg, NULL, 0);
8512                                 break;
8513                         case 'v':
8514                                 arglist |= CAM_ARG_VERBOSE;
8515                                 break;
8516                         default:
8517                                 break;
8518                 }
8519         }
8520
8521 #ifndef MINIMALISTIC
8522         /*
8523          * For most commands we'll want to open the passthrough device
8524          * associated with the specified device.  In the case of the rescan
8525          * commands, we don't use a passthrough device at all, just the
8526          * transport layer device.
8527          */
8528         if (devopen == 1) {
8529                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
8530                  && (((arglist & CAM_ARG_DEVICE) == 0)
8531                   || ((arglist & CAM_ARG_UNIT) == 0))) {
8532                         errx(1, "subcommand \"%s\" requires a valid device "
8533                              "identifier", argv[1]);
8534                 }
8535
8536                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
8537                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
8538                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
8539                      == NULL)
8540                         errx(1,"%s", cam_errbuf);
8541         }
8542 #endif /* MINIMALISTIC */
8543
8544         /*
8545          * Reset optind to 2, and reset getopt, so these routines can parse
8546          * the arguments again.
8547          */
8548         optind = optstart;
8549         optreset = 1;
8550
8551         switch(cmdlist) {
8552 #ifndef MINIMALISTIC
8553                 case CAM_CMD_DEVLIST:
8554                         error = getdevlist(cam_dev);
8555                         break;
8556                 case CAM_CMD_HPA:
8557                         error = atahpa(cam_dev, retry_count, timeout,
8558                                        argc, argv, combinedopt);
8559                         break;
8560 #endif /* MINIMALISTIC */
8561                 case CAM_CMD_DEVTREE:
8562                         error = getdevtree(argc, argv, combinedopt);
8563                         break;
8564 #ifndef MINIMALISTIC
8565                 case CAM_CMD_TUR:
8566                         error = testunitready(cam_dev, retry_count, timeout, 0);
8567                         break;
8568                 case CAM_CMD_INQUIRY:
8569                         error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
8570                                               retry_count, timeout);
8571                         break;
8572                 case CAM_CMD_IDENTIFY:
8573                         error = ataidentify(cam_dev, retry_count, timeout);
8574                         break;
8575                 case CAM_CMD_STARTSTOP:
8576                         error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
8577                                           arglist & CAM_ARG_EJECT, retry_count,
8578                                           timeout);
8579                         break;
8580 #endif /* MINIMALISTIC */
8581                 case CAM_CMD_RESCAN:
8582                         error = dorescan_or_reset(argc, argv, 1);
8583                         break;
8584                 case CAM_CMD_RESET:
8585                         error = dorescan_or_reset(argc, argv, 0);
8586                         break;
8587 #ifndef MINIMALISTIC
8588                 case CAM_CMD_READ_DEFECTS:
8589                         error = readdefects(cam_dev, argc, argv, combinedopt,
8590                                             retry_count, timeout);
8591                         break;
8592                 case CAM_CMD_MODE_PAGE:
8593                         modepage(cam_dev, argc, argv, combinedopt,
8594                                  retry_count, timeout);
8595                         break;
8596                 case CAM_CMD_SCSI_CMD:
8597                         error = scsicmd(cam_dev, argc, argv, combinedopt,
8598                                         retry_count, timeout);
8599                         break;
8600                 case CAM_CMD_SMP_CMD:
8601                         error = smpcmd(cam_dev, argc, argv, combinedopt,
8602                                        retry_count, timeout);
8603                         break;
8604                 case CAM_CMD_SMP_RG:
8605                         error = smpreportgeneral(cam_dev, argc, argv,
8606                                                  combinedopt, retry_count,
8607                                                  timeout);
8608                         break;
8609                 case CAM_CMD_SMP_PC:
8610                         error = smpphycontrol(cam_dev, argc, argv, combinedopt, 
8611                                               retry_count, timeout);
8612                         break;
8613                 case CAM_CMD_SMP_PHYLIST:
8614                         error = smpphylist(cam_dev, argc, argv, combinedopt,
8615                                            retry_count, timeout);
8616                         break;
8617                 case CAM_CMD_SMP_MANINFO:
8618                         error = smpmaninfo(cam_dev, argc, argv, combinedopt,
8619                                            retry_count, timeout);
8620                         break;
8621                 case CAM_CMD_DEBUG:
8622                         error = camdebug(argc, argv, combinedopt);
8623                         break;
8624                 case CAM_CMD_TAG:
8625                         error = tagcontrol(cam_dev, argc, argv, combinedopt);
8626                         break;
8627                 case CAM_CMD_RATE:
8628                         error = ratecontrol(cam_dev, retry_count, timeout,
8629                                             argc, argv, combinedopt);
8630                         break;
8631                 case CAM_CMD_FORMAT:
8632                         error = scsiformat(cam_dev, argc, argv,
8633                                            combinedopt, retry_count, timeout);
8634                         break;
8635                 case CAM_CMD_REPORTLUNS:
8636                         error = scsireportluns(cam_dev, argc, argv,
8637                                                combinedopt, retry_count,
8638                                                timeout);
8639                         break;
8640                 case CAM_CMD_READCAP:
8641                         error = scsireadcapacity(cam_dev, argc, argv,
8642                                                  combinedopt, retry_count,
8643                                                  timeout);
8644                         break;
8645                 case CAM_CMD_IDLE:
8646                 case CAM_CMD_STANDBY:
8647                 case CAM_CMD_SLEEP:
8648                         error = atapm(cam_dev, argc, argv,
8649                                       combinedopt, retry_count, timeout);
8650                         break;
8651                 case CAM_CMD_APM:
8652                 case CAM_CMD_AAM:
8653                         error = ataaxm(cam_dev, argc, argv,
8654                                       combinedopt, retry_count, timeout);
8655                         break;
8656                 case CAM_CMD_SECURITY:
8657                         error = atasecurity(cam_dev, retry_count, timeout,
8658                                             argc, argv, combinedopt);
8659                         break;
8660                 case CAM_CMD_DOWNLOAD_FW:
8661                         error = fwdownload(cam_dev, argc, argv, combinedopt,
8662                             arglist & CAM_ARG_VERBOSE, retry_count, timeout,
8663                             get_disk_type(cam_dev));
8664                         break;
8665                 case CAM_CMD_SANITIZE:
8666                         error = scsisanitize(cam_dev, argc, argv,
8667                                              combinedopt, retry_count, timeout);
8668                         break;
8669                 case CAM_CMD_PERSIST:
8670                         error = scsipersist(cam_dev, argc, argv, combinedopt,
8671                             retry_count, timeout, arglist & CAM_ARG_VERBOSE,
8672                             arglist & CAM_ARG_ERR_RECOVER);
8673                         break;
8674                 case CAM_CMD_ATTRIB:
8675                         error = scsiattrib(cam_dev, argc, argv, combinedopt,
8676                             retry_count, timeout, arglist & CAM_ARG_VERBOSE,
8677                             arglist & CAM_ARG_ERR_RECOVER);
8678                         break;
8679 #endif /* MINIMALISTIC */
8680                 case CAM_CMD_USAGE:
8681                         usage(1);
8682                         break;
8683                 default:
8684                         usage(0);
8685                         error = 1;
8686                         break;
8687         }
8688
8689         if (cam_dev != NULL)
8690                 cam_close_device(cam_dev);
8691
8692         exit(error);
8693 }