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