]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - sbin/camcontrol/camcontrol.c
Document SA-14:25, SA-14:26
[FreeBSD/releng/10.1.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:GP";
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 static int
3373 readdefects(struct cam_device *device, int argc, char **argv,
3374             char *combinedopt, int retry_count, int timeout)
3375 {
3376         union ccb *ccb = NULL;
3377         struct scsi_read_defect_data_10 *rdd_cdb;
3378         u_int8_t *defect_list = NULL;
3379         u_int32_t max_dlist_length = SRDD10_MAX_LENGTH, dlist_length = 0;
3380         u_int32_t returned_length = 0;
3381         u_int32_t num_returned = 0;
3382         u_int8_t returned_format;
3383         unsigned int i;
3384         int c, error = 0;
3385         int lists_specified;
3386         int get_length = 1;
3387
3388         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3389                 switch(c){
3390                 case 'f':
3391                 {
3392                         char *tstr;
3393                         tstr = optarg;
3394                         while (isspace(*tstr) && (*tstr != '\0'))
3395                                 tstr++;
3396                         if (strcmp(tstr, "block") == 0)
3397                                 arglist |= CAM_ARG_FORMAT_BLOCK;
3398                         else if (strcmp(tstr, "bfi") == 0)
3399                                 arglist |= CAM_ARG_FORMAT_BFI;
3400                         else if (strcmp(tstr, "phys") == 0)
3401                                 arglist |= CAM_ARG_FORMAT_PHYS;
3402                         else {
3403                                 error = 1;
3404                                 warnx("invalid defect format %s", tstr);
3405                                 goto defect_bailout;
3406                         }
3407                         break;
3408                 }
3409                 case 'G':
3410                         arglist |= CAM_ARG_GLIST;
3411                         break;
3412                 case 'P':
3413                         arglist |= CAM_ARG_PLIST;
3414                         break;
3415                 default:
3416                         break;
3417                 }
3418         }
3419
3420         ccb = cam_getccb(device);
3421
3422         /*
3423          * Eventually we should probably support the 12 byte READ DEFECT
3424          * DATA command.  It supports a longer parameter list, which may be
3425          * necessary on newer drives with lots of defects.  According to
3426          * the SBC-3 spec, drives are supposed to return an illegal request
3427          * if they have more defect data than will fit in 64K.
3428          */
3429         defect_list = malloc(max_dlist_length);
3430         if (defect_list == NULL) {
3431                 warnx("can't malloc memory for defect list");
3432                 error = 1;
3433                 goto defect_bailout;
3434         }
3435
3436         /*
3437          * We start off asking for just the header to determine how much
3438          * defect data is available.  Some Hitachi drives return an error
3439          * if you ask for more data than the drive has.  Once we know the
3440          * length, we retry the command with the returned length.
3441          */
3442         dlist_length = sizeof(struct scsi_read_defect_data_hdr_10);
3443
3444         rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
3445
3446 retry:
3447
3448         lists_specified = 0;
3449
3450         /*
3451          * cam_getccb() zeros the CCB header only.  So we need to zero the
3452          * payload portion of the ccb.
3453          */
3454         bzero(&(&ccb->ccb_h)[1],
3455               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3456
3457         cam_fill_csio(&ccb->csio,
3458                       /*retries*/ retry_count,
3459                       /*cbfcnp*/ NULL,
3460                       /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
3461                                               CAM_PASS_ERR_RECOVER : 0),
3462                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
3463                       /*data_ptr*/ defect_list,
3464                       /*dxfer_len*/ dlist_length,
3465                       /*sense_len*/ SSD_FULL_SIZE,
3466                       /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
3467                       /*timeout*/ timeout ? timeout : 5000);
3468
3469         rdd_cdb->opcode = READ_DEFECT_DATA_10;
3470         if (arglist & CAM_ARG_FORMAT_BLOCK)
3471                 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
3472         else if (arglist & CAM_ARG_FORMAT_BFI)
3473                 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
3474         else if (arglist & CAM_ARG_FORMAT_PHYS)
3475                 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
3476         else {
3477                 error = 1;
3478                 warnx("no defect list format specified");
3479                 goto defect_bailout;
3480         }
3481         if (arglist & CAM_ARG_PLIST) {
3482                 rdd_cdb->format |= SRDD10_PLIST;
3483                 lists_specified++;
3484         }
3485
3486         if (arglist & CAM_ARG_GLIST) {
3487                 rdd_cdb->format |= SRDD10_GLIST;
3488                 lists_specified++;
3489         }
3490
3491         scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
3492
3493         /* Disable freezing the device queue */
3494         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3495
3496         if (cam_send_ccb(device, ccb) < 0) {
3497                 perror("error reading defect list");
3498
3499                 if (arglist & CAM_ARG_VERBOSE) {
3500                         cam_error_print(device, ccb, CAM_ESF_ALL,
3501                                         CAM_EPF_ALL, stderr);
3502                 }
3503
3504                 error = 1;
3505                 goto defect_bailout;
3506         }
3507
3508         returned_length = scsi_2btoul(((struct
3509                 scsi_read_defect_data_hdr_10 *)defect_list)->length);
3510
3511         if (get_length != 0) {
3512                 get_length = 0;
3513
3514                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3515                      CAM_SCSI_STATUS_ERROR) {
3516                         struct scsi_sense_data *sense;
3517                         int error_code, sense_key, asc, ascq;
3518
3519                         sense = &ccb->csio.sense_data;
3520                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
3521                             ccb->csio.sense_resid, &error_code, &sense_key,
3522                             &asc, &ascq, /*show_errors*/ 1);
3523
3524                         /*
3525                          * If the drive is reporting that it just doesn't
3526                          * support the defect list format, go ahead and use
3527                          * the length it reported.  Otherwise, the length
3528                          * may not be valid, so use the maximum.
3529                          */
3530                         if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3531                          && (asc == 0x1c) && (ascq == 0x00)
3532                          && (returned_length > 0)) {
3533                                 dlist_length = returned_length +
3534                                     sizeof(struct scsi_read_defect_data_hdr_10);
3535                                 dlist_length = min(dlist_length,
3536                                                    SRDD10_MAX_LENGTH);
3537                         } else
3538                                 dlist_length = max_dlist_length;
3539                 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3540                             CAM_REQ_CMP){
3541                         error = 1;
3542                         warnx("Error reading defect header");
3543                         if (arglist & CAM_ARG_VERBOSE)
3544                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3545                                                 CAM_EPF_ALL, stderr);
3546                         goto defect_bailout;
3547                 } else {
3548                         dlist_length = returned_length +
3549                             sizeof(struct scsi_read_defect_data_hdr_10);
3550                         dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3551                 }
3552
3553                 goto retry;
3554         }
3555
3556         returned_format = ((struct scsi_read_defect_data_hdr_10 *)
3557                         defect_list)->format;
3558
3559         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3560          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3561          && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3562                 struct scsi_sense_data *sense;
3563                 int error_code, sense_key, asc, ascq;
3564
3565                 sense = &ccb->csio.sense_data;
3566                 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3567                     ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3568                     &ascq, /*show_errors*/ 1);
3569
3570                 /*
3571                  * According to the SCSI spec, if the disk doesn't support
3572                  * the requested format, it will generally return a sense
3573                  * key of RECOVERED ERROR, and an additional sense code
3574                  * of "DEFECT LIST NOT FOUND".  So, we check for that, and
3575                  * also check to make sure that the returned length is
3576                  * greater than 0, and then print out whatever format the
3577                  * disk gave us.
3578                  */
3579                 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3580                  && (asc == 0x1c) && (ascq == 0x00)
3581                  && (returned_length > 0)) {
3582                         warnx("requested defect format not available");
3583                         switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
3584                         case SRDD10_BLOCK_FORMAT:
3585                                 warnx("Device returned block format");
3586                                 break;
3587                         case SRDD10_BYTES_FROM_INDEX_FORMAT:
3588                                 warnx("Device returned bytes from index"
3589                                       " format");
3590                                 break;
3591                         case SRDD10_PHYSICAL_SECTOR_FORMAT:
3592                                 warnx("Device returned physical sector format");
3593                                 break;
3594                         default:
3595                                 error = 1;
3596                                 warnx("Device returned unknown defect"
3597                                      " data format %#x", returned_format);
3598                                 goto defect_bailout;
3599                                 break; /* NOTREACHED */
3600                         }
3601                 } else {
3602                         error = 1;
3603                         warnx("Error returned from read defect data command");
3604                         if (arglist & CAM_ARG_VERBOSE)
3605                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3606                                                 CAM_EPF_ALL, stderr);
3607                         goto defect_bailout;
3608                 }
3609         } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3610                 error = 1;
3611                 warnx("Error returned from read defect data command");
3612                 if (arglist & CAM_ARG_VERBOSE)
3613                         cam_error_print(device, ccb, CAM_ESF_ALL,
3614                                         CAM_EPF_ALL, stderr);
3615                 goto defect_bailout;
3616         }
3617
3618         /*
3619          * XXX KDM  I should probably clean up the printout format for the
3620          * disk defects.
3621          */
3622         switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
3623                 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
3624                 {
3625                         struct scsi_defect_desc_phys_sector *dlist;
3626
3627                         dlist = (struct scsi_defect_desc_phys_sector *)
3628                                 (defect_list +
3629                                 sizeof(struct scsi_read_defect_data_hdr_10));
3630
3631                         num_returned = returned_length /
3632                                 sizeof(struct scsi_defect_desc_phys_sector);
3633
3634                         fprintf(stderr, "Got %d defect", num_returned);
3635
3636                         if ((lists_specified == 0) || (num_returned == 0)) {
3637                                 fprintf(stderr, "s.\n");
3638                                 break;
3639                         } else if (num_returned == 1)
3640                                 fprintf(stderr, ":\n");
3641                         else
3642                                 fprintf(stderr, "s:\n");
3643
3644                         for (i = 0; i < num_returned; i++) {
3645                                 fprintf(stdout, "%d:%d:%d\n",
3646                                         scsi_3btoul(dlist[i].cylinder),
3647                                         dlist[i].head,
3648                                         scsi_4btoul(dlist[i].sector));
3649                         }
3650                         break;
3651                 }
3652                 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
3653                 {
3654                         struct scsi_defect_desc_bytes_from_index *dlist;
3655
3656                         dlist = (struct scsi_defect_desc_bytes_from_index *)
3657                                 (defect_list +
3658                                 sizeof(struct scsi_read_defect_data_hdr_10));
3659
3660                         num_returned = returned_length /
3661                               sizeof(struct scsi_defect_desc_bytes_from_index);
3662
3663                         fprintf(stderr, "Got %d defect", num_returned);
3664
3665                         if ((lists_specified == 0) || (num_returned == 0)) {
3666                                 fprintf(stderr, "s.\n");
3667                                 break;
3668                         } else if (num_returned == 1)
3669                                 fprintf(stderr, ":\n");
3670                         else
3671                                 fprintf(stderr, "s:\n");
3672
3673                         for (i = 0; i < num_returned; i++) {
3674                                 fprintf(stdout, "%d:%d:%d\n",
3675                                         scsi_3btoul(dlist[i].cylinder),
3676                                         dlist[i].head,
3677                                         scsi_4btoul(dlist[i].bytes_from_index));
3678                         }
3679                         break;
3680                 }
3681                 case SRDDH10_BLOCK_FORMAT:
3682                 {
3683                         struct scsi_defect_desc_block *dlist;
3684
3685                         dlist = (struct scsi_defect_desc_block *)(defect_list +
3686                                 sizeof(struct scsi_read_defect_data_hdr_10));
3687
3688                         num_returned = returned_length /
3689                               sizeof(struct scsi_defect_desc_block);
3690
3691                         fprintf(stderr, "Got %d defect", num_returned);
3692
3693                         if ((lists_specified == 0) || (num_returned == 0)) {
3694                                 fprintf(stderr, "s.\n");
3695                                 break;
3696                         } else if (num_returned == 1)
3697                                 fprintf(stderr, ":\n");
3698                         else
3699                                 fprintf(stderr, "s:\n");
3700
3701                         for (i = 0; i < num_returned; i++)
3702                                 fprintf(stdout, "%u\n",
3703                                         scsi_4btoul(dlist[i].address));
3704                         break;
3705                 }
3706                 default:
3707                         fprintf(stderr, "Unknown defect format %d\n",
3708                                 returned_format & SRDDH10_DLIST_FORMAT_MASK);
3709                         error = 1;
3710                         break;
3711         }
3712 defect_bailout:
3713
3714         if (defect_list != NULL)
3715                 free(defect_list);
3716
3717         if (ccb != NULL)
3718                 cam_freeccb(ccb);
3719
3720         return(error);
3721 }
3722 #endif /* MINIMALISTIC */
3723
3724 #if 0
3725 void
3726 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3727 {
3728         union ccb *ccb;
3729
3730         ccb = cam_getccb(device);
3731
3732         cam_freeccb(ccb);
3733 }
3734 #endif
3735
3736 #ifndef MINIMALISTIC
3737 void
3738 mode_sense(struct cam_device *device, int mode_page, int page_control,
3739            int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3740 {
3741         union ccb *ccb;
3742         int retval;
3743
3744         ccb = cam_getccb(device);
3745
3746         if (ccb == NULL)
3747                 errx(1, "mode_sense: couldn't allocate CCB");
3748
3749         bzero(&(&ccb->ccb_h)[1],
3750               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3751
3752         scsi_mode_sense(&ccb->csio,
3753                         /* retries */ retry_count,
3754                         /* cbfcnp */ NULL,
3755                         /* tag_action */ MSG_SIMPLE_Q_TAG,
3756                         /* dbd */ dbd,
3757                         /* page_code */ page_control << 6,
3758                         /* page */ mode_page,
3759                         /* param_buf */ data,
3760                         /* param_len */ datalen,
3761                         /* sense_len */ SSD_FULL_SIZE,
3762                         /* timeout */ timeout ? timeout : 5000);
3763
3764         if (arglist & CAM_ARG_ERR_RECOVER)
3765                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3766
3767         /* Disable freezing the device queue */
3768         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3769
3770         if (((retval = cam_send_ccb(device, ccb)) < 0)
3771          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3772                 if (arglist & CAM_ARG_VERBOSE) {
3773                         cam_error_print(device, ccb, CAM_ESF_ALL,
3774                                         CAM_EPF_ALL, stderr);
3775                 }
3776                 cam_freeccb(ccb);
3777                 cam_close_device(device);
3778                 if (retval < 0)
3779                         err(1, "error sending mode sense command");
3780                 else
3781                         errx(1, "error sending mode sense command");
3782         }
3783
3784         cam_freeccb(ccb);
3785 }
3786
3787 void
3788 mode_select(struct cam_device *device, int save_pages, int retry_count,
3789            int timeout, u_int8_t *data, int datalen)
3790 {
3791         union ccb *ccb;
3792         int retval;
3793
3794         ccb = cam_getccb(device);
3795
3796         if (ccb == NULL)
3797                 errx(1, "mode_select: couldn't allocate CCB");
3798
3799         bzero(&(&ccb->ccb_h)[1],
3800               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3801
3802         scsi_mode_select(&ccb->csio,
3803                          /* retries */ retry_count,
3804                          /* cbfcnp */ NULL,
3805                          /* tag_action */ MSG_SIMPLE_Q_TAG,
3806                          /* scsi_page_fmt */ 1,
3807                          /* save_pages */ save_pages,
3808                          /* param_buf */ data,
3809                          /* param_len */ datalen,
3810                          /* sense_len */ SSD_FULL_SIZE,
3811                          /* timeout */ timeout ? timeout : 5000);
3812
3813         if (arglist & CAM_ARG_ERR_RECOVER)
3814                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3815
3816         /* Disable freezing the device queue */
3817         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3818
3819         if (((retval = cam_send_ccb(device, ccb)) < 0)
3820          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3821                 if (arglist & CAM_ARG_VERBOSE) {
3822                         cam_error_print(device, ccb, CAM_ESF_ALL,
3823                                         CAM_EPF_ALL, stderr);
3824                 }
3825                 cam_freeccb(ccb);
3826                 cam_close_device(device);
3827
3828                 if (retval < 0)
3829                         err(1, "error sending mode select command");
3830                 else
3831                         errx(1, "error sending mode select command");
3832
3833         }
3834
3835         cam_freeccb(ccb);
3836 }
3837
3838 void
3839 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
3840          int retry_count, int timeout)
3841 {
3842         int c, mode_page = -1, page_control = 0;
3843         int binary = 0, list = 0;
3844
3845         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3846                 switch(c) {
3847                 case 'b':
3848                         binary = 1;
3849                         break;
3850                 case 'd':
3851                         arglist |= CAM_ARG_DBD;
3852                         break;
3853                 case 'e':
3854                         arglist |= CAM_ARG_MODE_EDIT;
3855                         break;
3856                 case 'l':
3857                         list = 1;
3858                         break;
3859                 case 'm':
3860                         mode_page = strtol(optarg, NULL, 0);
3861                         if (mode_page < 0)
3862                                 errx(1, "invalid mode page %d", mode_page);
3863                         break;
3864                 case 'P':
3865                         page_control = strtol(optarg, NULL, 0);
3866                         if ((page_control < 0) || (page_control > 3))
3867                                 errx(1, "invalid page control field %d",
3868                                      page_control);
3869                         arglist |= CAM_ARG_PAGE_CNTL;
3870                         break;
3871                 default:
3872                         break;
3873                 }
3874         }
3875
3876         if (mode_page == -1 && list == 0)
3877                 errx(1, "you must specify a mode page!");
3878
3879         if (list) {
3880                 mode_list(device, page_control, arglist & CAM_ARG_DBD,
3881                     retry_count, timeout);
3882         } else {
3883                 mode_edit(device, mode_page, page_control,
3884                     arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
3885                     retry_count, timeout);
3886         }
3887 }
3888
3889 static int
3890 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
3891         int retry_count, int timeout)
3892 {
3893         union ccb *ccb;
3894         u_int32_t flags = CAM_DIR_NONE;
3895         u_int8_t *data_ptr = NULL;
3896         u_int8_t cdb[20];
3897         u_int8_t atacmd[12];
3898         struct get_hook hook;
3899         int c, data_bytes = 0;
3900         int cdb_len = 0;
3901         int atacmd_len = 0;
3902         int dmacmd = 0;
3903         int fpdmacmd = 0;
3904         int need_res = 0;
3905         char *datastr = NULL, *tstr, *resstr = NULL;
3906         int error = 0;
3907         int fd_data = 0, fd_res = 0;
3908         int retval;
3909
3910         ccb = cam_getccb(device);
3911
3912         if (ccb == NULL) {
3913                 warnx("scsicmd: error allocating ccb");
3914                 return(1);
3915         }
3916
3917         bzero(&(&ccb->ccb_h)[1],
3918               sizeof(union ccb) - sizeof(struct ccb_hdr));
3919
3920         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3921                 switch(c) {
3922                 case 'a':
3923                         tstr = optarg;
3924                         while (isspace(*tstr) && (*tstr != '\0'))
3925                                 tstr++;
3926                         hook.argc = argc - optind;
3927                         hook.argv = argv + optind;
3928                         hook.got = 0;
3929                         atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
3930                                                     iget, &hook);
3931                         /*
3932                          * Increment optind by the number of arguments the
3933                          * encoding routine processed.  After each call to
3934                          * getopt(3), optind points to the argument that
3935                          * getopt should process _next_.  In this case,
3936                          * that means it points to the first command string
3937                          * argument, if there is one.  Once we increment
3938                          * this, it should point to either the next command
3939                          * line argument, or it should be past the end of
3940                          * the list.
3941                          */
3942                         optind += hook.got;
3943                         break;
3944                 case 'c':
3945                         tstr = optarg;
3946                         while (isspace(*tstr) && (*tstr != '\0'))
3947                                 tstr++;
3948                         hook.argc = argc - optind;
3949                         hook.argv = argv + optind;
3950                         hook.got = 0;
3951                         cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
3952                                                     iget, &hook);
3953                         /*
3954                          * Increment optind by the number of arguments the
3955                          * encoding routine processed.  After each call to
3956                          * getopt(3), optind points to the argument that
3957                          * getopt should process _next_.  In this case,
3958                          * that means it points to the first command string
3959                          * argument, if there is one.  Once we increment
3960                          * this, it should point to either the next command
3961                          * line argument, or it should be past the end of
3962                          * the list.
3963                          */
3964                         optind += hook.got;
3965                         break;
3966                 case 'd':
3967                         dmacmd = 1;
3968                         break;
3969                 case 'f':
3970                         fpdmacmd = 1;
3971                         break;
3972                 case 'i':
3973                         if (arglist & CAM_ARG_CMD_OUT) {
3974                                 warnx("command must either be "
3975                                       "read or write, not both");
3976                                 error = 1;
3977                                 goto scsicmd_bailout;
3978                         }
3979                         arglist |= CAM_ARG_CMD_IN;
3980                         flags = CAM_DIR_IN;
3981                         data_bytes = strtol(optarg, NULL, 0);
3982                         if (data_bytes <= 0) {
3983                                 warnx("invalid number of input bytes %d",
3984                                       data_bytes);
3985                                 error = 1;
3986                                 goto scsicmd_bailout;
3987                         }
3988                         hook.argc = argc - optind;
3989                         hook.argv = argv + optind;
3990                         hook.got = 0;
3991                         optind++;
3992                         datastr = cget(&hook, NULL);
3993                         /*
3994                          * If the user supplied "-" instead of a format, he
3995                          * wants the data to be written to stdout.
3996                          */
3997                         if ((datastr != NULL)
3998                          && (datastr[0] == '-'))
3999                                 fd_data = 1;
4000
4001                         data_ptr = (u_int8_t *)malloc(data_bytes);
4002                         if (data_ptr == NULL) {
4003                                 warnx("can't malloc memory for data_ptr");
4004                                 error = 1;
4005                                 goto scsicmd_bailout;
4006                         }
4007                         break;
4008                 case 'o':
4009                         if (arglist & CAM_ARG_CMD_IN) {
4010                                 warnx("command must either be "
4011                                       "read or write, not both");
4012                                 error = 1;
4013                                 goto scsicmd_bailout;
4014                         }
4015                         arglist |= CAM_ARG_CMD_OUT;
4016                         flags = CAM_DIR_OUT;
4017                         data_bytes = strtol(optarg, NULL, 0);
4018                         if (data_bytes <= 0) {
4019                                 warnx("invalid number of output bytes %d",
4020                                       data_bytes);
4021                                 error = 1;
4022                                 goto scsicmd_bailout;
4023                         }
4024                         hook.argc = argc - optind;
4025                         hook.argv = argv + optind;
4026                         hook.got = 0;
4027                         datastr = cget(&hook, NULL);
4028                         data_ptr = (u_int8_t *)malloc(data_bytes);
4029                         if (data_ptr == NULL) {
4030                                 warnx("can't malloc memory for data_ptr");
4031                                 error = 1;
4032                                 goto scsicmd_bailout;
4033                         }
4034                         bzero(data_ptr, data_bytes);
4035                         /*
4036                          * If the user supplied "-" instead of a format, he
4037                          * wants the data to be read from stdin.
4038                          */
4039                         if ((datastr != NULL)
4040                          && (datastr[0] == '-'))
4041                                 fd_data = 1;
4042                         else
4043                                 buff_encode_visit(data_ptr, data_bytes, datastr,
4044                                                   iget, &hook);
4045                         optind += hook.got;
4046                         break;
4047                 case 'r':
4048                         need_res = 1;
4049                         hook.argc = argc - optind;
4050                         hook.argv = argv + optind;
4051                         hook.got = 0;
4052                         resstr = cget(&hook, NULL);
4053                         if ((resstr != NULL) && (resstr[0] == '-'))
4054                                 fd_res = 1;
4055                         optind += hook.got;
4056                         break;
4057                 default:
4058                         break;
4059                 }
4060         }
4061
4062         /*
4063          * If fd_data is set, and we're writing to the device, we need to
4064          * read the data the user wants written from stdin.
4065          */
4066         if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4067                 ssize_t amt_read;
4068                 int amt_to_read = data_bytes;
4069                 u_int8_t *buf_ptr = data_ptr;
4070
4071                 for (amt_read = 0; amt_to_read > 0;
4072                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4073                         if (amt_read == -1) {
4074                                 warn("error reading data from stdin");
4075                                 error = 1;
4076                                 goto scsicmd_bailout;
4077                         }
4078                         amt_to_read -= amt_read;
4079                         buf_ptr += amt_read;
4080                 }
4081         }
4082
4083         if (arglist & CAM_ARG_ERR_RECOVER)
4084                 flags |= CAM_PASS_ERR_RECOVER;
4085
4086         /* Disable freezing the device queue */
4087         flags |= CAM_DEV_QFRZDIS;
4088
4089         if (cdb_len) {
4090                 /*
4091                  * This is taken from the SCSI-3 draft spec.
4092                  * (T10/1157D revision 0.3)
4093                  * The top 3 bits of an opcode are the group code.
4094                  * The next 5 bits are the command code.
4095                  * Group 0:  six byte commands
4096                  * Group 1:  ten byte commands
4097                  * Group 2:  ten byte commands
4098                  * Group 3:  reserved
4099                  * Group 4:  sixteen byte commands
4100                  * Group 5:  twelve byte commands
4101                  * Group 6:  vendor specific
4102                  * Group 7:  vendor specific
4103                  */
4104                 switch((cdb[0] >> 5) & 0x7) {
4105                         case 0:
4106                                 cdb_len = 6;
4107                                 break;
4108                         case 1:
4109                         case 2:
4110                                 cdb_len = 10;
4111                                 break;
4112                         case 3:
4113                         case 6:
4114                         case 7:
4115                                 /* computed by buff_encode_visit */
4116                                 break;
4117                         case 4:
4118                                 cdb_len = 16;
4119                                 break;
4120                         case 5:
4121                                 cdb_len = 12;
4122                                 break;
4123                 }
4124
4125                 /*
4126                  * We should probably use csio_build_visit or something like that
4127                  * here, but it's easier to encode arguments as you go.  The
4128                  * alternative would be skipping the CDB argument and then encoding
4129                  * it here, since we've got the data buffer argument by now.
4130                  */
4131                 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4132
4133                 cam_fill_csio(&ccb->csio,
4134                       /*retries*/ retry_count,
4135                       /*cbfcnp*/ NULL,
4136                       /*flags*/ flags,
4137                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
4138                       /*data_ptr*/ data_ptr,
4139                       /*dxfer_len*/ data_bytes,
4140                       /*sense_len*/ SSD_FULL_SIZE,
4141                       /*cdb_len*/ cdb_len,
4142                       /*timeout*/ timeout ? timeout : 5000);
4143         } else {
4144                 atacmd_len = 12;
4145                 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4146                 if (need_res)
4147                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4148                 if (dmacmd)
4149                         ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4150                 if (fpdmacmd)
4151                         ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4152
4153                 cam_fill_ataio(&ccb->ataio,
4154                       /*retries*/ retry_count,
4155                       /*cbfcnp*/ NULL,
4156                       /*flags*/ flags,
4157                       /*tag_action*/ 0,
4158                       /*data_ptr*/ data_ptr,
4159                       /*dxfer_len*/ data_bytes,
4160                       /*timeout*/ timeout ? timeout : 5000);
4161         }
4162
4163         if (((retval = cam_send_ccb(device, ccb)) < 0)
4164          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4165                 const char warnstr[] = "error sending command";
4166
4167                 if (retval < 0)
4168                         warn(warnstr);
4169                 else
4170                         warnx(warnstr);
4171
4172                 if (arglist & CAM_ARG_VERBOSE) {
4173                         cam_error_print(device, ccb, CAM_ESF_ALL,
4174                                         CAM_EPF_ALL, stderr);
4175                 }
4176
4177                 error = 1;
4178                 goto scsicmd_bailout;
4179         }
4180
4181         if (atacmd_len && need_res) {
4182                 if (fd_res == 0) {
4183                         buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4184                                           arg_put, NULL);
4185                         fprintf(stdout, "\n");
4186                 } else {
4187                         fprintf(stdout,
4188                             "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4189                             ccb->ataio.res.status,
4190                             ccb->ataio.res.error,
4191                             ccb->ataio.res.lba_low,
4192                             ccb->ataio.res.lba_mid,
4193                             ccb->ataio.res.lba_high,
4194                             ccb->ataio.res.device,
4195                             ccb->ataio.res.lba_low_exp,
4196                             ccb->ataio.res.lba_mid_exp,
4197                             ccb->ataio.res.lba_high_exp,
4198                             ccb->ataio.res.sector_count,
4199                             ccb->ataio.res.sector_count_exp);
4200                         fflush(stdout);
4201                 }
4202         }
4203
4204         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4205          && (arglist & CAM_ARG_CMD_IN)
4206          && (data_bytes > 0)) {
4207                 if (fd_data == 0) {
4208                         buff_decode_visit(data_ptr, data_bytes, datastr,
4209                                           arg_put, NULL);
4210                         fprintf(stdout, "\n");
4211                 } else {
4212                         ssize_t amt_written;
4213                         int amt_to_write = data_bytes;
4214                         u_int8_t *buf_ptr = data_ptr;
4215
4216                         for (amt_written = 0; (amt_to_write > 0) &&
4217                              (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4218                                 amt_to_write -= amt_written;
4219                                 buf_ptr += amt_written;
4220                         }
4221                         if (amt_written == -1) {
4222                                 warn("error writing data to stdout");
4223                                 error = 1;
4224                                 goto scsicmd_bailout;
4225                         } else if ((amt_written == 0)
4226                                 && (amt_to_write > 0)) {
4227                                 warnx("only wrote %u bytes out of %u",
4228                                       data_bytes - amt_to_write, data_bytes);
4229                         }
4230                 }
4231         }
4232
4233 scsicmd_bailout:
4234
4235         if ((data_bytes > 0) && (data_ptr != NULL))
4236                 free(data_ptr);
4237
4238         cam_freeccb(ccb);
4239
4240         return(error);
4241 }
4242
4243 static int
4244 camdebug(int argc, char **argv, char *combinedopt)
4245 {
4246         int c, fd;
4247         path_id_t bus = CAM_BUS_WILDCARD;
4248         target_id_t target = CAM_TARGET_WILDCARD;
4249         lun_id_t lun = CAM_LUN_WILDCARD;
4250         char *tstr, *tmpstr = NULL;
4251         union ccb ccb;
4252         int error = 0;
4253
4254         bzero(&ccb, sizeof(union ccb));
4255
4256         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4257                 switch(c) {
4258                 case 'I':
4259                         arglist |= CAM_ARG_DEBUG_INFO;
4260                         ccb.cdbg.flags |= CAM_DEBUG_INFO;
4261                         break;
4262                 case 'P':
4263                         arglist |= CAM_ARG_DEBUG_PERIPH;
4264                         ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4265                         break;
4266                 case 'S':
4267                         arglist |= CAM_ARG_DEBUG_SUBTRACE;
4268                         ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4269                         break;
4270                 case 'T':
4271                         arglist |= CAM_ARG_DEBUG_TRACE;
4272                         ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4273                         break;
4274                 case 'X':
4275                         arglist |= CAM_ARG_DEBUG_XPT;
4276                         ccb.cdbg.flags |= CAM_DEBUG_XPT;
4277                         break;
4278                 case 'c':
4279                         arglist |= CAM_ARG_DEBUG_CDB;
4280                         ccb.cdbg.flags |= CAM_DEBUG_CDB;
4281                         break;
4282                 case 'p':
4283                         arglist |= CAM_ARG_DEBUG_PROBE;
4284                         ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4285                         break;
4286                 default:
4287                         break;
4288                 }
4289         }
4290
4291         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4292                 warnx("error opening transport layer device %s", XPT_DEVICE);
4293                 warn("%s", XPT_DEVICE);
4294                 return(1);
4295         }
4296         argc -= optind;
4297         argv += optind;
4298
4299         if (argc <= 0) {
4300                 warnx("you must specify \"off\", \"all\" or a bus,");
4301                 warnx("bus:target, or bus:target:lun");
4302                 close(fd);
4303                 return(1);
4304         }
4305
4306         tstr = *argv;
4307
4308         while (isspace(*tstr) && (*tstr != '\0'))
4309                 tstr++;
4310
4311         if (strncmp(tstr, "off", 3) == 0) {
4312                 ccb.cdbg.flags = CAM_DEBUG_NONE;
4313                 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4314                              CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4315                              CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4316         } else if (strncmp(tstr, "all", 3) != 0) {
4317                 tmpstr = (char *)strtok(tstr, ":");
4318                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4319                         bus = strtol(tmpstr, NULL, 0);
4320                         arglist |= CAM_ARG_BUS;
4321                         tmpstr = (char *)strtok(NULL, ":");
4322                         if ((tmpstr != NULL) && (*tmpstr != '\0')){
4323                                 target = strtol(tmpstr, NULL, 0);
4324                                 arglist |= CAM_ARG_TARGET;
4325                                 tmpstr = (char *)strtok(NULL, ":");
4326                                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4327                                         lun = strtol(tmpstr, NULL, 0);
4328                                         arglist |= CAM_ARG_LUN;
4329                                 }
4330                         }
4331                 } else {
4332                         error = 1;
4333                         warnx("you must specify \"all\", \"off\", or a bus,");
4334                         warnx("bus:target, or bus:target:lun to debug");
4335                 }
4336         }
4337
4338         if (error == 0) {
4339
4340                 ccb.ccb_h.func_code = XPT_DEBUG;
4341                 ccb.ccb_h.path_id = bus;
4342                 ccb.ccb_h.target_id = target;
4343                 ccb.ccb_h.target_lun = lun;
4344
4345                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4346                         warn("CAMIOCOMMAND ioctl failed");
4347                         error = 1;
4348                 }
4349
4350                 if (error == 0) {
4351                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4352                              CAM_FUNC_NOTAVAIL) {
4353                                 warnx("CAM debugging not available");
4354                                 warnx("you need to put options CAMDEBUG in"
4355                                       " your kernel config file!");
4356                                 error = 1;
4357                         } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4358                                     CAM_REQ_CMP) {
4359                                 warnx("XPT_DEBUG CCB failed with status %#x",
4360                                       ccb.ccb_h.status);
4361                                 error = 1;
4362                         } else {
4363                                 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4364                                         fprintf(stderr,
4365                                                 "Debugging turned off\n");
4366                                 } else {
4367                                         fprintf(stderr,
4368                                                 "Debugging enabled for "
4369                                                 "%d:%d:%jx\n",
4370                                                 bus, target, (uintmax_t)lun);
4371                                 }
4372                         }
4373                 }
4374                 close(fd);
4375         }
4376
4377         return(error);
4378 }
4379
4380 static int
4381 tagcontrol(struct cam_device *device, int argc, char **argv,
4382            char *combinedopt)
4383 {
4384         int c;
4385         union ccb *ccb;
4386         int numtags = -1;
4387         int retval = 0;
4388         int quiet = 0;
4389         char pathstr[1024];
4390
4391         ccb = cam_getccb(device);
4392
4393         if (ccb == NULL) {
4394                 warnx("tagcontrol: error allocating ccb");
4395                 return(1);
4396         }
4397
4398         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4399                 switch(c) {
4400                 case 'N':
4401                         numtags = strtol(optarg, NULL, 0);
4402                         if (numtags < 0) {
4403                                 warnx("tag count %d is < 0", numtags);
4404                                 retval = 1;
4405                                 goto tagcontrol_bailout;
4406                         }
4407                         break;
4408                 case 'q':
4409                         quiet++;
4410                         break;
4411                 default:
4412                         break;
4413                 }
4414         }
4415
4416         cam_path_string(device, pathstr, sizeof(pathstr));
4417
4418         if (numtags >= 0) {
4419                 bzero(&(&ccb->ccb_h)[1],
4420                       sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4421                 ccb->ccb_h.func_code = XPT_REL_SIMQ;
4422                 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4423                 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4424                 ccb->crs.openings = numtags;
4425
4426
4427                 if (cam_send_ccb(device, ccb) < 0) {
4428                         perror("error sending XPT_REL_SIMQ CCB");
4429                         retval = 1;
4430                         goto tagcontrol_bailout;
4431                 }
4432
4433                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4434                         warnx("XPT_REL_SIMQ CCB failed");
4435                         cam_error_print(device, ccb, CAM_ESF_ALL,
4436                                         CAM_EPF_ALL, stderr);
4437                         retval = 1;
4438                         goto tagcontrol_bailout;
4439                 }
4440
4441
4442                 if (quiet == 0)
4443                         fprintf(stdout, "%stagged openings now %d\n",
4444                                 pathstr, ccb->crs.openings);
4445         }
4446
4447         bzero(&(&ccb->ccb_h)[1],
4448               sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4449
4450         ccb->ccb_h.func_code = XPT_GDEV_STATS;
4451
4452         if (cam_send_ccb(device, ccb) < 0) {
4453                 perror("error sending XPT_GDEV_STATS CCB");
4454                 retval = 1;
4455                 goto tagcontrol_bailout;
4456         }
4457
4458         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4459                 warnx("XPT_GDEV_STATS CCB failed");
4460                 cam_error_print(device, ccb, CAM_ESF_ALL,
4461                                 CAM_EPF_ALL, stderr);
4462                 retval = 1;
4463                 goto tagcontrol_bailout;
4464         }
4465
4466         if (arglist & CAM_ARG_VERBOSE) {
4467                 fprintf(stdout, "%s", pathstr);
4468                 fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4469                 fprintf(stdout, "%s", pathstr);
4470                 fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4471                 fprintf(stdout, "%s", pathstr);
4472                 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
4473                 fprintf(stdout, "%s", pathstr);
4474                 fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
4475                 fprintf(stdout, "%s", pathstr);
4476                 fprintf(stdout, "held          %d\n", ccb->cgds.held);
4477                 fprintf(stdout, "%s", pathstr);
4478                 fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4479                 fprintf(stdout, "%s", pathstr);
4480                 fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4481         } else {
4482                 if (quiet == 0) {
4483                         fprintf(stdout, "%s", pathstr);
4484                         fprintf(stdout, "device openings: ");
4485                 }
4486                 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4487                         ccb->cgds.dev_active);
4488         }
4489
4490 tagcontrol_bailout:
4491
4492         cam_freeccb(ccb);
4493         return(retval);
4494 }
4495
4496 static void
4497 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4498 {
4499         char pathstr[1024];
4500
4501         cam_path_string(device, pathstr, sizeof(pathstr));
4502
4503         if (cts->transport == XPORT_SPI) {
4504                 struct ccb_trans_settings_spi *spi =
4505                     &cts->xport_specific.spi;
4506
4507                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4508
4509                         fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4510                                 spi->sync_period);
4511
4512                         if (spi->sync_offset != 0) {
4513                                 u_int freq;
4514
4515                                 freq = scsi_calc_syncsrate(spi->sync_period);
4516                                 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4517                                         pathstr, freq / 1000, freq % 1000);
4518                         }
4519                 }
4520
4521                 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4522                         fprintf(stdout, "%soffset: %d\n", pathstr,
4523                             spi->sync_offset);
4524                 }
4525
4526                 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4527                         fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4528                                 (0x01 << spi->bus_width) * 8);
4529                 }
4530
4531                 if (spi->valid & CTS_SPI_VALID_DISC) {
4532                         fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4533                                 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4534                                 "enabled" : "disabled");
4535                 }
4536         }
4537         if (cts->transport == XPORT_FC) {
4538                 struct ccb_trans_settings_fc *fc =
4539                     &cts->xport_specific.fc;
4540
4541                 if (fc->valid & CTS_FC_VALID_WWNN)
4542                         fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4543                             (long long) fc->wwnn);
4544                 if (fc->valid & CTS_FC_VALID_WWPN)
4545                         fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4546                             (long long) fc->wwpn);
4547                 if (fc->valid & CTS_FC_VALID_PORT)
4548                         fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4549                 if (fc->valid & CTS_FC_VALID_SPEED)
4550                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4551                             pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4552         }
4553         if (cts->transport == XPORT_SAS) {
4554                 struct ccb_trans_settings_sas *sas =
4555                     &cts->xport_specific.sas;
4556
4557                 if (sas->valid & CTS_SAS_VALID_SPEED)
4558                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4559                             pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4560         }
4561         if (cts->transport == XPORT_ATA) {
4562                 struct ccb_trans_settings_pata *pata =
4563                     &cts->xport_specific.ata;
4564
4565                 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4566                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4567                                 ata_mode2string(pata->mode));
4568                 }
4569                 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4570                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4571                                 pata->atapi);
4572                 }
4573                 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4574                         fprintf(stdout, "%sPIO transaction length: %d\n",
4575                                 pathstr, pata->bytecount);
4576                 }
4577         }
4578         if (cts->transport == XPORT_SATA) {
4579                 struct ccb_trans_settings_sata *sata =
4580                     &cts->xport_specific.sata;
4581
4582                 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4583                         fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4584                                 sata->revision);
4585                 }
4586                 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4587                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4588                                 ata_mode2string(sata->mode));
4589                 }
4590                 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4591                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4592                                 sata->atapi);
4593                 }
4594                 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4595                         fprintf(stdout, "%sPIO transaction length: %d\n",
4596                                 pathstr, sata->bytecount);
4597                 }
4598                 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4599                         fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4600                                 sata->pm_present);
4601                 }
4602                 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4603                         fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4604                                 sata->tags);
4605                 }
4606                 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4607                         fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4608                                 sata->caps);
4609                 }
4610         }
4611         if (cts->protocol == PROTO_ATA) {
4612                 struct ccb_trans_settings_ata *ata=
4613                     &cts->proto_specific.ata;
4614
4615                 if (ata->valid & CTS_ATA_VALID_TQ) {
4616                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4617                                 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4618                                 "enabled" : "disabled");
4619                 }
4620         }
4621         if (cts->protocol == PROTO_SCSI) {
4622                 struct ccb_trans_settings_scsi *scsi=
4623                     &cts->proto_specific.scsi;
4624
4625                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
4626                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4627                                 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4628                                 "enabled" : "disabled");
4629                 }
4630         }
4631
4632 }
4633
4634 /*
4635  * Get a path inquiry CCB for the specified device.
4636  */
4637 static int
4638 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4639 {
4640         union ccb *ccb;
4641         int retval = 0;
4642
4643         ccb = cam_getccb(device);
4644         if (ccb == NULL) {
4645                 warnx("get_cpi: couldn't allocate CCB");
4646                 return(1);
4647         }
4648         bzero(&(&ccb->ccb_h)[1],
4649               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4650         ccb->ccb_h.func_code = XPT_PATH_INQ;
4651         if (cam_send_ccb(device, ccb) < 0) {
4652                 warn("get_cpi: error sending Path Inquiry CCB");
4653                 if (arglist & CAM_ARG_VERBOSE)
4654                         cam_error_print(device, ccb, CAM_ESF_ALL,
4655                                         CAM_EPF_ALL, stderr);
4656                 retval = 1;
4657                 goto get_cpi_bailout;
4658         }
4659         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4660                 if (arglist & CAM_ARG_VERBOSE)
4661                         cam_error_print(device, ccb, CAM_ESF_ALL,
4662                                         CAM_EPF_ALL, stderr);
4663                 retval = 1;
4664                 goto get_cpi_bailout;
4665         }
4666         bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4667
4668 get_cpi_bailout:
4669         cam_freeccb(ccb);
4670         return(retval);
4671 }
4672
4673 /*
4674  * Get a get device CCB for the specified device.
4675  */
4676 static int
4677 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4678 {
4679         union ccb *ccb;
4680         int retval = 0;
4681
4682         ccb = cam_getccb(device);
4683         if (ccb == NULL) {
4684                 warnx("get_cgd: couldn't allocate CCB");
4685                 return(1);
4686         }
4687         bzero(&(&ccb->ccb_h)[1],
4688               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4689         ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4690         if (cam_send_ccb(device, ccb) < 0) {
4691                 warn("get_cgd: error sending Path Inquiry CCB");
4692                 if (arglist & CAM_ARG_VERBOSE)
4693                         cam_error_print(device, ccb, CAM_ESF_ALL,
4694                                         CAM_EPF_ALL, stderr);
4695                 retval = 1;
4696                 goto get_cgd_bailout;
4697         }
4698         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4699                 if (arglist & CAM_ARG_VERBOSE)
4700                         cam_error_print(device, ccb, CAM_ESF_ALL,
4701                                         CAM_EPF_ALL, stderr);
4702                 retval = 1;
4703                 goto get_cgd_bailout;
4704         }
4705         bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4706
4707 get_cgd_bailout:
4708         cam_freeccb(ccb);
4709         return(retval);
4710 }
4711
4712 /* return the type of disk (really the command type) */
4713 static const char *
4714 get_disk_type(struct cam_device *device)
4715 {
4716         struct ccb_getdev       cgd;
4717
4718         (void) memset(&cgd, 0x0, sizeof(cgd));
4719         get_cgd(device, &cgd);
4720         switch(cgd.protocol) {
4721         case PROTO_SCSI:
4722                 return "scsi";
4723         case PROTO_ATA:
4724         case PROTO_ATAPI:
4725         case PROTO_SATAPM:
4726                 return "ata";
4727         default:
4728                 return "unknown";
4729         }
4730 }
4731
4732 static void
4733 cpi_print(struct ccb_pathinq *cpi)
4734 {
4735         char adapter_str[1024];
4736         int i;
4737
4738         snprintf(adapter_str, sizeof(adapter_str),
4739                  "%s%d:", cpi->dev_name, cpi->unit_number);
4740
4741         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
4742                 cpi->version_num);
4743
4744         for (i = 1; i < 0xff; i = i << 1) {
4745                 const char *str;
4746
4747                 if ((i & cpi->hba_inquiry) == 0)
4748                         continue;
4749
4750                 fprintf(stdout, "%s supports ", adapter_str);
4751
4752                 switch(i) {
4753                 case PI_MDP_ABLE:
4754                         str = "MDP message";
4755                         break;
4756                 case PI_WIDE_32:
4757                         str = "32 bit wide SCSI";
4758                         break;
4759                 case PI_WIDE_16:
4760                         str = "16 bit wide SCSI";
4761                         break;
4762                 case PI_SDTR_ABLE:
4763                         str = "SDTR message";
4764                         break;
4765                 case PI_LINKED_CDB:
4766                         str = "linked CDBs";
4767                         break;
4768                 case PI_TAG_ABLE:
4769                         str = "tag queue messages";
4770                         break;
4771                 case PI_SOFT_RST:
4772                         str = "soft reset alternative";
4773                         break;
4774                 case PI_SATAPM:
4775                         str = "SATA Port Multiplier";
4776                         break;
4777                 default:
4778                         str = "unknown PI bit set";
4779                         break;
4780                 }
4781                 fprintf(stdout, "%s\n", str);
4782         }
4783
4784         for (i = 1; i < 0xff; i = i << 1) {
4785                 const char *str;
4786
4787                 if ((i & cpi->hba_misc) == 0)
4788                         continue;
4789
4790                 fprintf(stdout, "%s ", adapter_str);
4791
4792                 switch(i) {
4793                 case PIM_SCANHILO:
4794                         str = "bus scans from high ID to low ID";
4795                         break;
4796                 case PIM_NOREMOVE:
4797                         str = "removable devices not included in scan";
4798                         break;
4799                 case PIM_NOINITIATOR:
4800                         str = "initiator role not supported";
4801                         break;
4802                 case PIM_NOBUSRESET:
4803                         str = "user has disabled initial BUS RESET or"
4804                               " controller is in target/mixed mode";
4805                         break;
4806                 case PIM_NO_6_BYTE:
4807                         str = "do not send 6-byte commands";
4808                         break;
4809                 case PIM_SEQSCAN:
4810                         str = "scan bus sequentially";
4811                         break;
4812                 default:
4813                         str = "unknown PIM bit set";
4814                         break;
4815                 }
4816                 fprintf(stdout, "%s\n", str);
4817         }
4818
4819         for (i = 1; i < 0xff; i = i << 1) {
4820                 const char *str;
4821
4822                 if ((i & cpi->target_sprt) == 0)
4823                         continue;
4824
4825                 fprintf(stdout, "%s supports ", adapter_str);
4826                 switch(i) {
4827                 case PIT_PROCESSOR:
4828                         str = "target mode processor mode";
4829                         break;
4830                 case PIT_PHASE:
4831                         str = "target mode phase cog. mode";
4832                         break;
4833                 case PIT_DISCONNECT:
4834                         str = "disconnects in target mode";
4835                         break;
4836                 case PIT_TERM_IO:
4837                         str = "terminate I/O message in target mode";
4838                         break;
4839                 case PIT_GRP_6:
4840                         str = "group 6 commands in target mode";
4841                         break;
4842                 case PIT_GRP_7:
4843                         str = "group 7 commands in target mode";
4844                         break;
4845                 default:
4846                         str = "unknown PIT bit set";
4847                         break;
4848                 }
4849
4850                 fprintf(stdout, "%s\n", str);
4851         }
4852         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
4853                 cpi->hba_eng_cnt);
4854         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
4855                 cpi->max_target);
4856         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
4857                 cpi->max_lun);
4858         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
4859                 adapter_str, cpi->hpath_id);
4860         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
4861                 cpi->initiator_id);
4862         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
4863         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
4864         fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
4865             adapter_str, cpi->hba_vendor);
4866         fprintf(stdout, "%s HBA device ID: 0x%04x\n",
4867             adapter_str, cpi->hba_device);
4868         fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
4869             adapter_str, cpi->hba_subvendor);
4870         fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
4871             adapter_str, cpi->hba_subdevice);
4872         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
4873         fprintf(stdout, "%s base transfer speed: ", adapter_str);
4874         if (cpi->base_transfer_speed > 1000)
4875                 fprintf(stdout, "%d.%03dMB/sec\n",
4876                         cpi->base_transfer_speed / 1000,
4877                         cpi->base_transfer_speed % 1000);
4878         else
4879                 fprintf(stdout, "%dKB/sec\n",
4880                         (cpi->base_transfer_speed % 1000) * 1000);
4881         fprintf(stdout, "%s maximum transfer size: %u bytes\n",
4882             adapter_str, cpi->maxio);
4883 }
4884
4885 static int
4886 get_print_cts(struct cam_device *device, int user_settings, int quiet,
4887               struct ccb_trans_settings *cts)
4888 {
4889         int retval;
4890         union ccb *ccb;
4891
4892         retval = 0;
4893         ccb = cam_getccb(device);
4894
4895         if (ccb == NULL) {
4896                 warnx("get_print_cts: error allocating ccb");
4897                 return(1);
4898         }
4899
4900         bzero(&(&ccb->ccb_h)[1],
4901               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
4902
4903         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
4904
4905         if (user_settings == 0)
4906                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
4907         else
4908                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
4909
4910         if (cam_send_ccb(device, ccb) < 0) {
4911                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
4912                 if (arglist & CAM_ARG_VERBOSE)
4913                         cam_error_print(device, ccb, CAM_ESF_ALL,
4914                                         CAM_EPF_ALL, stderr);
4915                 retval = 1;
4916                 goto get_print_cts_bailout;
4917         }
4918
4919         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4920                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
4921                 if (arglist & CAM_ARG_VERBOSE)
4922                         cam_error_print(device, ccb, CAM_ESF_ALL,
4923                                         CAM_EPF_ALL, stderr);
4924                 retval = 1;
4925                 goto get_print_cts_bailout;
4926         }
4927
4928         if (quiet == 0)
4929                 cts_print(device, &ccb->cts);
4930
4931         if (cts != NULL)
4932                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
4933
4934 get_print_cts_bailout:
4935
4936         cam_freeccb(ccb);
4937
4938         return(retval);
4939 }
4940
4941 static int
4942 ratecontrol(struct cam_device *device, int retry_count, int timeout,
4943             int argc, char **argv, char *combinedopt)
4944 {
4945         int c;
4946         union ccb *ccb;
4947         int user_settings = 0;
4948         int retval = 0;
4949         int disc_enable = -1, tag_enable = -1;
4950         int mode = -1;
4951         int offset = -1;
4952         double syncrate = -1;
4953         int bus_width = -1;
4954         int quiet = 0;
4955         int change_settings = 0, send_tur = 0;
4956         struct ccb_pathinq cpi;
4957
4958         ccb = cam_getccb(device);
4959         if (ccb == NULL) {
4960                 warnx("ratecontrol: error allocating ccb");
4961                 return(1);
4962         }
4963         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4964                 switch(c){
4965                 case 'a':
4966                         send_tur = 1;
4967                         break;
4968                 case 'c':
4969                         user_settings = 0;
4970                         break;
4971                 case 'D':
4972                         if (strncasecmp(optarg, "enable", 6) == 0)
4973                                 disc_enable = 1;
4974                         else if (strncasecmp(optarg, "disable", 7) == 0)
4975                                 disc_enable = 0;
4976                         else {
4977                                 warnx("-D argument \"%s\" is unknown", optarg);
4978                                 retval = 1;
4979                                 goto ratecontrol_bailout;
4980                         }
4981                         change_settings = 1;
4982                         break;
4983                 case 'M':
4984                         mode = ata_string2mode(optarg);
4985                         if (mode < 0) {
4986                                 warnx("unknown mode '%s'", optarg);
4987                                 retval = 1;
4988                                 goto ratecontrol_bailout;
4989                         }
4990                         change_settings = 1;
4991                         break;
4992                 case 'O':
4993                         offset = strtol(optarg, NULL, 0);
4994                         if (offset < 0) {
4995                                 warnx("offset value %d is < 0", offset);
4996                                 retval = 1;
4997                                 goto ratecontrol_bailout;
4998                         }
4999                         change_settings = 1;
5000                         break;
5001                 case 'q':
5002                         quiet++;
5003                         break;
5004                 case 'R':
5005                         syncrate = atof(optarg);
5006                         if (syncrate < 0) {
5007                                 warnx("sync rate %f is < 0", syncrate);
5008                                 retval = 1;
5009                                 goto ratecontrol_bailout;
5010                         }
5011                         change_settings = 1;
5012                         break;
5013                 case 'T':
5014                         if (strncasecmp(optarg, "enable", 6) == 0)
5015                                 tag_enable = 1;
5016                         else if (strncasecmp(optarg, "disable", 7) == 0)
5017                                 tag_enable = 0;
5018                         else {
5019                                 warnx("-T argument \"%s\" is unknown", optarg);
5020                                 retval = 1;
5021                                 goto ratecontrol_bailout;
5022                         }
5023                         change_settings = 1;
5024                         break;
5025                 case 'U':
5026                         user_settings = 1;
5027                         break;
5028                 case 'W':
5029                         bus_width = strtol(optarg, NULL, 0);
5030                         if (bus_width < 0) {
5031                                 warnx("bus width %d is < 0", bus_width);
5032                                 retval = 1;
5033                                 goto ratecontrol_bailout;
5034                         }
5035                         change_settings = 1;
5036                         break;
5037                 default:
5038                         break;
5039                 }
5040         }
5041         bzero(&(&ccb->ccb_h)[1],
5042               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5043         /*
5044          * Grab path inquiry information, so we can determine whether
5045          * or not the initiator is capable of the things that the user
5046          * requests.
5047          */
5048         ccb->ccb_h.func_code = XPT_PATH_INQ;
5049         if (cam_send_ccb(device, ccb) < 0) {
5050                 perror("error sending XPT_PATH_INQ CCB");
5051                 if (arglist & CAM_ARG_VERBOSE) {
5052                         cam_error_print(device, ccb, CAM_ESF_ALL,
5053                                         CAM_EPF_ALL, stderr);
5054                 }
5055                 retval = 1;
5056                 goto ratecontrol_bailout;
5057         }
5058         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5059                 warnx("XPT_PATH_INQ CCB failed");
5060                 if (arglist & CAM_ARG_VERBOSE) {
5061                         cam_error_print(device, ccb, CAM_ESF_ALL,
5062                                         CAM_EPF_ALL, stderr);
5063                 }
5064                 retval = 1;
5065                 goto ratecontrol_bailout;
5066         }
5067         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5068         bzero(&(&ccb->ccb_h)[1],
5069               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5070         if (quiet == 0) {
5071                 fprintf(stdout, "%s parameters:\n",
5072                     user_settings ? "User" : "Current");
5073         }
5074         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5075         if (retval != 0)
5076                 goto ratecontrol_bailout;
5077
5078         if (arglist & CAM_ARG_VERBOSE)
5079                 cpi_print(&cpi);
5080
5081         if (change_settings) {
5082                 int didsettings = 0;
5083                 struct ccb_trans_settings_spi *spi = NULL;
5084                 struct ccb_trans_settings_pata *pata = NULL;
5085                 struct ccb_trans_settings_sata *sata = NULL;
5086                 struct ccb_trans_settings_ata *ata = NULL;
5087                 struct ccb_trans_settings_scsi *scsi = NULL;
5088
5089                 if (ccb->cts.transport == XPORT_SPI)
5090                         spi = &ccb->cts.xport_specific.spi;
5091                 if (ccb->cts.transport == XPORT_ATA)
5092                         pata = &ccb->cts.xport_specific.ata;
5093                 if (ccb->cts.transport == XPORT_SATA)
5094                         sata = &ccb->cts.xport_specific.sata;
5095                 if (ccb->cts.protocol == PROTO_ATA)
5096                         ata = &ccb->cts.proto_specific.ata;
5097                 if (ccb->cts.protocol == PROTO_SCSI)
5098                         scsi = &ccb->cts.proto_specific.scsi;
5099                 ccb->cts.xport_specific.valid = 0;
5100                 ccb->cts.proto_specific.valid = 0;
5101                 if (spi && disc_enable != -1) {
5102                         spi->valid |= CTS_SPI_VALID_DISC;
5103                         if (disc_enable == 0)
5104                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5105                         else
5106                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5107                         didsettings++;
5108                 }
5109                 if (tag_enable != -1) {
5110                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5111                                 warnx("HBA does not support tagged queueing, "
5112                                       "so you cannot modify tag settings");
5113                                 retval = 1;
5114                                 goto ratecontrol_bailout;
5115                         }
5116                         if (ata) {
5117                                 ata->valid |= CTS_SCSI_VALID_TQ;
5118                                 if (tag_enable == 0)
5119                                         ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5120                                 else
5121                                         ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5122                                 didsettings++;
5123                         } else if (scsi) {
5124                                 scsi->valid |= CTS_SCSI_VALID_TQ;
5125                                 if (tag_enable == 0)
5126                                         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5127                                 else
5128                                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5129                                 didsettings++;
5130                         }
5131                 }
5132                 if (spi && offset != -1) {
5133                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5134                                 warnx("HBA is not capable of changing offset");
5135                                 retval = 1;
5136                                 goto ratecontrol_bailout;
5137                         }
5138                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5139                         spi->sync_offset = offset;
5140                         didsettings++;
5141                 }
5142                 if (spi && syncrate != -1) {
5143                         int prelim_sync_period;
5144
5145                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5146                                 warnx("HBA is not capable of changing "
5147                                       "transfer rates");
5148                                 retval = 1;
5149                                 goto ratecontrol_bailout;
5150                         }
5151                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5152                         /*
5153                          * The sync rate the user gives us is in MHz.
5154                          * We need to translate it into KHz for this
5155                          * calculation.
5156                          */
5157                         syncrate *= 1000;
5158                         /*
5159                          * Next, we calculate a "preliminary" sync period
5160                          * in tenths of a nanosecond.
5161                          */
5162                         if (syncrate == 0)
5163                                 prelim_sync_period = 0;
5164                         else
5165                                 prelim_sync_period = 10000000 / syncrate;
5166                         spi->sync_period =
5167                                 scsi_calc_syncparam(prelim_sync_period);
5168                         didsettings++;
5169                 }
5170                 if (sata && syncrate != -1) {
5171                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5172                                 warnx("HBA is not capable of changing "
5173                                       "transfer rates");
5174                                 retval = 1;
5175                                 goto ratecontrol_bailout;
5176                         }
5177                         if  (!user_settings) {
5178                                 warnx("You can modify only user rate "
5179                                     "settings for SATA");
5180                                 retval = 1;
5181                                 goto ratecontrol_bailout;
5182                         }
5183                         sata->revision = ata_speed2revision(syncrate * 100);
5184                         if (sata->revision < 0) {
5185                                 warnx("Invalid rate %f", syncrate);
5186                                 retval = 1;
5187                                 goto ratecontrol_bailout;
5188                         }
5189                         sata->valid |= CTS_SATA_VALID_REVISION;
5190                         didsettings++;
5191                 }
5192                 if ((pata || sata) && mode != -1) {
5193                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5194                                 warnx("HBA is not capable of changing "
5195                                       "transfer rates");
5196                                 retval = 1;
5197                                 goto ratecontrol_bailout;
5198                         }
5199                         if  (!user_settings) {
5200                                 warnx("You can modify only user mode "
5201                                     "settings for ATA/SATA");
5202                                 retval = 1;
5203                                 goto ratecontrol_bailout;
5204                         }
5205                         if (pata) {
5206                                 pata->mode = mode;
5207                                 pata->valid |= CTS_ATA_VALID_MODE;
5208                         } else {
5209                                 sata->mode = mode;
5210                                 sata->valid |= CTS_SATA_VALID_MODE;
5211                         }
5212                         didsettings++;
5213                 }
5214                 /*
5215                  * The bus_width argument goes like this:
5216                  * 0 == 8 bit
5217                  * 1 == 16 bit
5218                  * 2 == 32 bit
5219                  * Therefore, if you shift the number of bits given on the
5220                  * command line right by 4, you should get the correct
5221                  * number.
5222                  */
5223                 if (spi && bus_width != -1) {
5224                         /*
5225                          * We might as well validate things here with a
5226                          * decipherable error message, rather than what
5227                          * will probably be an indecipherable error message
5228                          * by the time it gets back to us.
5229                          */
5230                         if ((bus_width == 16)
5231                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5232                                 warnx("HBA does not support 16 bit bus width");
5233                                 retval = 1;
5234                                 goto ratecontrol_bailout;
5235                         } else if ((bus_width == 32)
5236                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5237                                 warnx("HBA does not support 32 bit bus width");
5238                                 retval = 1;
5239                                 goto ratecontrol_bailout;
5240                         } else if ((bus_width != 8)
5241                                 && (bus_width != 16)
5242                                 && (bus_width != 32)) {
5243                                 warnx("Invalid bus width %d", bus_width);
5244                                 retval = 1;
5245                                 goto ratecontrol_bailout;
5246                         }
5247                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5248                         spi->bus_width = bus_width >> 4;
5249                         didsettings++;
5250                 }
5251                 if  (didsettings == 0) {
5252                         goto ratecontrol_bailout;
5253                 }
5254                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5255                 if (cam_send_ccb(device, ccb) < 0) {
5256                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5257                         if (arglist & CAM_ARG_VERBOSE) {
5258                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5259                                                 CAM_EPF_ALL, stderr);
5260                         }
5261                         retval = 1;
5262                         goto ratecontrol_bailout;
5263                 }
5264                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5265                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5266                         if (arglist & CAM_ARG_VERBOSE) {
5267                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5268                                                 CAM_EPF_ALL, stderr);
5269                         }
5270                         retval = 1;
5271                         goto ratecontrol_bailout;
5272                 }
5273         }
5274         if (send_tur) {
5275                 retval = testunitready(device, retry_count, timeout,
5276                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5277                 /*
5278                  * If the TUR didn't succeed, just bail.
5279                  */
5280                 if (retval != 0) {
5281                         if (quiet == 0)
5282                                 fprintf(stderr, "Test Unit Ready failed\n");
5283                         goto ratecontrol_bailout;
5284                 }
5285         }
5286         if ((change_settings || send_tur) && !quiet &&
5287             (ccb->cts.transport == XPORT_ATA ||
5288              ccb->cts.transport == XPORT_SATA || send_tur)) {
5289                 fprintf(stdout, "New parameters:\n");
5290                 retval = get_print_cts(device, user_settings, 0, NULL);
5291         }
5292
5293 ratecontrol_bailout:
5294         cam_freeccb(ccb);
5295         return(retval);
5296 }
5297
5298 static int
5299 scsiformat(struct cam_device *device, int argc, char **argv,
5300            char *combinedopt, int retry_count, int timeout)
5301 {
5302         union ccb *ccb;
5303         int c;
5304         int ycount = 0, quiet = 0;
5305         int error = 0, retval = 0;
5306         int use_timeout = 10800 * 1000;
5307         int immediate = 1;
5308         struct format_defect_list_header fh;
5309         u_int8_t *data_ptr = NULL;
5310         u_int32_t dxfer_len = 0;
5311         u_int8_t byte2 = 0;
5312         int num_warnings = 0;
5313         int reportonly = 0;
5314
5315         ccb = cam_getccb(device);
5316
5317         if (ccb == NULL) {
5318                 warnx("scsiformat: error allocating ccb");
5319                 return(1);
5320         }
5321
5322         bzero(&(&ccb->ccb_h)[1],
5323               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5324
5325         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5326                 switch(c) {
5327                 case 'q':
5328                         quiet++;
5329                         break;
5330                 case 'r':
5331                         reportonly = 1;
5332                         break;
5333                 case 'w':
5334                         immediate = 0;
5335                         break;
5336                 case 'y':
5337                         ycount++;
5338                         break;
5339                 }
5340         }
5341
5342         if (reportonly)
5343                 goto doreport;
5344
5345         if (quiet == 0) {
5346                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5347                         "following device:\n");
5348
5349                 error = scsidoinquiry(device, argc, argv, combinedopt,
5350                                       retry_count, timeout);
5351
5352                 if (error != 0) {
5353                         warnx("scsiformat: error sending inquiry");
5354                         goto scsiformat_bailout;
5355                 }
5356         }
5357
5358         if (ycount == 0) {
5359                 if (!get_confirmation()) {
5360                         error = 1;
5361                         goto scsiformat_bailout;
5362                 }
5363         }
5364
5365         if (timeout != 0)
5366                 use_timeout = timeout;
5367
5368         if (quiet == 0) {
5369                 fprintf(stdout, "Current format timeout is %d seconds\n",
5370                         use_timeout / 1000);
5371         }
5372
5373         /*
5374          * If the user hasn't disabled questions and didn't specify a
5375          * timeout on the command line, ask them if they want the current
5376          * timeout.
5377          */
5378         if ((ycount == 0)
5379          && (timeout == 0)) {
5380                 char str[1024];
5381                 int new_timeout = 0;
5382
5383                 fprintf(stdout, "Enter new timeout in seconds or press\n"
5384                         "return to keep the current timeout [%d] ",
5385                         use_timeout / 1000);
5386
5387                 if (fgets(str, sizeof(str), stdin) != NULL) {
5388                         if (str[0] != '\0')
5389                                 new_timeout = atoi(str);
5390                 }
5391
5392                 if (new_timeout != 0) {
5393                         use_timeout = new_timeout * 1000;
5394                         fprintf(stdout, "Using new timeout value %d\n",
5395                                 use_timeout / 1000);
5396                 }
5397         }
5398
5399         /*
5400          * Keep this outside the if block below to silence any unused
5401          * variable warnings.
5402          */
5403         bzero(&fh, sizeof(fh));
5404
5405         /*
5406          * If we're in immediate mode, we've got to include the format
5407          * header
5408          */
5409         if (immediate != 0) {
5410                 fh.byte2 = FU_DLH_IMMED;
5411                 data_ptr = (u_int8_t *)&fh;
5412                 dxfer_len = sizeof(fh);
5413                 byte2 = FU_FMT_DATA;
5414         } else if (quiet == 0) {
5415                 fprintf(stdout, "Formatting...");
5416                 fflush(stdout);
5417         }
5418
5419         scsi_format_unit(&ccb->csio,
5420                          /* retries */ retry_count,
5421                          /* cbfcnp */ NULL,
5422                          /* tag_action */ MSG_SIMPLE_Q_TAG,
5423                          /* byte2 */ byte2,
5424                          /* ileave */ 0,
5425                          /* data_ptr */ data_ptr,
5426                          /* dxfer_len */ dxfer_len,
5427                          /* sense_len */ SSD_FULL_SIZE,
5428                          /* timeout */ use_timeout);
5429
5430         /* Disable freezing the device queue */
5431         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5432
5433         if (arglist & CAM_ARG_ERR_RECOVER)
5434                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5435
5436         if (((retval = cam_send_ccb(device, ccb)) < 0)
5437          || ((immediate == 0)
5438            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5439                 const char errstr[] = "error sending format command";
5440
5441                 if (retval < 0)
5442                         warn(errstr);
5443                 else
5444                         warnx(errstr);
5445
5446                 if (arglist & CAM_ARG_VERBOSE) {
5447                         cam_error_print(device, ccb, CAM_ESF_ALL,
5448                                         CAM_EPF_ALL, stderr);
5449                 }
5450                 error = 1;
5451                 goto scsiformat_bailout;
5452         }
5453
5454         /*
5455          * If we ran in non-immediate mode, we already checked for errors
5456          * above and printed out any necessary information.  If we're in
5457          * immediate mode, we need to loop through and get status
5458          * information periodically.
5459          */
5460         if (immediate == 0) {
5461                 if (quiet == 0) {
5462                         fprintf(stdout, "Format Complete\n");
5463                 }
5464                 goto scsiformat_bailout;
5465         }
5466
5467 doreport:
5468         do {
5469                 cam_status status;
5470
5471                 bzero(&(&ccb->ccb_h)[1],
5472                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5473
5474                 /*
5475                  * There's really no need to do error recovery or
5476                  * retries here, since we're just going to sit in a
5477                  * loop and wait for the device to finish formatting.
5478                  */
5479                 scsi_test_unit_ready(&ccb->csio,
5480                                      /* retries */ 0,
5481                                      /* cbfcnp */ NULL,
5482                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
5483                                      /* sense_len */ SSD_FULL_SIZE,
5484                                      /* timeout */ 5000);
5485
5486                 /* Disable freezing the device queue */
5487                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5488
5489                 retval = cam_send_ccb(device, ccb);
5490
5491                 /*
5492                  * If we get an error from the ioctl, bail out.  SCSI
5493                  * errors are expected.
5494                  */
5495                 if (retval < 0) {
5496                         warn("error sending CAMIOCOMMAND ioctl");
5497                         if (arglist & CAM_ARG_VERBOSE) {
5498                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5499                                                 CAM_EPF_ALL, stderr);
5500                         }
5501                         error = 1;
5502                         goto scsiformat_bailout;
5503                 }
5504
5505                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5506
5507                 if ((status != CAM_REQ_CMP)
5508                  && (status == CAM_SCSI_STATUS_ERROR)
5509                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5510                         struct scsi_sense_data *sense;
5511                         int error_code, sense_key, asc, ascq;
5512
5513                         sense = &ccb->csio.sense_data;
5514                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
5515                             ccb->csio.sense_resid, &error_code, &sense_key,
5516                             &asc, &ascq, /*show_errors*/ 1);
5517
5518                         /*
5519                          * According to the SCSI-2 and SCSI-3 specs, a
5520                          * drive that is in the middle of a format should
5521                          * return NOT READY with an ASC of "logical unit
5522                          * not ready, format in progress".  The sense key
5523                          * specific bytes will then be a progress indicator.
5524                          */
5525                         if ((sense_key == SSD_KEY_NOT_READY)
5526                          && (asc == 0x04) && (ascq == 0x04)) {
5527                                 uint8_t sks[3];
5528
5529                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5530                                      ccb->csio.sense_resid, sks) == 0)
5531                                  && (quiet == 0)) {
5532                                         int val;
5533                                         u_int64_t percentage;
5534
5535                                         val = scsi_2btoul(&sks[1]);
5536                                         percentage = 10000 * val;
5537
5538                                         fprintf(stdout,
5539                                                 "\rFormatting:  %ju.%02u %% "
5540                                                 "(%d/%d) done",
5541                                                 (uintmax_t)(percentage /
5542                                                 (0x10000 * 100)),
5543                                                 (unsigned)((percentage /
5544                                                 0x10000) % 100),
5545                                                 val, 0x10000);
5546                                         fflush(stdout);
5547                                 } else if ((quiet == 0)
5548                                         && (++num_warnings <= 1)) {
5549                                         warnx("Unexpected SCSI Sense Key "
5550                                               "Specific value returned "
5551                                               "during format:");
5552                                         scsi_sense_print(device, &ccb->csio,
5553                                                          stderr);
5554                                         warnx("Unable to print status "
5555                                               "information, but format will "
5556                                               "proceed.");
5557                                         warnx("will exit when format is "
5558                                               "complete");
5559                                 }
5560                                 sleep(1);
5561                         } else {
5562                                 warnx("Unexpected SCSI error during format");
5563                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5564                                                 CAM_EPF_ALL, stderr);
5565                                 error = 1;
5566                                 goto scsiformat_bailout;
5567                         }
5568
5569                 } else if (status != CAM_REQ_CMP) {
5570                         warnx("Unexpected CAM status %#x", status);
5571                         if (arglist & CAM_ARG_VERBOSE)
5572                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5573                                                 CAM_EPF_ALL, stderr);
5574                         error = 1;
5575                         goto scsiformat_bailout;
5576                 }
5577
5578         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5579
5580         if (quiet == 0)
5581                 fprintf(stdout, "\nFormat Complete\n");
5582
5583 scsiformat_bailout:
5584
5585         cam_freeccb(ccb);
5586
5587         return(error);
5588 }
5589
5590 static int
5591 scsisanitize(struct cam_device *device, int argc, char **argv,
5592              char *combinedopt, int retry_count, int timeout)
5593 {
5594         union ccb *ccb;
5595         u_int8_t action = 0;
5596         int c;
5597         int ycount = 0, quiet = 0;
5598         int error = 0, retval = 0;
5599         int use_timeout = 10800 * 1000;
5600         int immediate = 1;
5601         int invert = 0;
5602         int passes = 0;
5603         int ause = 0;
5604         int fd = -1;
5605         const char *pattern = NULL;
5606         u_int8_t *data_ptr = NULL;
5607         u_int32_t dxfer_len = 0;
5608         u_int8_t byte2 = 0;
5609         int num_warnings = 0;
5610         int reportonly = 0;
5611
5612         ccb = cam_getccb(device);
5613
5614         if (ccb == NULL) {
5615                 warnx("scsisanitize: error allocating ccb");
5616                 return(1);
5617         }
5618
5619         bzero(&(&ccb->ccb_h)[1],
5620               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5621
5622         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5623                 switch(c) {
5624                 case 'a':
5625                         if (strcasecmp(optarg, "overwrite") == 0)
5626                                 action = SSZ_SERVICE_ACTION_OVERWRITE;
5627                         else if (strcasecmp(optarg, "block") == 0)
5628                                 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
5629                         else if (strcasecmp(optarg, "crypto") == 0)
5630                                 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
5631                         else if (strcasecmp(optarg, "exitfailure") == 0)
5632                                 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
5633                         else {
5634                                 warnx("invalid service operation \"%s\"",
5635                                       optarg);
5636                                 error = 1;
5637                                 goto scsisanitize_bailout;
5638                         }
5639                         break;
5640                 case 'c':
5641                         passes = strtol(optarg, NULL, 0);
5642                         if (passes < 1 || passes > 31) {
5643                                 warnx("invalid passes value %d", passes);
5644                                 error = 1;
5645                                 goto scsisanitize_bailout;
5646                         }
5647                         break;
5648                 case 'I':
5649                         invert = 1;
5650                         break;
5651                 case 'P':
5652                         pattern = optarg;
5653                         break;
5654                 case 'q':
5655                         quiet++;
5656                         break;
5657                 case 'U':
5658                         ause = 1;
5659                         break;
5660                 case 'r':
5661                         reportonly = 1;
5662                         break;
5663                 case 'w':
5664                         immediate = 0;
5665                         break;
5666                 case 'y':
5667                         ycount++;
5668                         break;
5669                 }
5670         }
5671
5672         if (reportonly)
5673                 goto doreport;
5674
5675         if (action == 0) {
5676                 warnx("an action is required");
5677                 error = 1;
5678                 goto scsisanitize_bailout;
5679         } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
5680                 struct scsi_sanitize_parameter_list *pl;
5681                 struct stat sb;
5682                 ssize_t sz, amt;
5683
5684                 if (pattern == NULL) {
5685                         warnx("overwrite action requires -P argument");
5686                         error = 1;
5687                         goto scsisanitize_bailout;
5688                 }
5689                 fd = open(pattern, O_RDONLY);
5690                 if (fd < 0) {
5691                         warn("cannot open pattern file %s", pattern);
5692                         error = 1;
5693                         goto scsisanitize_bailout;
5694                 }
5695                 if (fstat(fd, &sb) < 0) {
5696                         warn("cannot stat pattern file %s", pattern);
5697                         error = 1;
5698                         goto scsisanitize_bailout;
5699                 }
5700                 sz = sb.st_size;
5701                 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
5702                         warnx("pattern file size exceeds maximum value %d",
5703                               SSZPL_MAX_PATTERN_LENGTH);
5704                         error = 1;
5705                         goto scsisanitize_bailout;
5706                 }
5707                 dxfer_len = sizeof(*pl) + sz;
5708                 data_ptr = calloc(1, dxfer_len);
5709                 if (data_ptr == NULL) {
5710                         warnx("cannot allocate parameter list buffer");
5711                         error = 1;
5712                         goto scsisanitize_bailout;
5713                 }
5714
5715                 amt = read(fd, data_ptr + sizeof(*pl), sz);
5716                 if (amt < 0) {
5717                         warn("cannot read pattern file");
5718                         error = 1;
5719                         goto scsisanitize_bailout;
5720                 } else if (amt != sz) {
5721                         warnx("short pattern file read");
5722                         error = 1;
5723                         goto scsisanitize_bailout;
5724                 }
5725
5726                 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
5727                 if (passes == 0)
5728                         pl->byte1 = 1;
5729                 else
5730                         pl->byte1 = passes;
5731                 if (invert != 0)
5732                         pl->byte1 |= SSZPL_INVERT;
5733                 scsi_ulto2b(sz, pl->length);
5734         } else {
5735                 const char *arg;
5736
5737                 if (passes != 0)
5738                         arg = "-c";
5739                 else if (invert != 0)
5740                         arg = "-I";
5741                 else if (pattern != NULL)
5742                         arg = "-P";
5743                 else
5744                         arg = NULL;
5745                 if (arg != NULL) {
5746                         warnx("%s argument only valid with overwrite "
5747                               "operation", arg);
5748                         error = 1;
5749                         goto scsisanitize_bailout;
5750                 }
5751         }
5752
5753         if (quiet == 0) {
5754                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5755                         "following device:\n");
5756
5757                 error = scsidoinquiry(device, argc, argv, combinedopt,
5758                                       retry_count, timeout);
5759
5760                 if (error != 0) {
5761                         warnx("scsisanitize: error sending inquiry");
5762                         goto scsisanitize_bailout;
5763                 }
5764         }
5765
5766         if (ycount == 0) {
5767                 if (!get_confirmation()) {
5768                         error = 1;
5769                         goto scsisanitize_bailout;
5770                 }
5771         }
5772
5773         if (timeout != 0)
5774                 use_timeout = timeout;
5775
5776         if (quiet == 0) {
5777                 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
5778                         use_timeout / 1000);
5779         }
5780
5781         /*
5782          * If the user hasn't disabled questions and didn't specify a
5783          * timeout on the command line, ask them if they want the current
5784          * timeout.
5785          */
5786         if ((ycount == 0)
5787          && (timeout == 0)) {
5788                 char str[1024];
5789                 int new_timeout = 0;
5790
5791                 fprintf(stdout, "Enter new timeout in seconds or press\n"
5792                         "return to keep the current timeout [%d] ",
5793                         use_timeout / 1000);
5794
5795                 if (fgets(str, sizeof(str), stdin) != NULL) {
5796                         if (str[0] != '\0')
5797                                 new_timeout = atoi(str);
5798                 }
5799
5800                 if (new_timeout != 0) {
5801                         use_timeout = new_timeout * 1000;
5802                         fprintf(stdout, "Using new timeout value %d\n",
5803                                 use_timeout / 1000);
5804                 }
5805         }
5806
5807         byte2 = action;
5808         if (ause != 0)
5809                 byte2 |= SSZ_UNRESTRICTED_EXIT;
5810         if (immediate != 0)
5811                 byte2 |= SSZ_IMMED;
5812
5813         scsi_sanitize(&ccb->csio,
5814                       /* retries */ retry_count,
5815                       /* cbfcnp */ NULL,
5816                       /* tag_action */ MSG_SIMPLE_Q_TAG,
5817                       /* byte2 */ byte2,
5818                       /* control */ 0,
5819                       /* data_ptr */ data_ptr,
5820                       /* dxfer_len */ dxfer_len,
5821                       /* sense_len */ SSD_FULL_SIZE,
5822                       /* timeout */ use_timeout);
5823
5824         /* Disable freezing the device queue */
5825         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5826
5827         if (arglist & CAM_ARG_ERR_RECOVER)
5828                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5829
5830         if (((retval = cam_send_ccb(device, ccb)) < 0)
5831          || ((immediate == 0)
5832            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5833                 const char errstr[] = "error sending sanitize command";
5834
5835                 if (retval < 0)
5836                         warn(errstr);
5837                 else
5838                         warnx(errstr);
5839
5840                 if (arglist & CAM_ARG_VERBOSE) {
5841                         cam_error_print(device, ccb, CAM_ESF_ALL,
5842                                         CAM_EPF_ALL, stderr);
5843                 }
5844                 error = 1;
5845                 goto scsisanitize_bailout;
5846         }
5847
5848         /*
5849          * If we ran in non-immediate mode, we already checked for errors
5850          * above and printed out any necessary information.  If we're in
5851          * immediate mode, we need to loop through and get status
5852          * information periodically.
5853          */
5854         if (immediate == 0) {
5855                 if (quiet == 0) {
5856                         fprintf(stdout, "Sanitize Complete\n");
5857                 }
5858                 goto scsisanitize_bailout;
5859         }
5860
5861 doreport:
5862         do {
5863                 cam_status status;
5864
5865                 bzero(&(&ccb->ccb_h)[1],
5866                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5867
5868                 /*
5869                  * There's really no need to do error recovery or
5870                  * retries here, since we're just going to sit in a
5871                  * loop and wait for the device to finish sanitizing.
5872                  */
5873                 scsi_test_unit_ready(&ccb->csio,
5874                                      /* retries */ 0,
5875                                      /* cbfcnp */ NULL,
5876                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
5877                                      /* sense_len */ SSD_FULL_SIZE,
5878                                      /* timeout */ 5000);
5879
5880                 /* Disable freezing the device queue */
5881                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5882
5883                 retval = cam_send_ccb(device, ccb);
5884
5885                 /*
5886                  * If we get an error from the ioctl, bail out.  SCSI
5887                  * errors are expected.
5888                  */
5889                 if (retval < 0) {
5890                         warn("error sending CAMIOCOMMAND ioctl");
5891                         if (arglist & CAM_ARG_VERBOSE) {
5892                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5893                                                 CAM_EPF_ALL, stderr);
5894                         }
5895                         error = 1;
5896                         goto scsisanitize_bailout;
5897                 }
5898
5899                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5900
5901                 if ((status != CAM_REQ_CMP)
5902                  && (status == CAM_SCSI_STATUS_ERROR)
5903                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5904                         struct scsi_sense_data *sense;
5905                         int error_code, sense_key, asc, ascq;
5906
5907                         sense = &ccb->csio.sense_data;
5908                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
5909                             ccb->csio.sense_resid, &error_code, &sense_key,
5910                             &asc, &ascq, /*show_errors*/ 1);
5911
5912                         /*
5913                          * According to the SCSI-3 spec, a drive that is in the
5914                          * middle of a sanitize should return NOT READY with an
5915                          * ASC of "logical unit not ready, sanitize in
5916                          * progress". The sense key specific bytes will then
5917                          * be a progress indicator.
5918                          */
5919                         if ((sense_key == SSD_KEY_NOT_READY)
5920                          && (asc == 0x04) && (ascq == 0x1b)) {
5921                                 uint8_t sks[3];
5922
5923                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5924                                      ccb->csio.sense_resid, sks) == 0)
5925                                  && (quiet == 0)) {
5926                                         int val;
5927                                         u_int64_t percentage;
5928
5929                                         val = scsi_2btoul(&sks[1]);
5930                                         percentage = 10000 * val;
5931
5932                                         fprintf(stdout,
5933                                                 "\rSanitizing:  %ju.%02u %% "
5934                                                 "(%d/%d) done",
5935                                                 (uintmax_t)(percentage /
5936                                                 (0x10000 * 100)),
5937                                                 (unsigned)((percentage /
5938                                                 0x10000) % 100),
5939                                                 val, 0x10000);
5940                                         fflush(stdout);
5941                                 } else if ((quiet == 0)
5942                                         && (++num_warnings <= 1)) {
5943                                         warnx("Unexpected SCSI Sense Key "
5944                                               "Specific value returned "
5945                                               "during sanitize:");
5946                                         scsi_sense_print(device, &ccb->csio,
5947                                                          stderr);
5948                                         warnx("Unable to print status "
5949                                               "information, but sanitze will "
5950                                               "proceed.");
5951                                         warnx("will exit when sanitize is "
5952                                               "complete");
5953                                 }
5954                                 sleep(1);
5955                         } else {
5956                                 warnx("Unexpected SCSI error during sanitize");
5957                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5958                                                 CAM_EPF_ALL, stderr);
5959                                 error = 1;
5960                                 goto scsisanitize_bailout;
5961                         }
5962
5963                 } else if (status != CAM_REQ_CMP) {
5964                         warnx("Unexpected CAM status %#x", status);
5965                         if (arglist & CAM_ARG_VERBOSE)
5966                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5967                                                 CAM_EPF_ALL, stderr);
5968                         error = 1;
5969                         goto scsisanitize_bailout;
5970                 }
5971         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5972
5973         if (quiet == 0)
5974                 fprintf(stdout, "\nSanitize Complete\n");
5975
5976 scsisanitize_bailout:
5977         if (fd >= 0)
5978                 close(fd);
5979         if (data_ptr != NULL)
5980                 free(data_ptr);
5981         cam_freeccb(ccb);
5982
5983         return(error);
5984 }
5985
5986 static int
5987 scsireportluns(struct cam_device *device, int argc, char **argv,
5988                char *combinedopt, int retry_count, int timeout)
5989 {
5990         union ccb *ccb;
5991         int c, countonly, lunsonly;
5992         struct scsi_report_luns_data *lundata;
5993         int alloc_len;
5994         uint8_t report_type;
5995         uint32_t list_len, i, j;
5996         int retval;
5997
5998         retval = 0;
5999         lundata = NULL;
6000         report_type = RPL_REPORT_DEFAULT;
6001         ccb = cam_getccb(device);
6002
6003         if (ccb == NULL) {
6004                 warnx("%s: error allocating ccb", __func__);
6005                 return (1);
6006         }
6007
6008         bzero(&(&ccb->ccb_h)[1],
6009               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6010
6011         countonly = 0;
6012         lunsonly = 0;
6013
6014         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6015                 switch (c) {
6016                 case 'c':
6017                         countonly++;
6018                         break;
6019                 case 'l':
6020                         lunsonly++;
6021                         break;
6022                 case 'r':
6023                         if (strcasecmp(optarg, "default") == 0)
6024                                 report_type = RPL_REPORT_DEFAULT;
6025                         else if (strcasecmp(optarg, "wellknown") == 0)
6026                                 report_type = RPL_REPORT_WELLKNOWN;
6027                         else if (strcasecmp(optarg, "all") == 0)
6028                                 report_type = RPL_REPORT_ALL;
6029                         else {
6030                                 warnx("%s: invalid report type \"%s\"",
6031                                       __func__, optarg);
6032                                 retval = 1;
6033                                 goto bailout;
6034                         }
6035                         break;
6036                 default:
6037                         break;
6038                 }
6039         }
6040
6041         if ((countonly != 0)
6042          && (lunsonly != 0)) {
6043                 warnx("%s: you can only specify one of -c or -l", __func__);
6044                 retval = 1;
6045                 goto bailout;
6046         }
6047         /*
6048          * According to SPC-4, the allocation length must be at least 16
6049          * bytes -- enough for the header and one LUN.
6050          */
6051         alloc_len = sizeof(*lundata) + 8;
6052
6053 retry:
6054
6055         lundata = malloc(alloc_len);
6056
6057         if (lundata == NULL) {
6058                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6059                 retval = 1;
6060                 goto bailout;
6061         }
6062
6063         scsi_report_luns(&ccb->csio,
6064                          /*retries*/ retry_count,
6065                          /*cbfcnp*/ NULL,
6066                          /*tag_action*/ MSG_SIMPLE_Q_TAG,
6067                          /*select_report*/ report_type,
6068                          /*rpl_buf*/ lundata,
6069                          /*alloc_len*/ alloc_len,
6070                          /*sense_len*/ SSD_FULL_SIZE,
6071                          /*timeout*/ timeout ? timeout : 5000);
6072
6073         /* Disable freezing the device queue */
6074         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6075
6076         if (arglist & CAM_ARG_ERR_RECOVER)
6077                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6078
6079         if (cam_send_ccb(device, ccb) < 0) {
6080                 warn("error sending REPORT LUNS command");
6081
6082                 if (arglist & CAM_ARG_VERBOSE)
6083                         cam_error_print(device, ccb, CAM_ESF_ALL,
6084                                         CAM_EPF_ALL, stderr);
6085
6086                 retval = 1;
6087                 goto bailout;
6088         }
6089
6090         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6091                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6092                 retval = 1;
6093                 goto bailout;
6094         }
6095
6096
6097         list_len = scsi_4btoul(lundata->length);
6098
6099         /*
6100          * If we need to list the LUNs, and our allocation
6101          * length was too short, reallocate and retry.
6102          */
6103         if ((countonly == 0)
6104          && (list_len > (alloc_len - sizeof(*lundata)))) {
6105                 alloc_len = list_len + sizeof(*lundata);
6106                 free(lundata);
6107                 goto retry;
6108         }
6109
6110         if (lunsonly == 0)
6111                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6112                         ((list_len / 8) > 1) ? "s" : "");
6113
6114         if (countonly != 0)
6115                 goto bailout;
6116
6117         for (i = 0; i < (list_len / 8); i++) {
6118                 int no_more;
6119
6120                 no_more = 0;
6121                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6122                         if (j != 0)
6123                                 fprintf(stdout, ",");
6124                         switch (lundata->luns[i].lundata[j] &
6125                                 RPL_LUNDATA_ATYP_MASK) {
6126                         case RPL_LUNDATA_ATYP_PERIPH:
6127                                 if ((lundata->luns[i].lundata[j] &
6128                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6129                                         fprintf(stdout, "%d:",
6130                                                 lundata->luns[i].lundata[j] &
6131                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
6132                                 else if ((j == 0)
6133                                       && ((lundata->luns[i].lundata[j+2] &
6134                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6135                                         no_more = 1;
6136
6137                                 fprintf(stdout, "%d",
6138                                         lundata->luns[i].lundata[j+1]);
6139                                 break;
6140                         case RPL_LUNDATA_ATYP_FLAT: {
6141                                 uint8_t tmplun[2];
6142                                 tmplun[0] = lundata->luns[i].lundata[j] &
6143                                         RPL_LUNDATA_FLAT_LUN_MASK;
6144                                 tmplun[1] = lundata->luns[i].lundata[j+1];
6145
6146                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6147                                 no_more = 1;
6148                                 break;
6149                         }
6150                         case RPL_LUNDATA_ATYP_LUN:
6151                                 fprintf(stdout, "%d:%d:%d",
6152                                         (lundata->luns[i].lundata[j+1] &
6153                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6154                                         lundata->luns[i].lundata[j] &
6155                                         RPL_LUNDATA_LUN_TARG_MASK,
6156                                         lundata->luns[i].lundata[j+1] &
6157                                         RPL_LUNDATA_LUN_LUN_MASK);
6158                                 break;
6159                         case RPL_LUNDATA_ATYP_EXTLUN: {
6160                                 int field_len_code, eam_code;
6161
6162                                 eam_code = lundata->luns[i].lundata[j] &
6163                                         RPL_LUNDATA_EXT_EAM_MASK;
6164                                 field_len_code = (lundata->luns[i].lundata[j] &
6165                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6166
6167                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6168                                  && (field_len_code == 0x00)) {
6169                                         fprintf(stdout, "%d",
6170                                                 lundata->luns[i].lundata[j+1]);
6171                                 } else if ((eam_code ==
6172                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6173                                         && (field_len_code == 0x03)) {
6174                                         uint8_t tmp_lun[8];
6175
6176                                         /*
6177                                          * This format takes up all 8 bytes.
6178                                          * If we aren't starting at offset 0,
6179                                          * that's a bug.
6180                                          */
6181                                         if (j != 0) {
6182                                                 fprintf(stdout, "Invalid "
6183                                                         "offset %d for "
6184                                                         "Extended LUN not "
6185                                                         "specified format", j);
6186                                                 no_more = 1;
6187                                                 break;
6188                                         }
6189                                         bzero(tmp_lun, sizeof(tmp_lun));
6190                                         bcopy(&lundata->luns[i].lundata[j+1],
6191                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
6192                                         fprintf(stdout, "%#jx",
6193                                                (intmax_t)scsi_8btou64(tmp_lun));
6194                                         no_more = 1;
6195                                 } else {
6196                                         fprintf(stderr, "Unknown Extended LUN"
6197                                                 "Address method %#x, length "
6198                                                 "code %#x", eam_code,
6199                                                 field_len_code);
6200                                         no_more = 1;
6201                                 }
6202                                 break;
6203                         }
6204                         default:
6205                                 fprintf(stderr, "Unknown LUN address method "
6206                                         "%#x\n", lundata->luns[i].lundata[0] &
6207                                         RPL_LUNDATA_ATYP_MASK);
6208                                 break;
6209                         }
6210                         /*
6211                          * For the flat addressing method, there are no
6212                          * other levels after it.
6213                          */
6214                         if (no_more != 0)
6215                                 break;
6216                 }
6217                 fprintf(stdout, "\n");
6218         }
6219
6220 bailout:
6221
6222         cam_freeccb(ccb);
6223
6224         free(lundata);
6225
6226         return (retval);
6227 }
6228
6229 static int
6230 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6231                  char *combinedopt, int retry_count, int timeout)
6232 {
6233         union ccb *ccb;
6234         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6235         struct scsi_read_capacity_data rcap;
6236         struct scsi_read_capacity_data_long rcaplong;
6237         uint64_t maxsector;
6238         uint32_t block_len;
6239         int retval;
6240         int c;
6241
6242         blocksizeonly = 0;
6243         humanize = 0;
6244         numblocks = 0;
6245         quiet = 0;
6246         sizeonly = 0;
6247         baseten = 0;
6248         retval = 0;
6249
6250         ccb = cam_getccb(device);
6251
6252         if (ccb == NULL) {
6253                 warnx("%s: error allocating ccb", __func__);
6254                 return (1);
6255         }
6256
6257         bzero(&(&ccb->ccb_h)[1],
6258               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6259
6260         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6261                 switch (c) {
6262                 case 'b':
6263                         blocksizeonly++;
6264                         break;
6265                 case 'h':
6266                         humanize++;
6267                         baseten = 0;
6268                         break;
6269                 case 'H':
6270                         humanize++;
6271                         baseten++;
6272                         break;
6273                 case 'N':
6274                         numblocks++;
6275                         break;
6276                 case 'q':
6277                         quiet++;
6278                         break;
6279                 case 's':
6280                         sizeonly++;
6281                         break;
6282                 default:
6283                         break;
6284                 }
6285         }
6286
6287         if ((blocksizeonly != 0)
6288          && (numblocks != 0)) {
6289                 warnx("%s: you can only specify one of -b or -N", __func__);
6290                 retval = 1;
6291                 goto bailout;
6292         }
6293
6294         if ((blocksizeonly != 0)
6295          && (sizeonly != 0)) {
6296                 warnx("%s: you can only specify one of -b or -s", __func__);
6297                 retval = 1;
6298                 goto bailout;
6299         }
6300
6301         if ((humanize != 0)
6302          && (quiet != 0)) {
6303                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6304                 retval = 1;
6305                 goto bailout;
6306         }
6307
6308         if ((humanize != 0)
6309          && (blocksizeonly != 0)) {
6310                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6311                 retval = 1;
6312                 goto bailout;
6313         }
6314
6315         scsi_read_capacity(&ccb->csio,
6316                            /*retries*/ retry_count,
6317                            /*cbfcnp*/ NULL,
6318                            /*tag_action*/ MSG_SIMPLE_Q_TAG,
6319                            &rcap,
6320                            SSD_FULL_SIZE,
6321                            /*timeout*/ timeout ? timeout : 5000);
6322
6323         /* Disable freezing the device queue */
6324         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6325
6326         if (arglist & CAM_ARG_ERR_RECOVER)
6327                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6328
6329         if (cam_send_ccb(device, ccb) < 0) {
6330                 warn("error sending READ CAPACITY command");
6331
6332                 if (arglist & CAM_ARG_VERBOSE)
6333                         cam_error_print(device, ccb, CAM_ESF_ALL,
6334                                         CAM_EPF_ALL, stderr);
6335
6336                 retval = 1;
6337                 goto bailout;
6338         }
6339
6340         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6341                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6342                 retval = 1;
6343                 goto bailout;
6344         }
6345
6346         maxsector = scsi_4btoul(rcap.addr);
6347         block_len = scsi_4btoul(rcap.length);
6348
6349         /*
6350          * A last block of 2^32-1 means that the true capacity is over 2TB,
6351          * and we need to issue the long READ CAPACITY to get the real
6352          * capacity.  Otherwise, we're all set.
6353          */
6354         if (maxsector != 0xffffffff)
6355                 goto do_print;
6356
6357         scsi_read_capacity_16(&ccb->csio,
6358                               /*retries*/ retry_count,
6359                               /*cbfcnp*/ NULL,
6360                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
6361                               /*lba*/ 0,
6362                               /*reladdr*/ 0,
6363                               /*pmi*/ 0,
6364                               /*rcap_buf*/ (uint8_t *)&rcaplong,
6365                               /*rcap_buf_len*/ sizeof(rcaplong),
6366                               /*sense_len*/ SSD_FULL_SIZE,
6367                               /*timeout*/ timeout ? timeout : 5000);
6368
6369         /* Disable freezing the device queue */
6370         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6371
6372         if (arglist & CAM_ARG_ERR_RECOVER)
6373                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6374
6375         if (cam_send_ccb(device, ccb) < 0) {
6376                 warn("error sending READ CAPACITY (16) command");
6377
6378                 if (arglist & CAM_ARG_VERBOSE)
6379                         cam_error_print(device, ccb, CAM_ESF_ALL,
6380                                         CAM_EPF_ALL, stderr);
6381
6382                 retval = 1;
6383                 goto bailout;
6384         }
6385
6386         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6387                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6388                 retval = 1;
6389                 goto bailout;
6390         }
6391
6392         maxsector = scsi_8btou64(rcaplong.addr);
6393         block_len = scsi_4btoul(rcaplong.length);
6394
6395 do_print:
6396         if (blocksizeonly == 0) {
6397                 /*
6398                  * Humanize implies !quiet, and also implies numblocks.
6399                  */
6400                 if (humanize != 0) {
6401                         char tmpstr[6];
6402                         int64_t tmpbytes;
6403                         int ret;
6404
6405                         tmpbytes = (maxsector + 1) * block_len;
6406                         ret = humanize_number(tmpstr, sizeof(tmpstr),
6407                                               tmpbytes, "", HN_AUTOSCALE,
6408                                               HN_B | HN_DECIMAL |
6409                                               ((baseten != 0) ?
6410                                               HN_DIVISOR_1000 : 0));
6411                         if (ret == -1) {
6412                                 warnx("%s: humanize_number failed!", __func__);
6413                                 retval = 1;
6414                                 goto bailout;
6415                         }
6416                         fprintf(stdout, "Device Size: %s%s", tmpstr,
6417                                 (sizeonly == 0) ?  ", " : "\n");
6418                 } else if (numblocks != 0) {
6419                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6420                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
6421                                 (sizeonly == 0) ? ", " : "\n");
6422                 } else {
6423                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6424                                 "Last Block: " : "", (uintmax_t)maxsector,
6425                                 (sizeonly == 0) ? ", " : "\n");
6426                 }
6427         }
6428         if (sizeonly == 0)
6429                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6430                         "Block Length: " : "", block_len, (quiet == 0) ?
6431                         " bytes" : "");
6432 bailout:
6433         cam_freeccb(ccb);
6434
6435         return (retval);
6436 }
6437
6438 static int
6439 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6440        int retry_count, int timeout)
6441 {
6442         int c, error = 0;
6443         union ccb *ccb;
6444         uint8_t *smp_request = NULL, *smp_response = NULL;
6445         int request_size = 0, response_size = 0;
6446         int fd_request = 0, fd_response = 0;
6447         char *datastr = NULL;
6448         struct get_hook hook;
6449         int retval;
6450         int flags = 0;
6451
6452         /*
6453          * Note that at the moment we don't support sending SMP CCBs to
6454          * devices that aren't probed by CAM.
6455          */
6456         ccb = cam_getccb(device);
6457         if (ccb == NULL) {
6458                 warnx("%s: error allocating CCB", __func__);
6459                 return (1);
6460         }
6461
6462         bzero(&(&ccb->ccb_h)[1],
6463               sizeof(union ccb) - sizeof(struct ccb_hdr));
6464
6465         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6466                 switch (c) {
6467                 case 'R':
6468                         arglist |= CAM_ARG_CMD_IN;
6469                         response_size = strtol(optarg, NULL, 0);
6470                         if (response_size <= 0) {
6471                                 warnx("invalid number of response bytes %d",
6472                                       response_size);
6473                                 error = 1;
6474                                 goto smpcmd_bailout;
6475                         }
6476                         hook.argc = argc - optind;
6477                         hook.argv = argv + optind;
6478                         hook.got = 0;
6479                         optind++;
6480                         datastr = cget(&hook, NULL);
6481                         /*
6482                          * If the user supplied "-" instead of a format, he
6483                          * wants the data to be written to stdout.
6484                          */
6485                         if ((datastr != NULL)
6486                          && (datastr[0] == '-'))
6487                                 fd_response = 1;
6488
6489                         smp_response = (u_int8_t *)malloc(response_size);
6490                         if (smp_response == NULL) {
6491                                 warn("can't malloc memory for SMP response");
6492                                 error = 1;
6493                                 goto smpcmd_bailout;
6494                         }
6495                         break;
6496                 case 'r':
6497                         arglist |= CAM_ARG_CMD_OUT;
6498                         request_size = strtol(optarg, NULL, 0);
6499                         if (request_size <= 0) {
6500                                 warnx("invalid number of request bytes %d",
6501                                       request_size);
6502                                 error = 1;
6503                                 goto smpcmd_bailout;
6504                         }
6505                         hook.argc = argc - optind;
6506                         hook.argv = argv + optind;
6507                         hook.got = 0;
6508                         datastr = cget(&hook, NULL);
6509                         smp_request = (u_int8_t *)malloc(request_size);
6510                         if (smp_request == NULL) {
6511                                 warn("can't malloc memory for SMP request");
6512                                 error = 1;
6513                                 goto smpcmd_bailout;
6514                         }
6515                         bzero(smp_request, request_size);
6516                         /*
6517                          * If the user supplied "-" instead of a format, he
6518                          * wants the data to be read from stdin.
6519                          */
6520                         if ((datastr != NULL)
6521                          && (datastr[0] == '-'))
6522                                 fd_request = 1;
6523                         else
6524                                 buff_encode_visit(smp_request, request_size,
6525                                                   datastr,
6526                                                   iget, &hook);
6527                         optind += hook.got;
6528                         break;
6529                 default:
6530                         break;
6531                 }
6532         }
6533
6534         /*
6535          * If fd_data is set, and we're writing to the device, we need to
6536          * read the data the user wants written from stdin.
6537          */
6538         if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6539                 ssize_t amt_read;
6540                 int amt_to_read = request_size;
6541                 u_int8_t *buf_ptr = smp_request;
6542
6543                 for (amt_read = 0; amt_to_read > 0;
6544                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6545                         if (amt_read == -1) {
6546                                 warn("error reading data from stdin");
6547                                 error = 1;
6548                                 goto smpcmd_bailout;
6549                         }
6550                         amt_to_read -= amt_read;
6551                         buf_ptr += amt_read;
6552                 }
6553         }
6554
6555         if (((arglist & CAM_ARG_CMD_IN) == 0)
6556          || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6557                 warnx("%s: need both the request (-r) and response (-R) "
6558                       "arguments", __func__);
6559                 error = 1;
6560                 goto smpcmd_bailout;
6561         }
6562
6563         flags |= CAM_DEV_QFRZDIS;
6564
6565         cam_fill_smpio(&ccb->smpio,
6566                        /*retries*/ retry_count,
6567                        /*cbfcnp*/ NULL,
6568                        /*flags*/ flags,
6569                        /*smp_request*/ smp_request,
6570                        /*smp_request_len*/ request_size,
6571                        /*smp_response*/ smp_response,
6572                        /*smp_response_len*/ response_size,
6573                        /*timeout*/ timeout ? timeout : 5000);
6574
6575         ccb->smpio.flags = SMP_FLAG_NONE;
6576
6577         if (((retval = cam_send_ccb(device, ccb)) < 0)
6578          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6579                 const char warnstr[] = "error sending command";
6580
6581                 if (retval < 0)
6582                         warn(warnstr);
6583                 else
6584                         warnx(warnstr);
6585
6586                 if (arglist & CAM_ARG_VERBOSE) {
6587                         cam_error_print(device, ccb, CAM_ESF_ALL,
6588                                         CAM_EPF_ALL, stderr);
6589                 }
6590         }
6591
6592         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6593          && (response_size > 0)) {
6594                 if (fd_response == 0) {
6595                         buff_decode_visit(smp_response, response_size,
6596                                           datastr, arg_put, NULL);
6597                         fprintf(stdout, "\n");
6598                 } else {
6599                         ssize_t amt_written;
6600                         int amt_to_write = response_size;
6601                         u_int8_t *buf_ptr = smp_response;
6602
6603                         for (amt_written = 0; (amt_to_write > 0) &&
6604                              (amt_written = write(STDOUT_FILENO, buf_ptr,
6605                                                   amt_to_write)) > 0;){
6606                                 amt_to_write -= amt_written;
6607                                 buf_ptr += amt_written;
6608                         }
6609                         if (amt_written == -1) {
6610                                 warn("error writing data to stdout");
6611                                 error = 1;
6612                                 goto smpcmd_bailout;
6613                         } else if ((amt_written == 0)
6614                                 && (amt_to_write > 0)) {
6615                                 warnx("only wrote %u bytes out of %u",
6616                                       response_size - amt_to_write, 
6617                                       response_size);
6618                         }
6619                 }
6620         }
6621 smpcmd_bailout:
6622         if (ccb != NULL)
6623                 cam_freeccb(ccb);
6624
6625         if (smp_request != NULL)
6626                 free(smp_request);
6627
6628         if (smp_response != NULL)
6629                 free(smp_response);
6630
6631         return (error);
6632 }
6633
6634 static int
6635 smpreportgeneral(struct cam_device *device, int argc, char **argv,
6636                  char *combinedopt, int retry_count, int timeout)
6637 {
6638         union ccb *ccb;
6639         struct smp_report_general_request *request = NULL;
6640         struct smp_report_general_response *response = NULL;
6641         struct sbuf *sb = NULL;
6642         int error = 0;
6643         int c, long_response = 0;
6644         int retval;
6645
6646         /*
6647          * Note that at the moment we don't support sending SMP CCBs to
6648          * devices that aren't probed by CAM.
6649          */
6650         ccb = cam_getccb(device);
6651         if (ccb == NULL) {
6652                 warnx("%s: error allocating CCB", __func__);
6653                 return (1);
6654         }
6655
6656         bzero(&(&ccb->ccb_h)[1],
6657               sizeof(union ccb) - sizeof(struct ccb_hdr));
6658
6659         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6660                 switch (c) {
6661                 case 'l':
6662                         long_response = 1;
6663                         break;
6664                 default:
6665                         break;
6666                 }
6667         }
6668         request = malloc(sizeof(*request));
6669         if (request == NULL) {
6670                 warn("%s: unable to allocate %zd bytes", __func__,
6671                      sizeof(*request));
6672                 error = 1;
6673                 goto bailout;
6674         }
6675
6676         response = malloc(sizeof(*response));
6677         if (response == NULL) {
6678                 warn("%s: unable to allocate %zd bytes", __func__,
6679                      sizeof(*response));
6680                 error = 1;
6681                 goto bailout;
6682         }
6683
6684 try_long:
6685         smp_report_general(&ccb->smpio,
6686                            retry_count,
6687                            /*cbfcnp*/ NULL,
6688                            request,
6689                            /*request_len*/ sizeof(*request),
6690                            (uint8_t *)response,
6691                            /*response_len*/ sizeof(*response),
6692                            /*long_response*/ long_response,
6693                            timeout);
6694
6695         if (((retval = cam_send_ccb(device, ccb)) < 0)
6696          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6697                 const char warnstr[] = "error sending command";
6698
6699                 if (retval < 0)
6700                         warn(warnstr);
6701                 else
6702                         warnx(warnstr);
6703
6704                 if (arglist & CAM_ARG_VERBOSE) {
6705                         cam_error_print(device, ccb, CAM_ESF_ALL,
6706                                         CAM_EPF_ALL, stderr);
6707                 }
6708                 error = 1;
6709                 goto bailout;
6710         }
6711
6712         /*
6713          * If the device supports the long response bit, try again and see
6714          * if we can get all of the data.
6715          */
6716         if ((response->long_response & SMP_RG_LONG_RESPONSE)
6717          && (long_response == 0)) {
6718                 ccb->ccb_h.status = CAM_REQ_INPROG;
6719                 bzero(&(&ccb->ccb_h)[1],
6720                       sizeof(union ccb) - sizeof(struct ccb_hdr));
6721                 long_response = 1;
6722                 goto try_long;
6723         }
6724
6725         /*
6726          * XXX KDM detect and decode SMP errors here.
6727          */
6728         sb = sbuf_new_auto();
6729         if (sb == NULL) {
6730                 warnx("%s: error allocating sbuf", __func__);
6731                 goto bailout;
6732         }
6733
6734         smp_report_general_sbuf(response, sizeof(*response), sb);
6735
6736         if (sbuf_finish(sb) != 0) {
6737                 warnx("%s: sbuf_finish", __func__);
6738                 goto bailout;
6739         }
6740
6741         printf("%s", sbuf_data(sb));
6742
6743 bailout:
6744         if (ccb != NULL)
6745                 cam_freeccb(ccb);
6746
6747         if (request != NULL)
6748                 free(request);
6749
6750         if (response != NULL)
6751                 free(response);
6752
6753         if (sb != NULL)
6754                 sbuf_delete(sb);
6755
6756         return (error);
6757 }
6758
6759 static struct camcontrol_opts phy_ops[] = {
6760         {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
6761         {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
6762         {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
6763         {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
6764         {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
6765         {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
6766         {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
6767         {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
6768         {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
6769         {NULL, 0, 0, NULL}
6770 };
6771
6772 static int
6773 smpphycontrol(struct cam_device *device, int argc, char **argv,
6774               char *combinedopt, int retry_count, int timeout)
6775 {
6776         union ccb *ccb;
6777         struct smp_phy_control_request *request = NULL;
6778         struct smp_phy_control_response *response = NULL;
6779         int long_response = 0;
6780         int retval = 0;
6781         int phy = -1;
6782         uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
6783         int phy_op_set = 0;
6784         uint64_t attached_dev_name = 0;
6785         int dev_name_set = 0;
6786         uint32_t min_plr = 0, max_plr = 0;
6787         uint32_t pp_timeout_val = 0;
6788         int slumber_partial = 0;
6789         int set_pp_timeout_val = 0;
6790         int c;
6791
6792         /*
6793          * Note that at the moment we don't support sending SMP CCBs to
6794          * devices that aren't probed by CAM.
6795          */
6796         ccb = cam_getccb(device);
6797         if (ccb == NULL) {
6798                 warnx("%s: error allocating CCB", __func__);
6799                 return (1);
6800         }
6801
6802         bzero(&(&ccb->ccb_h)[1],
6803               sizeof(union ccb) - sizeof(struct ccb_hdr));
6804
6805         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6806                 switch (c) {
6807                 case 'a':
6808                 case 'A':
6809                 case 's':
6810                 case 'S': {
6811                         int enable = -1;
6812
6813                         if (strcasecmp(optarg, "enable") == 0)
6814                                 enable = 1;
6815                         else if (strcasecmp(optarg, "disable") == 0)
6816                                 enable = 2;
6817                         else {
6818                                 warnx("%s: Invalid argument %s", __func__,
6819                                       optarg);
6820                                 retval = 1;
6821                                 goto bailout;
6822                         }
6823                         switch (c) {
6824                         case 's':
6825                                 slumber_partial |= enable <<
6826                                                    SMP_PC_SAS_SLUMBER_SHIFT;
6827                                 break;
6828                         case 'S':
6829                                 slumber_partial |= enable <<
6830                                                    SMP_PC_SAS_PARTIAL_SHIFT;
6831                                 break;
6832                         case 'a':
6833                                 slumber_partial |= enable <<
6834                                                    SMP_PC_SATA_SLUMBER_SHIFT;
6835                                 break;
6836                         case 'A':
6837                                 slumber_partial |= enable <<
6838                                                    SMP_PC_SATA_PARTIAL_SHIFT;
6839                                 break;
6840                         default:
6841                                 warnx("%s: programmer error", __func__);
6842                                 retval = 1;
6843                                 goto bailout;
6844                                 break; /*NOTREACHED*/
6845                         }
6846                         break;
6847                 }
6848                 case 'd':
6849                         attached_dev_name = (uintmax_t)strtoumax(optarg,
6850                                                                  NULL,0);
6851                         dev_name_set = 1;
6852                         break;
6853                 case 'l':
6854                         long_response = 1;
6855                         break;
6856                 case 'm':
6857                         /*
6858                          * We don't do extensive checking here, so this
6859                          * will continue to work when new speeds come out.
6860                          */
6861                         min_plr = strtoul(optarg, NULL, 0);
6862                         if ((min_plr == 0)
6863                          || (min_plr > 0xf)) {
6864                                 warnx("%s: invalid link rate %x",
6865                                       __func__, min_plr);
6866                                 retval = 1;
6867                                 goto bailout;
6868                         }
6869                         break;
6870                 case 'M':
6871                         /*
6872                          * We don't do extensive checking here, so this
6873                          * will continue to work when new speeds come out.
6874                          */
6875                         max_plr = strtoul(optarg, NULL, 0);
6876                         if ((max_plr == 0)
6877                          || (max_plr > 0xf)) {
6878                                 warnx("%s: invalid link rate %x",
6879                                       __func__, max_plr);
6880                                 retval = 1;
6881                                 goto bailout;
6882                         }
6883                         break;
6884                 case 'o': {
6885                         camcontrol_optret optreturn;
6886                         cam_argmask argnums;
6887                         const char *subopt;
6888
6889                         if (phy_op_set != 0) {
6890                                 warnx("%s: only one phy operation argument "
6891                                       "(-o) allowed", __func__);
6892                                 retval = 1;
6893                                 goto bailout;
6894                         }
6895
6896                         phy_op_set = 1;
6897
6898                         /*
6899                          * Allow the user to specify the phy operation
6900                          * numerically, as well as with a name.  This will
6901                          * future-proof it a bit, so options that are added
6902                          * in future specs can be used.
6903                          */
6904                         if (isdigit(optarg[0])) {
6905                                 phy_operation = strtoul(optarg, NULL, 0);
6906                                 if ((phy_operation == 0)
6907                                  || (phy_operation > 0xff)) {
6908                                         warnx("%s: invalid phy operation %#x",
6909                                               __func__, phy_operation);
6910                                         retval = 1;
6911                                         goto bailout;
6912                                 }
6913                                 break;
6914                         }
6915                         optreturn = getoption(phy_ops, optarg, &phy_operation,
6916                                               &argnums, &subopt);
6917
6918                         if (optreturn == CC_OR_AMBIGUOUS) {
6919                                 warnx("%s: ambiguous option %s", __func__,
6920                                       optarg);
6921                                 usage(0);
6922                                 retval = 1;
6923                                 goto bailout;
6924                         } else if (optreturn == CC_OR_NOT_FOUND) {
6925                                 warnx("%s: option %s not found", __func__,
6926                                       optarg);
6927                                 usage(0);
6928                                 retval = 1;
6929                                 goto bailout;
6930                         }
6931                         break;
6932                 }
6933                 case 'p':
6934                         phy = atoi(optarg);
6935                         break;
6936                 case 'T':
6937                         pp_timeout_val = strtoul(optarg, NULL, 0);
6938                         if (pp_timeout_val > 15) {
6939                                 warnx("%s: invalid partial pathway timeout "
6940                                       "value %u, need a value less than 16",
6941                                       __func__, pp_timeout_val);
6942                                 retval = 1;
6943                                 goto bailout;
6944                         }
6945                         set_pp_timeout_val = 1;
6946                         break;
6947                 default:
6948                         break;
6949                 }
6950         }
6951
6952         if (phy == -1) {
6953                 warnx("%s: a PHY (-p phy) argument is required",__func__);
6954                 retval = 1;
6955                 goto bailout;
6956         }
6957
6958         if (((dev_name_set != 0)
6959           && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
6960          || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
6961           && (dev_name_set == 0))) {
6962                 warnx("%s: -d name and -o setdevname arguments both "
6963                       "required to set device name", __func__);
6964                 retval = 1;
6965                 goto bailout;
6966         }
6967
6968         request = malloc(sizeof(*request));
6969         if (request == NULL) {
6970                 warn("%s: unable to allocate %zd bytes", __func__,
6971                      sizeof(*request));
6972                 retval = 1;
6973                 goto bailout;
6974         }
6975
6976         response = malloc(sizeof(*response));
6977         if (response == NULL) {
6978                 warn("%s: unable to allocate %zd bytes", __func__,
6979                      sizeof(*request));
6980                 retval = 1;
6981                 goto bailout;
6982         }
6983
6984         smp_phy_control(&ccb->smpio,
6985                         retry_count,
6986                         /*cbfcnp*/ NULL,
6987                         request,
6988                         sizeof(*request),
6989                         (uint8_t *)response,
6990                         sizeof(*response),
6991                         long_response,
6992                         /*expected_exp_change_count*/ 0,
6993                         phy,
6994                         phy_operation,
6995                         (set_pp_timeout_val != 0) ? 1 : 0,
6996                         attached_dev_name,
6997                         min_plr,
6998                         max_plr,
6999                         slumber_partial,
7000                         pp_timeout_val,
7001                         timeout);
7002
7003         if (((retval = cam_send_ccb(device, ccb)) < 0)
7004          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7005                 const char warnstr[] = "error sending command";
7006
7007                 if (retval < 0)
7008                         warn(warnstr);
7009                 else
7010                         warnx(warnstr);
7011
7012                 if (arglist & CAM_ARG_VERBOSE) {
7013                         /*
7014                          * Use CAM_EPF_NORMAL so we only get one line of
7015                          * SMP command decoding.
7016                          */
7017                         cam_error_print(device, ccb, CAM_ESF_ALL,
7018                                         CAM_EPF_NORMAL, stderr);
7019                 }
7020                 retval = 1;
7021                 goto bailout;
7022         }
7023
7024         /* XXX KDM print out something here for success? */
7025 bailout:
7026         if (ccb != NULL)
7027                 cam_freeccb(ccb);
7028
7029         if (request != NULL)
7030                 free(request);
7031
7032         if (response != NULL)
7033                 free(response);
7034
7035         return (retval);
7036 }
7037
7038 static int
7039 smpmaninfo(struct cam_device *device, int argc, char **argv,
7040            char *combinedopt, int retry_count, int timeout)
7041 {
7042         union ccb *ccb;
7043         struct smp_report_manuf_info_request request;
7044         struct smp_report_manuf_info_response response;
7045         struct sbuf *sb = NULL;
7046         int long_response = 0;
7047         int retval = 0;
7048         int c;
7049
7050         /*
7051          * Note that at the moment we don't support sending SMP CCBs to
7052          * devices that aren't probed by CAM.
7053          */
7054         ccb = cam_getccb(device);
7055         if (ccb == NULL) {
7056                 warnx("%s: error allocating CCB", __func__);
7057                 return (1);
7058         }
7059
7060         bzero(&(&ccb->ccb_h)[1],
7061               sizeof(union ccb) - sizeof(struct ccb_hdr));
7062
7063         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7064                 switch (c) {
7065                 case 'l':
7066                         long_response = 1;
7067                         break;
7068                 default:
7069                         break;
7070                 }
7071         }
7072         bzero(&request, sizeof(request));
7073         bzero(&response, sizeof(response));
7074
7075         smp_report_manuf_info(&ccb->smpio,
7076                               retry_count,
7077                               /*cbfcnp*/ NULL,
7078                               &request,
7079                               sizeof(request),
7080                               (uint8_t *)&response,
7081                               sizeof(response),
7082                               long_response,
7083                               timeout);
7084
7085         if (((retval = cam_send_ccb(device, ccb)) < 0)
7086          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7087                 const char warnstr[] = "error sending command";
7088
7089                 if (retval < 0)
7090                         warn(warnstr);
7091                 else
7092                         warnx(warnstr);
7093
7094                 if (arglist & CAM_ARG_VERBOSE) {
7095                         cam_error_print(device, ccb, CAM_ESF_ALL,
7096                                         CAM_EPF_ALL, stderr);
7097                 }
7098                 retval = 1;
7099                 goto bailout;
7100         }
7101
7102         sb = sbuf_new_auto();
7103         if (sb == NULL) {
7104                 warnx("%s: error allocating sbuf", __func__);
7105                 goto bailout;
7106         }
7107
7108         smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7109
7110         if (sbuf_finish(sb) != 0) {
7111                 warnx("%s: sbuf_finish", __func__);
7112                 goto bailout;
7113         }
7114
7115         printf("%s", sbuf_data(sb));
7116
7117 bailout:
7118
7119         if (ccb != NULL)
7120                 cam_freeccb(ccb);
7121
7122         if (sb != NULL)
7123                 sbuf_delete(sb);
7124
7125         return (retval);
7126 }
7127
7128 static int
7129 getdevid(struct cam_devitem *item)
7130 {
7131         int retval = 0;
7132         union ccb *ccb = NULL;
7133
7134         struct cam_device *dev;
7135
7136         dev = cam_open_btl(item->dev_match.path_id,
7137                            item->dev_match.target_id,
7138                            item->dev_match.target_lun, O_RDWR, NULL);
7139
7140         if (dev == NULL) {
7141                 warnx("%s", cam_errbuf);
7142                 retval = 1;
7143                 goto bailout;
7144         }
7145
7146         item->device_id_len = 0;
7147
7148         ccb = cam_getccb(dev);
7149         if (ccb == NULL) {
7150                 warnx("%s: error allocating CCB", __func__);
7151                 retval = 1;
7152                 goto bailout;
7153         }
7154
7155         bzero(&(&ccb->ccb_h)[1],
7156               sizeof(union ccb) - sizeof(struct ccb_hdr));
7157
7158         /*
7159          * On the first try, we just probe for the size of the data, and
7160          * then allocate that much memory and try again.
7161          */
7162 retry:
7163         ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7164         ccb->ccb_h.flags = CAM_DIR_IN;
7165         ccb->cdai.flags = 0;
7166         ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7167         ccb->cdai.bufsiz = item->device_id_len;
7168         if (item->device_id_len != 0)
7169                 ccb->cdai.buf = (uint8_t *)item->device_id;
7170
7171         if (cam_send_ccb(dev, ccb) < 0) {
7172                 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7173                 retval = 1;
7174                 goto bailout;
7175         }
7176
7177         if (ccb->ccb_h.status != CAM_REQ_CMP) {
7178                 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7179                 retval = 1;
7180                 goto bailout;
7181         }
7182
7183         if (item->device_id_len == 0) {
7184                 /*
7185                  * This is our first time through.  Allocate the buffer,
7186                  * and then go back to get the data.
7187                  */
7188                 if (ccb->cdai.provsiz == 0) {
7189                         warnx("%s: invalid .provsiz field returned with "
7190                              "XPT_GDEV_ADVINFO CCB", __func__);
7191                         retval = 1;
7192                         goto bailout;
7193                 }
7194                 item->device_id_len = ccb->cdai.provsiz;
7195                 item->device_id = malloc(item->device_id_len);
7196                 if (item->device_id == NULL) {
7197                         warn("%s: unable to allocate %d bytes", __func__,
7198                              item->device_id_len);
7199                         retval = 1;
7200                         goto bailout;
7201                 }
7202                 ccb->ccb_h.status = CAM_REQ_INPROG;
7203                 goto retry;
7204         }
7205
7206 bailout:
7207         if (dev != NULL)
7208                 cam_close_device(dev);
7209
7210         if (ccb != NULL)
7211                 cam_freeccb(ccb);
7212
7213         return (retval);
7214 }
7215
7216 /*
7217  * XXX KDM merge this code with getdevtree()?
7218  */
7219 static int
7220 buildbusdevlist(struct cam_devlist *devlist)
7221 {
7222         union ccb ccb;
7223         int bufsize, fd = -1;
7224         struct dev_match_pattern *patterns;
7225         struct cam_devitem *item = NULL;
7226         int skip_device = 0;
7227         int retval = 0;
7228
7229         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7230                 warn("couldn't open %s", XPT_DEVICE);
7231                 return(1);
7232         }
7233
7234         bzero(&ccb, sizeof(union ccb));
7235
7236         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7237         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7238         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7239
7240         ccb.ccb_h.func_code = XPT_DEV_MATCH;
7241         bufsize = sizeof(struct dev_match_result) * 100;
7242         ccb.cdm.match_buf_len = bufsize;
7243         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7244         if (ccb.cdm.matches == NULL) {
7245                 warnx("can't malloc memory for matches");
7246                 close(fd);
7247                 return(1);
7248         }
7249         ccb.cdm.num_matches = 0;
7250         ccb.cdm.num_patterns = 2;
7251         ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7252                 ccb.cdm.num_patterns;
7253
7254         patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7255         if (patterns == NULL) {
7256                 warnx("can't malloc memory for patterns");
7257                 retval = 1;
7258                 goto bailout;
7259         }
7260
7261         ccb.cdm.patterns = patterns;
7262         bzero(patterns, ccb.cdm.pattern_buf_len);
7263
7264         patterns[0].type = DEV_MATCH_DEVICE;
7265         patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7266         patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7267         patterns[1].type = DEV_MATCH_PERIPH;
7268         patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7269         patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7270
7271         /*
7272          * We do the ioctl multiple times if necessary, in case there are
7273          * more than 100 nodes in the EDT.
7274          */
7275         do {
7276                 unsigned int i;
7277
7278                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7279                         warn("error sending CAMIOCOMMAND ioctl");
7280                         retval = 1;
7281                         goto bailout;
7282                 }
7283
7284                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7285                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7286                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7287                         warnx("got CAM error %#x, CDM error %d\n",
7288                               ccb.ccb_h.status, ccb.cdm.status);
7289                         retval = 1;
7290                         goto bailout;
7291                 }
7292
7293                 for (i = 0; i < ccb.cdm.num_matches; i++) {
7294                         switch (ccb.cdm.matches[i].type) {
7295                         case DEV_MATCH_DEVICE: {
7296                                 struct device_match_result *dev_result;
7297
7298                                 dev_result = 
7299                                      &ccb.cdm.matches[i].result.device_result;
7300
7301                                 if (dev_result->flags &
7302                                     DEV_RESULT_UNCONFIGURED) {
7303                                         skip_device = 1;
7304                                         break;
7305                                 } else
7306                                         skip_device = 0;
7307
7308                                 item = malloc(sizeof(*item));
7309                                 if (item == NULL) {
7310                                         warn("%s: unable to allocate %zd bytes",
7311                                              __func__, sizeof(*item));
7312                                         retval = 1;
7313                                         goto bailout;
7314                                 }
7315                                 bzero(item, sizeof(*item));
7316                                 bcopy(dev_result, &item->dev_match,
7317                                       sizeof(*dev_result));
7318                                 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7319                                                    links);
7320
7321                                 if (getdevid(item) != 0) {
7322                                         retval = 1;
7323                                         goto bailout;
7324                                 }
7325                                 break;
7326                         }
7327                         case DEV_MATCH_PERIPH: {
7328                                 struct periph_match_result *periph_result;
7329
7330                                 periph_result =
7331                                       &ccb.cdm.matches[i].result.periph_result;
7332
7333                                 if (skip_device != 0)
7334                                         break;
7335                                 item->num_periphs++;
7336                                 item->periph_matches = realloc(
7337                                         item->periph_matches,
7338                                         item->num_periphs *
7339                                         sizeof(struct periph_match_result));
7340                                 if (item->periph_matches == NULL) {
7341                                         warn("%s: error allocating periph "
7342                                              "list", __func__);
7343                                         retval = 1;
7344                                         goto bailout;
7345                                 }
7346                                 bcopy(periph_result, &item->periph_matches[
7347                                       item->num_periphs - 1],
7348                                       sizeof(*periph_result));
7349                                 break;
7350                         }
7351                         default:
7352                                 fprintf(stderr, "%s: unexpected match "
7353                                         "type %d\n", __func__,
7354                                         ccb.cdm.matches[i].type);
7355                                 retval = 1;
7356                                 goto bailout;
7357                                 break; /*NOTREACHED*/
7358                         }
7359                 }
7360         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7361                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7362 bailout:
7363
7364         if (fd != -1)
7365                 close(fd);
7366
7367         free(patterns);
7368
7369         free(ccb.cdm.matches);
7370
7371         if (retval != 0)
7372                 freebusdevlist(devlist);
7373
7374         return (retval);
7375 }
7376
7377 static void
7378 freebusdevlist(struct cam_devlist *devlist)
7379 {
7380         struct cam_devitem *item, *item2;
7381
7382         STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7383                 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7384                               links);
7385                 free(item->device_id);
7386                 free(item->periph_matches);
7387                 free(item);
7388         }
7389 }
7390
7391 static struct cam_devitem *
7392 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7393 {
7394         struct cam_devitem *item;
7395
7396         STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7397                 struct scsi_vpd_id_descriptor *idd;
7398
7399                 /*
7400                  * XXX KDM look for LUN IDs as well?
7401                  */
7402                 idd = scsi_get_devid(item->device_id,
7403                                            item->device_id_len,
7404                                            scsi_devid_is_sas_target);
7405                 if (idd == NULL)
7406                         continue;
7407
7408                 if (scsi_8btou64(idd->identifier) == sasaddr)
7409                         return (item);
7410         }
7411
7412         return (NULL);
7413 }
7414
7415 static int
7416 smpphylist(struct cam_device *device, int argc, char **argv,
7417            char *combinedopt, int retry_count, int timeout)
7418 {
7419         struct smp_report_general_request *rgrequest = NULL;
7420         struct smp_report_general_response *rgresponse = NULL;
7421         struct smp_discover_request *disrequest = NULL;
7422         struct smp_discover_response *disresponse = NULL;
7423         struct cam_devlist devlist;
7424         union ccb *ccb;
7425         int long_response = 0;
7426         int num_phys = 0;
7427         int quiet = 0;
7428         int retval;
7429         int i, c;
7430
7431         /*
7432          * Note that at the moment we don't support sending SMP CCBs to
7433          * devices that aren't probed by CAM.
7434          */
7435         ccb = cam_getccb(device);
7436         if (ccb == NULL) {
7437                 warnx("%s: error allocating CCB", __func__);
7438                 return (1);
7439         }
7440
7441         bzero(&(&ccb->ccb_h)[1],
7442               sizeof(union ccb) - sizeof(struct ccb_hdr));
7443         STAILQ_INIT(&devlist.dev_queue);
7444
7445         rgrequest = malloc(sizeof(*rgrequest));
7446         if (rgrequest == NULL) {
7447                 warn("%s: unable to allocate %zd bytes", __func__,
7448                      sizeof(*rgrequest));
7449                 retval = 1;
7450                 goto bailout;
7451         }
7452
7453         rgresponse = malloc(sizeof(*rgresponse));
7454         if (rgresponse == NULL) {
7455                 warn("%s: unable to allocate %zd bytes", __func__,
7456                      sizeof(*rgresponse));
7457                 retval = 1;
7458                 goto bailout;
7459         }
7460
7461         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7462                 switch (c) {
7463                 case 'l':
7464                         long_response = 1;
7465                         break;
7466                 case 'q':
7467                         quiet = 1;
7468                         break;
7469                 default:
7470                         break;
7471                 }
7472         }
7473
7474         smp_report_general(&ccb->smpio,
7475                            retry_count,
7476                            /*cbfcnp*/ NULL,
7477                            rgrequest,
7478                            /*request_len*/ sizeof(*rgrequest),
7479                            (uint8_t *)rgresponse,
7480                            /*response_len*/ sizeof(*rgresponse),
7481                            /*long_response*/ long_response,
7482                            timeout);
7483
7484         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7485
7486         if (((retval = cam_send_ccb(device, ccb)) < 0)
7487          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7488                 const char warnstr[] = "error sending command";
7489
7490                 if (retval < 0)
7491                         warn(warnstr);
7492                 else
7493                         warnx(warnstr);
7494
7495                 if (arglist & CAM_ARG_VERBOSE) {
7496                         cam_error_print(device, ccb, CAM_ESF_ALL,
7497                                         CAM_EPF_ALL, stderr);
7498                 }
7499                 retval = 1;
7500                 goto bailout;
7501         }
7502
7503         num_phys = rgresponse->num_phys;
7504
7505         if (num_phys == 0) {
7506                 if (quiet == 0)
7507                         fprintf(stdout, "%s: No Phys reported\n", __func__);
7508                 retval = 1;
7509                 goto bailout;
7510         }
7511
7512         devlist.path_id = device->path_id;
7513
7514         retval = buildbusdevlist(&devlist);
7515         if (retval != 0)
7516                 goto bailout;
7517
7518         if (quiet == 0) {
7519                 fprintf(stdout, "%d PHYs:\n", num_phys);
7520                 fprintf(stdout, "PHY  Attached SAS Address\n");
7521         }
7522
7523         disrequest = malloc(sizeof(*disrequest));
7524         if (disrequest == NULL) {
7525                 warn("%s: unable to allocate %zd bytes", __func__,
7526                      sizeof(*disrequest));
7527                 retval = 1;
7528                 goto bailout;
7529         }
7530
7531         disresponse = malloc(sizeof(*disresponse));
7532         if (disresponse == NULL) {
7533                 warn("%s: unable to allocate %zd bytes", __func__,
7534                      sizeof(*disresponse));
7535                 retval = 1;
7536                 goto bailout;
7537         }
7538
7539         for (i = 0; i < num_phys; i++) {
7540                 struct cam_devitem *item;
7541                 struct device_match_result *dev_match;
7542                 char vendor[16], product[48], revision[16];
7543                 char tmpstr[256];
7544                 int j;
7545
7546                 bzero(&(&ccb->ccb_h)[1],
7547                       sizeof(union ccb) - sizeof(struct ccb_hdr));
7548
7549                 ccb->ccb_h.status = CAM_REQ_INPROG;
7550                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7551
7552                 smp_discover(&ccb->smpio,
7553                              retry_count,
7554                              /*cbfcnp*/ NULL,
7555                              disrequest,
7556                              sizeof(*disrequest),
7557                              (uint8_t *)disresponse,
7558                              sizeof(*disresponse),
7559                              long_response,
7560                              /*ignore_zone_group*/ 0,
7561                              /*phy*/ i,
7562                              timeout);
7563
7564                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7565                  || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7566                   && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7567                         const char warnstr[] = "error sending command";
7568
7569                         if (retval < 0)
7570                                 warn(warnstr);
7571                         else
7572                                 warnx(warnstr);
7573
7574                         if (arglist & CAM_ARG_VERBOSE) {
7575                                 cam_error_print(device, ccb, CAM_ESF_ALL,
7576                                                 CAM_EPF_ALL, stderr);
7577                         }
7578                         retval = 1;
7579                         goto bailout;
7580                 }
7581
7582                 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7583                         if (quiet == 0)
7584                                 fprintf(stdout, "%3d  <vacant>\n", i);
7585                         continue;
7586                 }
7587
7588                 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7589                         item = NULL;
7590                 } else {
7591                         item = findsasdevice(&devlist,
7592                             scsi_8btou64(disresponse->attached_sas_address));
7593                 }
7594
7595                 if ((quiet == 0)
7596                  || (item != NULL)) {
7597                         fprintf(stdout, "%3d  0x%016jx", i,
7598                                 (uintmax_t)scsi_8btou64(
7599                                 disresponse->attached_sas_address));
7600                         if (item == NULL) {
7601                                 fprintf(stdout, "\n");
7602                                 continue;
7603                         }
7604                 } else if (quiet != 0)
7605                         continue;
7606
7607                 dev_match = &item->dev_match;
7608
7609                 if (dev_match->protocol == PROTO_SCSI) {
7610                         cam_strvis(vendor, dev_match->inq_data.vendor,
7611                                    sizeof(dev_match->inq_data.vendor),
7612                                    sizeof(vendor));
7613                         cam_strvis(product, dev_match->inq_data.product,
7614                                    sizeof(dev_match->inq_data.product),
7615                                    sizeof(product));
7616                         cam_strvis(revision, dev_match->inq_data.revision,
7617                                    sizeof(dev_match->inq_data.revision),
7618                                    sizeof(revision));
7619                         sprintf(tmpstr, "<%s %s %s>", vendor, product,
7620                                 revision);
7621                 } else if ((dev_match->protocol == PROTO_ATA)
7622                         || (dev_match->protocol == PROTO_SATAPM)) {
7623                         cam_strvis(product, dev_match->ident_data.model,
7624                                    sizeof(dev_match->ident_data.model),
7625                                    sizeof(product));
7626                         cam_strvis(revision, dev_match->ident_data.revision,
7627                                    sizeof(dev_match->ident_data.revision),
7628                                    sizeof(revision));
7629                         sprintf(tmpstr, "<%s %s>", product, revision);
7630                 } else {
7631                         sprintf(tmpstr, "<>");
7632                 }
7633                 fprintf(stdout, "   %-33s ", tmpstr);
7634
7635                 /*
7636                  * If we have 0 periphs, that's a bug...
7637                  */
7638                 if (item->num_periphs == 0) {
7639                         fprintf(stdout, "\n");
7640                         continue;
7641                 }
7642
7643                 fprintf(stdout, "(");
7644                 for (j = 0; j < item->num_periphs; j++) {
7645                         if (j > 0)
7646                                 fprintf(stdout, ",");
7647
7648                         fprintf(stdout, "%s%d",
7649                                 item->periph_matches[j].periph_name,
7650                                 item->periph_matches[j].unit_number);
7651                                 
7652                 }
7653                 fprintf(stdout, ")\n");
7654         }
7655 bailout:
7656         if (ccb != NULL)
7657                 cam_freeccb(ccb);
7658
7659         free(rgrequest);
7660
7661         free(rgresponse);
7662
7663         free(disrequest);
7664
7665         free(disresponse);
7666
7667         freebusdevlist(&devlist);
7668
7669         return (retval);
7670 }
7671
7672 static int
7673 atapm(struct cam_device *device, int argc, char **argv,
7674                  char *combinedopt, int retry_count, int timeout)
7675 {
7676         union ccb *ccb;
7677         int retval = 0;
7678         int t = -1;
7679         int c;
7680         u_char cmd, sc;
7681
7682         ccb = cam_getccb(device);
7683
7684         if (ccb == NULL) {
7685                 warnx("%s: error allocating ccb", __func__);
7686                 return (1);
7687         }
7688
7689         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7690                 switch (c) {
7691                 case 't':
7692                         t = atoi(optarg);
7693                         break;
7694                 default:
7695                         break;
7696                 }
7697         }
7698         if (strcmp(argv[1], "idle") == 0) {
7699                 if (t == -1)
7700                         cmd = ATA_IDLE_IMMEDIATE;
7701                 else
7702                         cmd = ATA_IDLE_CMD;
7703         } else if (strcmp(argv[1], "standby") == 0) {
7704                 if (t == -1)
7705                         cmd = ATA_STANDBY_IMMEDIATE;
7706                 else
7707                         cmd = ATA_STANDBY_CMD;
7708         } else {
7709                 cmd = ATA_SLEEP;
7710                 t = -1;
7711         }
7712
7713         if (t < 0)
7714                 sc = 0;
7715         else if (t <= (240 * 5))
7716                 sc = (t + 4) / 5;
7717         else if (t <= (252 * 5))
7718                 /* special encoding for 21 minutes */
7719                 sc = 252;
7720         else if (t <= (11 * 30 * 60))
7721                 sc = (t - 1) / (30 * 60) + 241;
7722         else
7723                 sc = 253;
7724
7725         cam_fill_ataio(&ccb->ataio,
7726                       retry_count,
7727                       NULL,
7728                       /*flags*/CAM_DIR_NONE,
7729                       MSG_SIMPLE_Q_TAG,
7730                       /*data_ptr*/NULL,
7731                       /*dxfer_len*/0,
7732                       timeout ? timeout : 30 * 1000);
7733         ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
7734
7735         /* Disable freezing the device queue */
7736         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7737
7738         if (arglist & CAM_ARG_ERR_RECOVER)
7739                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7740
7741         if (cam_send_ccb(device, ccb) < 0) {
7742                 warn("error sending command");
7743
7744                 if (arglist & CAM_ARG_VERBOSE)
7745                         cam_error_print(device, ccb, CAM_ESF_ALL,
7746                                         CAM_EPF_ALL, stderr);
7747
7748                 retval = 1;
7749                 goto bailout;
7750         }
7751
7752         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7753                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7754                 retval = 1;
7755                 goto bailout;
7756         }
7757 bailout:
7758         cam_freeccb(ccb);
7759         return (retval);
7760 }
7761
7762 #endif /* MINIMALISTIC */
7763
7764 void
7765 usage(int printlong)
7766 {
7767
7768         fprintf(printlong ? stdout : stderr,
7769 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
7770 "        camcontrol devlist    [-v]\n"
7771 #ifndef MINIMALISTIC
7772 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
7773 "        camcontrol tur        [dev_id][generic args]\n"
7774 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
7775 "        camcontrol identify   [dev_id][generic args] [-v]\n"
7776 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
7777 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
7778 "                              [-q] [-s]\n"
7779 "        camcontrol start      [dev_id][generic args]\n"
7780 "        camcontrol stop       [dev_id][generic args]\n"
7781 "        camcontrol load       [dev_id][generic args]\n"
7782 "        camcontrol eject      [dev_id][generic args]\n"
7783 #endif /* MINIMALISTIC */
7784 "        camcontrol rescan     <all | bus[:target:lun]>\n"
7785 "        camcontrol reset      <all | bus[:target:lun]>\n"
7786 #ifndef MINIMALISTIC
7787 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
7788 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
7789 "                              [-P pagectl][-e | -b][-d]\n"
7790 "        camcontrol cmd        [dev_id][generic args]\n"
7791 "                              <-a cmd [args] | -c cmd [args]>\n"
7792 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
7793 "        camcontrol smpcmd     [dev_id][generic args]\n"
7794 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
7795 "        camcontrol smprg      [dev_id][generic args][-l]\n"
7796 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
7797 "                              [-o operation][-d name][-m rate][-M rate]\n"
7798 "                              [-T pp_timeout][-a enable|disable]\n"
7799 "                              [-A enable|disable][-s enable|disable]\n"
7800 "                              [-S enable|disable]\n"
7801 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
7802 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
7803 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
7804 "                              <all|bus[:target[:lun]]|off>\n"
7805 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
7806 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
7807 "                              [-D <enable|disable>][-M mode][-O offset]\n"
7808 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
7809 "                              [-U][-W bus_width]\n"
7810 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
7811 "        camcontrol sanitize   [dev_id][generic args]\n"
7812 "                              [-a overwrite|block|crypto|exitfailure]\n"
7813 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
7814 "                              [-y]\n"
7815 "        camcontrol idle       [dev_id][generic args][-t time]\n"
7816 "        camcontrol standby    [dev_id][generic args][-t time]\n"
7817 "        camcontrol sleep      [dev_id][generic args]\n"
7818 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
7819 "        camcontrol security   [dev_id][generic args]\n"
7820 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
7821 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
7822 "                              [-U <user|master>] [-y]\n"
7823 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
7824 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
7825 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
7826 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
7827 "                              [-s scope][-S][-T type][-U]\n"
7828 #endif /* MINIMALISTIC */
7829 "        camcontrol help\n");
7830         if (!printlong)
7831                 return;
7832 #ifndef MINIMALISTIC
7833         fprintf(stdout,
7834 "Specify one of the following options:\n"
7835 "devlist     list all CAM devices\n"
7836 "periphlist  list all CAM peripheral drivers attached to a device\n"
7837 "tur         send a test unit ready to the named device\n"
7838 "inquiry     send a SCSI inquiry command to the named device\n"
7839 "identify    send a ATA identify command to the named device\n"
7840 "reportluns  send a SCSI report luns command to the device\n"
7841 "readcap     send a SCSI read capacity command to the device\n"
7842 "start       send a Start Unit command to the device\n"
7843 "stop        send a Stop Unit command to the device\n"
7844 "load        send a Start Unit command to the device with the load bit set\n"
7845 "eject       send a Stop Unit command to the device with the eject bit set\n"
7846 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
7847 "reset       reset all busses, the given bus, or bus:target:lun\n"
7848 "defects     read the defect list of the specified device\n"
7849 "modepage    display or edit (-e) the given mode page\n"
7850 "cmd         send the given SCSI command, may need -i or -o as well\n"
7851 "smpcmd      send the given SMP command, requires -o and -i\n"
7852 "smprg       send the SMP Report General command\n"
7853 "smppc       send the SMP PHY Control command, requires -p\n"
7854 "smpphylist  display phys attached to a SAS expander\n"
7855 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
7856 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
7857 "tags        report or set the number of transaction slots for a device\n"
7858 "negotiate   report or set device negotiation parameters\n"
7859 "format      send the SCSI FORMAT UNIT command to the named device\n"
7860 "sanitize    send the SCSI SANITIZE command to the named device\n"
7861 "idle        send the ATA IDLE command to the named device\n"
7862 "standby     send the ATA STANDBY command to the named device\n"
7863 "sleep       send the ATA SLEEP command to the named device\n"
7864 "fwdownload  program firmware of the named device with the given image\n"
7865 "security    report or send ATA security commands to the named device\n"
7866 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
7867 "help        this message\n"
7868 "Device Identifiers:\n"
7869 "bus:target        specify the bus and target, lun defaults to 0\n"
7870 "bus:target:lun    specify the bus, target and lun\n"
7871 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
7872 "Generic arguments:\n"
7873 "-v                be verbose, print out sense information\n"
7874 "-t timeout        command timeout in seconds, overrides default timeout\n"
7875 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
7876 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
7877 "-E                have the kernel attempt to perform SCSI error recovery\n"
7878 "-C count          specify the SCSI command retry count (needs -E to work)\n"
7879 "modepage arguments:\n"
7880 "-l                list all available mode pages\n"
7881 "-m page           specify the mode page to view or edit\n"
7882 "-e                edit the specified mode page\n"
7883 "-b                force view to binary mode\n"
7884 "-d                disable block descriptors for mode sense\n"
7885 "-P pgctl          page control field 0-3\n"
7886 "defects arguments:\n"
7887 "-f format         specify defect list format (block, bfi or phys)\n"
7888 "-G                get the grown defect list\n"
7889 "-P                get the permanent defect list\n"
7890 "inquiry arguments:\n"
7891 "-D                get the standard inquiry data\n"
7892 "-S                get the serial number\n"
7893 "-R                get the transfer rate, etc.\n"
7894 "reportluns arguments:\n"
7895 "-c                only report a count of available LUNs\n"
7896 "-l                only print out luns, and not a count\n"
7897 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
7898 "readcap arguments\n"
7899 "-b                only report the blocksize\n"
7900 "-h                human readable device size, base 2\n"
7901 "-H                human readable device size, base 10\n"
7902 "-N                print the number of blocks instead of last block\n"
7903 "-q                quiet, print numbers only\n"
7904 "-s                only report the last block/device size\n"
7905 "cmd arguments:\n"
7906 "-c cdb [args]     specify the SCSI CDB\n"
7907 "-i len fmt        specify input data and input data format\n"
7908 "-o len fmt [args] specify output data and output data fmt\n"
7909 "smpcmd arguments:\n"
7910 "-r len fmt [args] specify the SMP command to be sent\n"
7911 "-R len fmt [args] specify SMP response format\n"
7912 "smprg arguments:\n"
7913 "-l                specify the long response format\n"
7914 "smppc arguments:\n"
7915 "-p phy            specify the PHY to operate on\n"
7916 "-l                specify the long request/response format\n"
7917 "-o operation      specify the phy control operation\n"
7918 "-d name           set the attached device name\n"
7919 "-m rate           set the minimum physical link rate\n"
7920 "-M rate           set the maximum physical link rate\n"
7921 "-T pp_timeout     set the partial pathway timeout value\n"
7922 "-a enable|disable enable or disable SATA slumber\n"
7923 "-A enable|disable enable or disable SATA partial phy power\n"
7924 "-s enable|disable enable or disable SAS slumber\n"
7925 "-S enable|disable enable or disable SAS partial phy power\n"
7926 "smpphylist arguments:\n"
7927 "-l                specify the long response format\n"
7928 "-q                only print phys with attached devices\n"
7929 "smpmaninfo arguments:\n"
7930 "-l                specify the long response format\n"
7931 "debug arguments:\n"
7932 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
7933 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
7934 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
7935 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
7936 "tags arguments:\n"
7937 "-N tags           specify the number of tags to use for this device\n"
7938 "-q                be quiet, don't report the number of tags\n"
7939 "-v                report a number of tag-related parameters\n"
7940 "negotiate arguments:\n"
7941 "-a                send a test unit ready after negotiation\n"
7942 "-c                report/set current negotiation settings\n"
7943 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
7944 "-M mode           set ATA mode\n"
7945 "-O offset         set command delay offset\n"
7946 "-q                be quiet, don't report anything\n"
7947 "-R syncrate       synchronization rate in MHz\n"
7948 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
7949 "-U                report/set user negotiation settings\n"
7950 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
7951 "-v                also print a Path Inquiry CCB for the controller\n"
7952 "format arguments:\n"
7953 "-q                be quiet, don't print status messages\n"
7954 "-r                run in report only mode\n"
7955 "-w                don't send immediate format command\n"
7956 "-y                don't ask any questions\n"
7957 "sanitize arguments:\n"
7958 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
7959 "-c passes         overwrite passes to perform (1 to 31)\n"
7960 "-I                invert overwrite pattern after each pass\n"
7961 "-P pattern        path to overwrite pattern file\n"
7962 "-q                be quiet, don't print status messages\n"
7963 "-r                run in report only mode\n"
7964 "-U                run operation in unrestricted completion exit mode\n"
7965 "-w                don't send immediate sanitize command\n"
7966 "-y                don't ask any questions\n"
7967 "idle/standby arguments:\n"
7968 "-t <arg>          number of seconds before respective state.\n"
7969 "fwdownload arguments:\n"
7970 "-f fw_image       path to firmware image file\n"
7971 "-y                don't ask any questions\n"
7972 "-s                run in simulation mode\n"
7973 "-v                print info for every firmware segment sent to device\n"
7974 "security arguments:\n"
7975 "-d pwd            disable security using the given password for the selected\n"
7976 "                  user\n"
7977 "-e pwd            erase the device using the given pwd for the selected user\n"
7978 "-f                freeze the security configuration of the specified device\n"
7979 "-h pwd            enhanced erase the device using the given pwd for the\n"
7980 "                  selected user\n"
7981 "-k pwd            unlock the device using the given pwd for the selected\n"
7982 "                  user\n"
7983 "-l <high|maximum> specifies which security level to set: high or maximum\n"
7984 "-q                be quiet, do not print any status messages\n"
7985 "-s pwd            password the device (enable security) using the given\n"
7986 "                  pwd for the selected user\n"
7987 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
7988 "-U <user|master>  specifies which user to set: user or master\n"
7989 "-y                don't ask any questions\n"
7990 "hpa arguments:\n"
7991 "-f                freeze the HPA configuration of the device\n"
7992 "-l                lock the HPA configuration of the device\n"
7993 "-P                make the HPA max sectors persist\n"
7994 "-p pwd            Set the HPA configuration password required for unlock\n"
7995 "                  calls\n"
7996 "-q                be quiet, do not print any status messages\n"
7997 "-s sectors        configures the maximum user accessible sectors of the\n"
7998 "                  device\n"
7999 "-U pwd            unlock the HPA configuration of the device\n"
8000 "-y                don't ask any questions\n"
8001 "persist arguments:\n"
8002 "-i action         specify read_keys, read_reservation, report_cap, or\n"
8003 "                  read_full_status\n"
8004 "-o action         specify register, register_ignore, reserve, release,\n"
8005 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
8006 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
8007 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8008 "-k key            specify the Reservation Key\n"
8009 "-K sa_key         specify the Service Action Reservation Key\n"
8010 "-p                set the Activate Persist Through Power Loss bit\n"
8011 "-R rtp            specify the Relative Target Port\n"
8012 "-s scope          specify the scope: lun, extent, element or a number\n"
8013 "-S                specify Transport ID for register, requires -I\n"
8014 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8015 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8016 "-U                unregister the current initiator for register_move\n"
8017 );
8018 #endif /* MINIMALISTIC */
8019 }
8020
8021 int
8022 main(int argc, char **argv)
8023 {
8024         int c;
8025         char *device = NULL;
8026         int unit = 0;
8027         struct cam_device *cam_dev = NULL;
8028         int timeout = 0, retry_count = 1;
8029         camcontrol_optret optreturn;
8030         char *tstr;
8031         const char *mainopt = "C:En:t:u:v";
8032         const char *subopt = NULL;
8033         char combinedopt[256];
8034         int error = 0, optstart = 2;
8035         int devopen = 1;
8036 #ifndef MINIMALISTIC
8037         path_id_t bus;
8038         target_id_t target;
8039         lun_id_t lun;
8040 #endif /* MINIMALISTIC */
8041
8042         cmdlist = CAM_CMD_NONE;
8043         arglist = CAM_ARG_NONE;
8044
8045         if (argc < 2) {
8046                 usage(0);
8047                 exit(1);
8048         }
8049
8050         /*
8051          * Get the base option.
8052          */
8053         optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8054
8055         if (optreturn == CC_OR_AMBIGUOUS) {
8056                 warnx("ambiguous option %s", argv[1]);
8057                 usage(0);
8058                 exit(1);
8059         } else if (optreturn == CC_OR_NOT_FOUND) {
8060                 warnx("option %s not found", argv[1]);
8061                 usage(0);
8062                 exit(1);
8063         }
8064
8065         /*
8066          * Ahh, getopt(3) is a pain.
8067          *
8068          * This is a gross hack.  There really aren't many other good
8069          * options (excuse the pun) for parsing options in a situation like
8070          * this.  getopt is kinda braindead, so you end up having to run
8071          * through the options twice, and give each invocation of getopt
8072          * the option string for the other invocation.
8073          *
8074          * You would think that you could just have two groups of options.
8075          * The first group would get parsed by the first invocation of
8076          * getopt, and the second group would get parsed by the second
8077          * invocation of getopt.  It doesn't quite work out that way.  When
8078          * the first invocation of getopt finishes, it leaves optind pointing
8079          * to the argument _after_ the first argument in the second group.
8080          * So when the second invocation of getopt comes around, it doesn't
8081          * recognize the first argument it gets and then bails out.
8082          *
8083          * A nice alternative would be to have a flag for getopt that says
8084          * "just keep parsing arguments even when you encounter an unknown
8085          * argument", but there isn't one.  So there's no real clean way to
8086          * easily parse two sets of arguments without having one invocation
8087          * of getopt know about the other.
8088          *
8089          * Without this hack, the first invocation of getopt would work as
8090          * long as the generic arguments are first, but the second invocation
8091          * (in the subfunction) would fail in one of two ways.  In the case
8092          * where you don't set optreset, it would fail because optind may be
8093          * pointing to the argument after the one it should be pointing at.
8094          * In the case where you do set optreset, and reset optind, it would
8095          * fail because getopt would run into the first set of options, which
8096          * it doesn't understand.
8097          *
8098          * All of this would "sort of" work if you could somehow figure out
8099          * whether optind had been incremented one option too far.  The
8100          * mechanics of that, however, are more daunting than just giving
8101          * both invocations all of the expect options for either invocation.
8102          *
8103          * Needless to say, I wouldn't mind if someone invented a better
8104          * (non-GPL!) command line parsing interface than getopt.  I
8105          * wouldn't mind if someone added more knobs to getopt to make it
8106          * work better.  Who knows, I may talk myself into doing it someday,
8107          * if the standards weenies let me.  As it is, it just leads to
8108          * hackery like this and causes people to avoid it in some cases.
8109          *
8110          * KDM, September 8th, 1998
8111          */
8112         if (subopt != NULL)
8113                 sprintf(combinedopt, "%s%s", mainopt, subopt);
8114         else
8115                 sprintf(combinedopt, "%s", mainopt);
8116
8117         /*
8118          * For these options we do not parse optional device arguments and
8119          * we do not open a passthrough device.
8120          */
8121         if ((cmdlist == CAM_CMD_RESCAN)
8122          || (cmdlist == CAM_CMD_RESET)
8123          || (cmdlist == CAM_CMD_DEVTREE)
8124          || (cmdlist == CAM_CMD_USAGE)
8125          || (cmdlist == CAM_CMD_DEBUG))
8126                 devopen = 0;
8127
8128 #ifndef MINIMALISTIC
8129         if ((devopen == 1)
8130          && (argc > 2 && argv[2][0] != '-')) {
8131                 char name[30];
8132                 int rv;
8133
8134                 if (isdigit(argv[2][0])) {
8135                         /* device specified as bus:target[:lun] */
8136                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
8137                         if (rv < 2)
8138                                 errx(1, "numeric device specification must "
8139                                      "be either bus:target, or "
8140                                      "bus:target:lun");
8141                         /* default to 0 if lun was not specified */
8142                         if ((arglist & CAM_ARG_LUN) == 0) {
8143                                 lun = 0;
8144                                 arglist |= CAM_ARG_LUN;
8145                         }
8146                         optstart++;
8147                 } else {
8148                         if (cam_get_device(argv[2], name, sizeof name, &unit)
8149                             == -1)
8150                                 errx(1, "%s", cam_errbuf);
8151                         device = strdup(name);
8152                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
8153                         optstart++;
8154                 }
8155         }
8156 #endif /* MINIMALISTIC */
8157         /*
8158          * Start getopt processing at argv[2/3], since we've already
8159          * accepted argv[1..2] as the command name, and as a possible
8160          * device name.
8161          */
8162         optind = optstart;
8163
8164         /*
8165          * Now we run through the argument list looking for generic
8166          * options, and ignoring options that possibly belong to
8167          * subfunctions.
8168          */
8169         while ((c = getopt(argc, argv, combinedopt))!= -1){
8170                 switch(c) {
8171                         case 'C':
8172                                 retry_count = strtol(optarg, NULL, 0);
8173                                 if (retry_count < 0)
8174                                         errx(1, "retry count %d is < 0",
8175                                              retry_count);
8176                                 arglist |= CAM_ARG_RETRIES;
8177                                 break;
8178                         case 'E':
8179                                 arglist |= CAM_ARG_ERR_RECOVER;
8180                                 break;
8181                         case 'n':
8182                                 arglist |= CAM_ARG_DEVICE;
8183                                 tstr = optarg;
8184                                 while (isspace(*tstr) && (*tstr != '\0'))
8185                                         tstr++;
8186                                 device = (char *)strdup(tstr);
8187                                 break;
8188                         case 't':
8189                                 timeout = strtol(optarg, NULL, 0);
8190                                 if (timeout < 0)
8191                                         errx(1, "invalid timeout %d", timeout);
8192                                 /* Convert the timeout from seconds to ms */
8193                                 timeout *= 1000;
8194                                 arglist |= CAM_ARG_TIMEOUT;
8195                                 break;
8196                         case 'u':
8197                                 arglist |= CAM_ARG_UNIT;
8198                                 unit = strtol(optarg, NULL, 0);
8199                                 break;
8200                         case 'v':
8201                                 arglist |= CAM_ARG_VERBOSE;
8202                                 break;
8203                         default:
8204                                 break;
8205                 }
8206         }
8207
8208 #ifndef MINIMALISTIC
8209         /*
8210          * For most commands we'll want to open the passthrough device
8211          * associated with the specified device.  In the case of the rescan
8212          * commands, we don't use a passthrough device at all, just the
8213          * transport layer device.
8214          */
8215         if (devopen == 1) {
8216                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
8217                  && (((arglist & CAM_ARG_DEVICE) == 0)
8218                   || ((arglist & CAM_ARG_UNIT) == 0))) {
8219                         errx(1, "subcommand \"%s\" requires a valid device "
8220                              "identifier", argv[1]);
8221                 }
8222
8223                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
8224                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
8225                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
8226                      == NULL)
8227                         errx(1,"%s", cam_errbuf);
8228         }
8229 #endif /* MINIMALISTIC */
8230
8231         /*
8232          * Reset optind to 2, and reset getopt, so these routines can parse
8233          * the arguments again.
8234          */
8235         optind = optstart;
8236         optreset = 1;
8237
8238         switch(cmdlist) {
8239 #ifndef MINIMALISTIC
8240                 case CAM_CMD_DEVLIST:
8241                         error = getdevlist(cam_dev);
8242                         break;
8243                 case CAM_CMD_HPA:
8244                         error = atahpa(cam_dev, retry_count, timeout,
8245                                        argc, argv, combinedopt);
8246                         break;
8247 #endif /* MINIMALISTIC */
8248                 case CAM_CMD_DEVTREE:
8249                         error = getdevtree(argc, argv, combinedopt);
8250                         break;
8251 #ifndef MINIMALISTIC
8252                 case CAM_CMD_TUR:
8253                         error = testunitready(cam_dev, retry_count, timeout, 0);
8254                         break;
8255                 case CAM_CMD_INQUIRY:
8256                         error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
8257                                               retry_count, timeout);
8258                         break;
8259                 case CAM_CMD_IDENTIFY:
8260                         error = ataidentify(cam_dev, retry_count, timeout);
8261                         break;
8262                 case CAM_CMD_STARTSTOP:
8263                         error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
8264                                           arglist & CAM_ARG_EJECT, retry_count,
8265                                           timeout);
8266                         break;
8267 #endif /* MINIMALISTIC */
8268                 case CAM_CMD_RESCAN:
8269                         error = dorescan_or_reset(argc, argv, 1);
8270                         break;
8271                 case CAM_CMD_RESET:
8272                         error = dorescan_or_reset(argc, argv, 0);
8273                         break;
8274 #ifndef MINIMALISTIC
8275                 case CAM_CMD_READ_DEFECTS:
8276                         error = readdefects(cam_dev, argc, argv, combinedopt,
8277                                             retry_count, timeout);
8278                         break;
8279                 case CAM_CMD_MODE_PAGE:
8280                         modepage(cam_dev, argc, argv, combinedopt,
8281                                  retry_count, timeout);
8282                         break;
8283                 case CAM_CMD_SCSI_CMD:
8284                         error = scsicmd(cam_dev, argc, argv, combinedopt,
8285                                         retry_count, timeout);
8286                         break;
8287                 case CAM_CMD_SMP_CMD:
8288                         error = smpcmd(cam_dev, argc, argv, combinedopt,
8289                                        retry_count, timeout);
8290                         break;
8291                 case CAM_CMD_SMP_RG:
8292                         error = smpreportgeneral(cam_dev, argc, argv,
8293                                                  combinedopt, retry_count,
8294                                                  timeout);
8295                         break;
8296                 case CAM_CMD_SMP_PC:
8297                         error = smpphycontrol(cam_dev, argc, argv, combinedopt, 
8298                                               retry_count, timeout);
8299                         break;
8300                 case CAM_CMD_SMP_PHYLIST:
8301                         error = smpphylist(cam_dev, argc, argv, combinedopt,
8302                                            retry_count, timeout);
8303                         break;
8304                 case CAM_CMD_SMP_MANINFO:
8305                         error = smpmaninfo(cam_dev, argc, argv, combinedopt,
8306                                            retry_count, timeout);
8307                         break;
8308                 case CAM_CMD_DEBUG:
8309                         error = camdebug(argc, argv, combinedopt);
8310                         break;
8311                 case CAM_CMD_TAG:
8312                         error = tagcontrol(cam_dev, argc, argv, combinedopt);
8313                         break;
8314                 case CAM_CMD_RATE:
8315                         error = ratecontrol(cam_dev, retry_count, timeout,
8316                                             argc, argv, combinedopt);
8317                         break;
8318                 case CAM_CMD_FORMAT:
8319                         error = scsiformat(cam_dev, argc, argv,
8320                                            combinedopt, retry_count, timeout);
8321                         break;
8322                 case CAM_CMD_REPORTLUNS:
8323                         error = scsireportluns(cam_dev, argc, argv,
8324                                                combinedopt, retry_count,
8325                                                timeout);
8326                         break;
8327                 case CAM_CMD_READCAP:
8328                         error = scsireadcapacity(cam_dev, argc, argv,
8329                                                  combinedopt, retry_count,
8330                                                  timeout);
8331                         break;
8332                 case CAM_CMD_IDLE:
8333                 case CAM_CMD_STANDBY:
8334                 case CAM_CMD_SLEEP:
8335                         error = atapm(cam_dev, argc, argv,
8336                                       combinedopt, retry_count, timeout);
8337                         break;
8338                 case CAM_CMD_SECURITY:
8339                         error = atasecurity(cam_dev, retry_count, timeout,
8340                                             argc, argv, combinedopt);
8341                         break;
8342                 case CAM_CMD_DOWNLOAD_FW:
8343                         error = fwdownload(cam_dev, argc, argv, combinedopt,
8344                             arglist & CAM_ARG_VERBOSE, retry_count, timeout,
8345                             get_disk_type(cam_dev));
8346                         break;
8347                 case CAM_CMD_SANITIZE:
8348                         error = scsisanitize(cam_dev, argc, argv,
8349                                              combinedopt, retry_count, timeout);
8350                         break;
8351                 case CAM_CMD_PERSIST:
8352                         error = scsipersist(cam_dev, argc, argv, combinedopt,
8353                             retry_count, timeout, arglist & CAM_ARG_VERBOSE,
8354                             arglist & CAM_ARG_ERR_RECOVER);
8355                         break;
8356 #endif /* MINIMALISTIC */
8357                 case CAM_CMD_USAGE:
8358                         usage(1);
8359                         break;
8360                 default:
8361                         usage(0);
8362                         error = 1;
8363                         break;
8364         }
8365
8366         if (cam_dev != NULL)
8367                 cam_close_device(cam_dev);
8368
8369         exit(error);
8370 }