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