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