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