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