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