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