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