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