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