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