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