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