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