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