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