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