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