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