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