]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/camcontrol/camcontrol.c
MFC r344701: Fix incorrect / unused sector_count for identify requests
[FreeBSD/FreeBSD.git] / sbin / camcontrol / camcontrol.c
1 /*
2  * Copyright (c) 1997-2007 Kenneth D. Merry
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/ioctl.h>
33 #include <sys/stdint.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/endian.h>
37 #include <sys/sbuf.h>
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <inttypes.h>
44 #include <limits.h>
45 #include <fcntl.h>
46 #include <ctype.h>
47 #include <err.h>
48 #include <libutil.h>
49 #ifndef MINIMALISTIC
50 #include <limits.h>
51 #include <inttypes.h>
52 #endif
53
54 #include <cam/cam.h>
55 #include <cam/cam_debug.h>
56 #include <cam/cam_ccb.h>
57 #include <cam/scsi/scsi_all.h>
58 #include <cam/scsi/scsi_da.h>
59 #include <cam/scsi/scsi_pass.h>
60 #include <cam/scsi/scsi_message.h>
61 #include <cam/scsi/smp_all.h>
62 #include <cam/ata/ata_all.h>
63 #include <cam/mmc/mmc_all.h>
64 #include <camlib.h>
65 #include "camcontrol.h"
66 #ifdef WITH_NVME
67 #include "nvmecontrol_ext.h"
68 #endif
69
70 typedef enum {
71         CAM_CMD_NONE            = 0x00000000,
72         CAM_CMD_DEVLIST         = 0x00000001,
73         CAM_CMD_TUR             = 0x00000002,
74         CAM_CMD_INQUIRY         = 0x00000003,
75         CAM_CMD_STARTSTOP       = 0x00000004,
76         CAM_CMD_RESCAN          = 0x00000005,
77         CAM_CMD_READ_DEFECTS    = 0x00000006,
78         CAM_CMD_MODE_PAGE       = 0x00000007,
79         CAM_CMD_SCSI_CMD        = 0x00000008,
80         CAM_CMD_DEVTREE         = 0x00000009,
81         CAM_CMD_USAGE           = 0x0000000a,
82         CAM_CMD_DEBUG           = 0x0000000b,
83         CAM_CMD_RESET           = 0x0000000c,
84         CAM_CMD_FORMAT          = 0x0000000d,
85         CAM_CMD_TAG             = 0x0000000e,
86         CAM_CMD_RATE            = 0x0000000f,
87         CAM_CMD_DETACH          = 0x00000010,
88         CAM_CMD_REPORTLUNS      = 0x00000011,
89         CAM_CMD_READCAP         = 0x00000012,
90         CAM_CMD_IDENTIFY        = 0x00000013,
91         CAM_CMD_IDLE            = 0x00000014,
92         CAM_CMD_STANDBY         = 0x00000015,
93         CAM_CMD_SLEEP           = 0x00000016,
94         CAM_CMD_SMP_CMD         = 0x00000017,
95         CAM_CMD_SMP_RG          = 0x00000018,
96         CAM_CMD_SMP_PC          = 0x00000019,
97         CAM_CMD_SMP_PHYLIST     = 0x0000001a,
98         CAM_CMD_SMP_MANINFO     = 0x0000001b,
99         CAM_CMD_DOWNLOAD_FW     = 0x0000001c,
100         CAM_CMD_SECURITY        = 0x0000001d,
101         CAM_CMD_HPA             = 0x0000001e,
102         CAM_CMD_SANITIZE        = 0x0000001f,
103         CAM_CMD_PERSIST         = 0x00000020,
104         CAM_CMD_APM             = 0x00000021,
105         CAM_CMD_AAM             = 0x00000022,
106         CAM_CMD_ATTRIB          = 0x00000023,
107         CAM_CMD_OPCODES         = 0x00000024,
108         CAM_CMD_REPROBE         = 0x00000025,
109         CAM_CMD_ZONE            = 0x00000026,
110         CAM_CMD_EPC             = 0x00000027,
111         CAM_CMD_TIMESTAMP       = 0x00000028,
112         CAM_CMD_MMCSD_CMD       = 0x00000029
113 } cam_cmdmask;
114
115 typedef enum {
116         CAM_ARG_NONE            = 0x00000000,
117         CAM_ARG_VERBOSE         = 0x00000001,
118         CAM_ARG_DEVICE          = 0x00000002,
119         CAM_ARG_BUS             = 0x00000004,
120         CAM_ARG_TARGET          = 0x00000008,
121         CAM_ARG_LUN             = 0x00000010,
122         CAM_ARG_EJECT           = 0x00000020,
123         CAM_ARG_UNIT            = 0x00000040,
124         CAM_ARG_FORMAT_BLOCK    = 0x00000080,
125         CAM_ARG_FORMAT_BFI      = 0x00000100,
126         CAM_ARG_FORMAT_PHYS     = 0x00000200,
127         CAM_ARG_PLIST           = 0x00000400,
128         CAM_ARG_GLIST           = 0x00000800,
129         CAM_ARG_GET_SERIAL      = 0x00001000,
130         CAM_ARG_GET_STDINQ      = 0x00002000,
131         CAM_ARG_GET_XFERRATE    = 0x00004000,
132         CAM_ARG_INQ_MASK        = 0x00007000,
133         CAM_ARG_TIMEOUT         = 0x00020000,
134         CAM_ARG_CMD_IN          = 0x00040000,
135         CAM_ARG_CMD_OUT         = 0x00080000,
136         CAM_ARG_ERR_RECOVER     = 0x00200000,
137         CAM_ARG_RETRIES         = 0x00400000,
138         CAM_ARG_START_UNIT      = 0x00800000,
139         CAM_ARG_DEBUG_INFO      = 0x01000000,
140         CAM_ARG_DEBUG_TRACE     = 0x02000000,
141         CAM_ARG_DEBUG_SUBTRACE  = 0x04000000,
142         CAM_ARG_DEBUG_CDB       = 0x08000000,
143         CAM_ARG_DEBUG_XPT       = 0x10000000,
144         CAM_ARG_DEBUG_PERIPH    = 0x20000000,
145         CAM_ARG_DEBUG_PROBE     = 0x40000000,
146 } cam_argmask;
147
148 struct camcontrol_opts {
149         const char      *optname;
150         uint32_t        cmdnum;
151         cam_argmask     argnum;
152         const char      *subopt;
153 };
154
155 #ifndef MINIMALISTIC
156 struct ata_res_pass16 {
157         u_int16_t reserved[5];
158         u_int8_t flags;
159         u_int8_t error;
160         u_int8_t sector_count_exp;
161         u_int8_t sector_count;
162         u_int8_t lba_low_exp;
163         u_int8_t lba_low;
164         u_int8_t lba_mid_exp;
165         u_int8_t lba_mid;
166         u_int8_t lba_high_exp;
167         u_int8_t lba_high;
168         u_int8_t device;
169         u_int8_t status;
170 };
171
172 struct ata_set_max_pwd
173 {
174         u_int16_t reserved1;
175         u_int8_t password[32];
176         u_int16_t reserved2[239];
177 };
178
179 static struct scsi_nv task_attrs[] = {
180         { "simple", MSG_SIMPLE_Q_TAG },
181         { "head", MSG_HEAD_OF_Q_TAG },
182         { "ordered", MSG_ORDERED_Q_TAG },
183         { "iwr", MSG_IGN_WIDE_RESIDUE },
184         { "aca", MSG_ACA_TASK }
185 };
186
187 static const char scsicmd_opts[] = "a:c:dfi:o:r";
188 static const char readdefect_opts[] = "f:GPqsS:X";
189 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
190 static const char smprg_opts[] = "l";
191 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
192 static const char smpphylist_opts[] = "lq";
193 static char pwd_opt;
194 #endif
195
196 static struct camcontrol_opts option_table[] = {
197 #ifndef MINIMALISTIC
198         {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
199         {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
200         {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
201         {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
202         {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
203         {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
204         {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
205         {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
206         {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
207         {"reprobe", CAM_CMD_REPROBE, CAM_ARG_NONE, NULL},
208 #endif /* MINIMALISTIC */
209         {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
210         {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
211 #ifndef MINIMALISTIC
212         {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
213         {"mmcsdcmd", CAM_CMD_MMCSD_CMD, CAM_ARG_NONE, "c:a:f:Wb:l:41S:I"},
214         {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
215         {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
216         {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
217         {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
218         {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
219         {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
220         {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
221         {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
222         {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
223         {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
224         {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
225 #endif /* MINIMALISTIC */
226         {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, "-b"},
227 #ifndef MINIMALISTIC
228         {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
229         {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
230         {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
231         {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
232         {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
233         {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
234         {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
235         {"sanitize", CAM_CMD_SANITIZE, CAM_ARG_NONE, "a:c:IP:qrUwy"},
236         {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
237         {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
238         {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
239         {"apm", CAM_CMD_APM, CAM_ARG_NONE, "l:"},
240         {"aam", CAM_CMD_AAM, CAM_ARG_NONE, "l:"},
241         {"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:qsy"},
242         {"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"},
243         {"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"},
244         {"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"},
245         {"attrib", CAM_CMD_ATTRIB, CAM_ARG_NONE, "a:ce:F:p:r:s:T:w:V:"},
246         {"opcodes", CAM_CMD_OPCODES, CAM_ARG_NONE, "No:s:T"},
247         {"zone", CAM_CMD_ZONE, CAM_ARG_NONE, "ac:l:No:P:"},
248         {"epc", CAM_CMD_EPC, CAM_ARG_NONE, "c:dDeHp:Pr:sS:T:"},
249         {"timestamp", CAM_CMD_TIMESTAMP, CAM_ARG_NONE, "f:mrsUT:"},
250 #endif /* MINIMALISTIC */
251         {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
252         {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
253         {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
254         {NULL, 0, 0, NULL}
255 };
256
257 struct cam_devitem {
258         struct device_match_result dev_match;
259         int num_periphs;
260         struct periph_match_result *periph_matches;
261         struct scsi_vpd_device_id *device_id;
262         int device_id_len;
263         STAILQ_ENTRY(cam_devitem) links;
264 };
265
266 struct cam_devlist {
267         STAILQ_HEAD(, cam_devitem) dev_queue;
268         path_id_t path_id;
269 };
270
271 static cam_cmdmask cmdlist;
272 static cam_argmask arglist;
273
274 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
275                             uint32_t *cmdnum, cam_argmask *argnum,
276                             const char **subopt);
277 #ifndef MINIMALISTIC
278 static int getdevlist(struct cam_device *device);
279 #endif /* MINIMALISTIC */
280 static int getdevtree(int argc, char **argv, char *combinedopt);
281 static int print_dev_scsi(struct device_match_result *dev_result, char *tmpstr);
282 static int print_dev_ata(struct device_match_result *dev_result, char *tmpstr);
283 static int print_dev_semb(struct device_match_result *dev_result, char *tmpstr);
284 static int print_dev_mmcsd(struct device_match_result *dev_result,
285     char *tmpstr);
286 #ifdef WITH_NVME
287 static int print_dev_nvme(struct device_match_result *dev_result, char *tmpstr);
288 #endif
289 #ifndef MINIMALISTIC
290 static int testunitready(struct cam_device *device, int task_attr,
291                          int retry_count, int timeout, int quiet);
292 static int scsistart(struct cam_device *device, int startstop, int loadeject,
293                      int task_attr, int retry_count, int timeout);
294 static int scsiinquiry(struct cam_device *device, int task_attr,
295                        int retry_count, int timeout);
296 static int scsiserial(struct cam_device *device, int task_attr,
297                       int retry_count, int timeout);
298 #endif /* MINIMALISTIC */
299 static int parse_btl(char *tstr, path_id_t *bus, target_id_t *target,
300                      lun_id_t *lun, cam_argmask *arglst);
301 static int dorescan_or_reset(int argc, char **argv, int rescan);
302 static int rescan_or_reset_bus(path_id_t bus, int rescan);
303 static int scanlun_or_reset_dev(path_id_t bus, target_id_t target,
304     lun_id_t lun, int scan);
305 #ifndef MINIMALISTIC
306 static int readdefects(struct cam_device *device, int argc, char **argv,
307                        char *combinedopt, int task_attr, int retry_count,
308                        int timeout);
309 static void modepage(struct cam_device *device, int argc, char **argv,
310                      char *combinedopt, int task_attr, int retry_count,
311                      int timeout);
312 static int scsicmd(struct cam_device *device, int argc, char **argv,
313                    char *combinedopt, int task_attr, int retry_count,
314                    int timeout);
315 static int smpcmd(struct cam_device *device, int argc, char **argv,
316                   char *combinedopt, int retry_count, int timeout);
317 static int mmcsdcmd(struct cam_device *device, int argc, char **argv,
318                   char *combinedopt, int retry_count, int timeout);
319 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
320                             char *combinedopt, int retry_count, int timeout);
321 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
322                          char *combinedopt, int retry_count, int timeout);
323 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
324                       char *combinedopt, int retry_count, int timeout);
325 static int getdevid(struct cam_devitem *item);
326 static int buildbusdevlist(struct cam_devlist *devlist);
327 static void freebusdevlist(struct cam_devlist *devlist);
328 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
329                                          uint64_t sasaddr);
330 static int smpphylist(struct cam_device *device, int argc, char **argv,
331                       char *combinedopt, int retry_count, int timeout);
332 static int tagcontrol(struct cam_device *device, int argc, char **argv,
333                       char *combinedopt);
334 static void cts_print(struct cam_device *device,
335                       struct ccb_trans_settings *cts);
336 static void cpi_print(struct ccb_pathinq *cpi);
337 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
338 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
339 static int get_print_cts(struct cam_device *device, int user_settings,
340                          int quiet, struct ccb_trans_settings *cts);
341 static int ratecontrol(struct cam_device *device, int task_attr,
342                        int retry_count, int timeout, int argc, char **argv,
343                        char *combinedopt);
344 static int scsiformat(struct cam_device *device, int argc, char **argv,
345                       char *combinedopt, int task_attr, int retry_count,
346                       int timeout);
347 static int scsisanitize(struct cam_device *device, int argc, char **argv,
348                         char *combinedopt, int task_attr, int retry_count,
349                         int timeout);
350 static int scsireportluns(struct cam_device *device, int argc, char **argv,
351                           char *combinedopt, int task_attr, int retry_count,
352                           int timeout);
353 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
354                             char *combinedopt, int task_attr, int retry_count,
355                             int timeout);
356 static int atapm(struct cam_device *device, int argc, char **argv,
357                  char *combinedopt, int retry_count, int timeout);
358 static int atasecurity(struct cam_device *device, int retry_count, int timeout,
359                        int argc, char **argv, char *combinedopt);
360 static int atahpa(struct cam_device *device, int retry_count, int timeout,
361                   int argc, char **argv, char *combinedopt);
362 static int scsiprintoneopcode(struct cam_device *device, int req_opcode,
363                               int sa_set, int req_sa, uint8_t *buf,
364                               uint32_t valid_len);
365 static int scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
366                             uint32_t valid_len);
367 static int scsiopcodes(struct cam_device *device, int argc, char **argv,
368                        char *combinedopt, int task_attr, int retry_count,
369                        int timeout, int verbose);
370 static int scsireprobe(struct cam_device *device);
371
372 #endif /* MINIMALISTIC */
373 #ifndef min
374 #define min(a,b) (((a)<(b))?(a):(b))
375 #endif
376 #ifndef max
377 #define max(a,b) (((a)>(b))?(a):(b))
378 #endif
379
380 camcontrol_optret
381 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
382           cam_argmask *argnum, const char **subopt)
383 {
384         struct camcontrol_opts *opts;
385         int num_matches = 0;
386
387         for (opts = table; (opts != NULL) && (opts->optname != NULL);
388              opts++) {
389                 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
390                         *cmdnum = opts->cmdnum;
391                         *argnum = opts->argnum;
392                         *subopt = opts->subopt;
393                         if (++num_matches > 1)
394                                 return (CC_OR_AMBIGUOUS);
395                 }
396         }
397
398         if (num_matches > 0)
399                 return (CC_OR_FOUND);
400         else
401                 return (CC_OR_NOT_FOUND);
402 }
403
404 #ifndef MINIMALISTIC
405 static int
406 getdevlist(struct cam_device *device)
407 {
408         union ccb *ccb;
409         char status[32];
410         int error = 0;
411
412         ccb = cam_getccb(device);
413
414         ccb->ccb_h.func_code = XPT_GDEVLIST;
415         ccb->ccb_h.flags = CAM_DIR_NONE;
416         ccb->ccb_h.retry_count = 1;
417         ccb->cgdl.index = 0;
418         ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
419         while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
420                 if (cam_send_ccb(device, ccb) < 0) {
421                         perror("error getting device list");
422                         cam_freeccb(ccb);
423                         return (1);
424                 }
425
426                 status[0] = '\0';
427
428                 switch (ccb->cgdl.status) {
429                         case CAM_GDEVLIST_MORE_DEVS:
430                                 strcpy(status, "MORE");
431                                 break;
432                         case CAM_GDEVLIST_LAST_DEVICE:
433                                 strcpy(status, "LAST");
434                                 break;
435                         case CAM_GDEVLIST_LIST_CHANGED:
436                                 strcpy(status, "CHANGED");
437                                 break;
438                         case CAM_GDEVLIST_ERROR:
439                                 strcpy(status, "ERROR");
440                                 error = 1;
441                                 break;
442                 }
443
444                 fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
445                         ccb->cgdl.periph_name,
446                         ccb->cgdl.unit_number,
447                         ccb->cgdl.generation,
448                         ccb->cgdl.index,
449                         status);
450
451                 /*
452                  * If the list has changed, we need to start over from the
453                  * beginning.
454                  */
455                 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
456                         ccb->cgdl.index = 0;
457         }
458
459         cam_freeccb(ccb);
460
461         return (error);
462 }
463 #endif /* MINIMALISTIC */
464
465 static int
466 getdevtree(int argc, char **argv, char *combinedopt)
467 {
468         union ccb ccb;
469         int bufsize, fd;
470         unsigned int i;
471         int need_close = 0;
472         int error = 0;
473         int skip_device = 0;
474         int busonly = 0;
475         int c;
476
477         while ((c = getopt(argc, argv, combinedopt)) != -1) {
478                 switch(c) {
479                 case 'b':
480                         if ((arglist & CAM_ARG_VERBOSE) == 0)
481                                 busonly = 1;
482                         break;
483                 default:
484                         break;
485                 }
486         }
487
488         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
489                 warn("couldn't open %s", XPT_DEVICE);
490                 return (1);
491         }
492
493         bzero(&ccb, sizeof(union ccb));
494
495         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
496         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
497         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
498
499         ccb.ccb_h.func_code = XPT_DEV_MATCH;
500         bufsize = sizeof(struct dev_match_result) * 100;
501         ccb.cdm.match_buf_len = bufsize;
502         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
503         if (ccb.cdm.matches == NULL) {
504                 warnx("can't malloc memory for matches");
505                 close(fd);
506                 return (1);
507         }
508         ccb.cdm.num_matches = 0;
509
510         /*
511          * We fetch all nodes, since we display most of them in the default
512          * case, and all in the verbose case.
513          */
514         ccb.cdm.num_patterns = 0;
515         ccb.cdm.pattern_buf_len = 0;
516
517         /*
518          * We do the ioctl multiple times if necessary, in case there are
519          * more than 100 nodes in the EDT.
520          */
521         do {
522                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
523                         warn("error sending CAMIOCOMMAND ioctl");
524                         error = 1;
525                         break;
526                 }
527
528                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
529                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
530                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
531                         warnx("got CAM error %#x, CDM error %d\n",
532                               ccb.ccb_h.status, ccb.cdm.status);
533                         error = 1;
534                         break;
535                 }
536
537                 for (i = 0; i < ccb.cdm.num_matches; i++) {
538                         switch (ccb.cdm.matches[i].type) {
539                         case DEV_MATCH_BUS: {
540                                 struct bus_match_result *bus_result;
541
542                                 /*
543                                  * Only print the bus information if the
544                                  * user turns on the verbose flag.
545                                  */
546                                 if ((busonly == 0) &&
547                                     (arglist & CAM_ARG_VERBOSE) == 0)
548                                         break;
549
550                                 bus_result =
551                                         &ccb.cdm.matches[i].result.bus_result;
552
553                                 if (need_close) {
554                                         fprintf(stdout, ")\n");
555                                         need_close = 0;
556                                 }
557
558                                 fprintf(stdout, "scbus%d on %s%d bus %d%s\n",
559                                         bus_result->path_id,
560                                         bus_result->dev_name,
561                                         bus_result->unit_number,
562                                         bus_result->bus_id,
563                                         (busonly ? "" : ":"));
564                                 break;
565                         }
566                         case DEV_MATCH_DEVICE: {
567                                 struct device_match_result *dev_result;
568                                 char tmpstr[256];
569
570                                 if (busonly == 1)
571                                         break;
572
573                                 dev_result =
574                                      &ccb.cdm.matches[i].result.device_result;
575
576                                 if ((dev_result->flags
577                                      & DEV_RESULT_UNCONFIGURED)
578                                  && ((arglist & CAM_ARG_VERBOSE) == 0)) {
579                                         skip_device = 1;
580                                         break;
581                                 } else
582                                         skip_device = 0;
583
584                                 if (dev_result->protocol == PROTO_SCSI) {
585                                         if (print_dev_scsi(dev_result,
586                                             &tmpstr[0]) != 0) {
587                                                 skip_device = 1;
588                                                 break;
589                                         }
590                                 } else if (dev_result->protocol == PROTO_ATA ||
591                                     dev_result->protocol == PROTO_SATAPM) {
592                                         if (print_dev_ata(dev_result,
593                                             &tmpstr[0]) != 0) {
594                                                 skip_device = 1;
595                                                 break;
596                                         }
597                                 } else if (dev_result->protocol == PROTO_MMCSD){
598                                         if (print_dev_mmcsd(dev_result,
599                                             &tmpstr[0]) != 0) {
600                                                 skip_device = 1;
601                                                 break;
602                                         }
603                                 } else if (dev_result->protocol == PROTO_SEMB) {
604                                         if (print_dev_semb(dev_result,
605                                             &tmpstr[0]) != 0) {
606                                                 skip_device = 1;
607                                                 break;
608                                         }
609 #ifdef WITH_NVME
610                                 } else if (dev_result->protocol == PROTO_NVME) {
611                                         if (print_dev_nvme(dev_result,
612                                             &tmpstr[0]) != 0) {
613                                                 skip_device = 1;
614                                                 break;
615                                         }
616 #endif
617                                 } else {
618                                     sprintf(tmpstr, "<>");
619                                 }
620                                 if (need_close) {
621                                         fprintf(stdout, ")\n");
622                                         need_close = 0;
623                                 }
624
625                                 fprintf(stdout, "%-33s  at scbus%d "
626                                         "target %d lun %jx (",
627                                         tmpstr,
628                                         dev_result->path_id,
629                                         dev_result->target_id,
630                                         (uintmax_t)dev_result->target_lun);
631
632                                 need_close = 1;
633
634                                 break;
635                         }
636                         case DEV_MATCH_PERIPH: {
637                                 struct periph_match_result *periph_result;
638
639                                 periph_result =
640                                       &ccb.cdm.matches[i].result.periph_result;
641
642                                 if (busonly || skip_device != 0)
643                                         break;
644
645                                 if (need_close > 1)
646                                         fprintf(stdout, ",");
647
648                                 fprintf(stdout, "%s%d",
649                                         periph_result->periph_name,
650                                         periph_result->unit_number);
651
652                                 need_close++;
653                                 break;
654                         }
655                         default:
656                                 fprintf(stdout, "unknown match type\n");
657                                 break;
658                         }
659                 }
660
661         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
662                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
663
664         if (need_close)
665                 fprintf(stdout, ")\n");
666
667         close(fd);
668
669         return (error);
670 }
671
672 static int
673 print_dev_scsi(struct device_match_result *dev_result, char *tmpstr)
674 {
675         char vendor[16], product[48], revision[16];
676
677         cam_strvis(vendor, dev_result->inq_data.vendor,
678             sizeof(dev_result->inq_data.vendor), sizeof(vendor));
679         cam_strvis(product, dev_result->inq_data.product,
680             sizeof(dev_result->inq_data.product), sizeof(product));
681         cam_strvis(revision, dev_result->inq_data.revision,
682             sizeof(dev_result->inq_data.revision), sizeof(revision));
683         sprintf(tmpstr, "<%s %s %s>", vendor, product, revision);
684
685         return (0);
686 }
687
688 static int
689 print_dev_ata(struct device_match_result *dev_result, char *tmpstr)
690 {
691         char product[48], revision[16];
692
693         cam_strvis(product, dev_result->ident_data.model,
694             sizeof(dev_result->ident_data.model), sizeof(product));
695         cam_strvis(revision, dev_result->ident_data.revision,
696             sizeof(dev_result->ident_data.revision), sizeof(revision));
697         sprintf(tmpstr, "<%s %s>", product, revision);
698
699         return (0);
700 }
701
702 static int
703 print_dev_semb(struct device_match_result *dev_result, char *tmpstr)
704 {
705         struct sep_identify_data *sid;
706         char vendor[16], product[48], revision[16], fw[5];
707
708         sid = (struct sep_identify_data *)&dev_result->ident_data;
709         cam_strvis(vendor, sid->vendor_id,
710             sizeof(sid->vendor_id), sizeof(vendor));
711         cam_strvis(product, sid->product_id,
712             sizeof(sid->product_id), sizeof(product));
713         cam_strvis(revision, sid->product_rev,
714             sizeof(sid->product_rev), sizeof(revision));
715         cam_strvis(fw, sid->firmware_rev,
716             sizeof(sid->firmware_rev), sizeof(fw));
717         sprintf(tmpstr, "<%s %s %s %s>", vendor, product, revision, fw);
718
719         return (0);
720 }
721
722 static int
723 print_dev_mmcsd(struct device_match_result *dev_result, char *tmpstr)
724 {
725         union ccb *ccb;
726         struct ccb_dev_advinfo *advi;
727         struct cam_device *dev;
728         struct mmc_params mmc_ident_data;
729
730         dev = cam_open_btl(dev_result->path_id, dev_result->target_id,
731             dev_result->target_lun, O_RDWR, NULL);
732         if (dev == NULL) {
733                 warnx("%s", cam_errbuf);
734                 return (1);
735         }
736
737         ccb = cam_getccb(dev);
738         if (ccb == NULL) {
739                 warnx("couldn't allocate CCB");
740                 cam_close_device(dev);
741                 return (1);
742         }
743
744         advi = &ccb->cdai;
745         advi->ccb_h.flags = CAM_DIR_IN;
746         advi->ccb_h.func_code = XPT_DEV_ADVINFO;
747         advi->flags = CDAI_FLAG_NONE;
748         advi->buftype = CDAI_TYPE_MMC_PARAMS;
749         advi->bufsiz = sizeof(struct mmc_params);
750         advi->buf = (uint8_t *)&mmc_ident_data;
751
752         if (cam_send_ccb(dev, ccb) < 0) {
753                 warn("error sending CAMIOCOMMAND ioctl");
754                 cam_freeccb(ccb);
755                 cam_close_device(dev);
756                 return (1);
757         }
758
759         if (strlen(mmc_ident_data.model) > 0) {
760                 sprintf(tmpstr, "<%s>", mmc_ident_data.model);
761         } else {
762                 sprintf(tmpstr, "<%s card>",
763                     mmc_ident_data.card_features &
764                     CARD_FEATURE_SDIO ? "SDIO" : "unknown");
765         }
766
767         cam_freeccb(ccb);
768         cam_close_device(dev);
769         return (0);
770 }
771
772 #ifdef WITH_NVME
773 static int
774 nvme_get_cdata(struct cam_device *dev, struct nvme_controller_data *cdata)
775 {
776         union ccb *ccb;
777         struct ccb_dev_advinfo *advi;
778
779         ccb = cam_getccb(dev);
780         if (ccb == NULL) {
781                 warnx("couldn't allocate CCB");
782                 cam_close_device(dev);
783                 return (1);
784         }
785
786         advi = &ccb->cdai;
787         advi->ccb_h.flags = CAM_DIR_IN;
788         advi->ccb_h.func_code = XPT_DEV_ADVINFO;
789         advi->flags = CDAI_FLAG_NONE;
790         advi->buftype = CDAI_TYPE_NVME_CNTRL;
791         advi->bufsiz = sizeof(struct nvme_controller_data);
792         advi->buf = (uint8_t *)cdata;
793
794         if (cam_send_ccb(dev, ccb) < 0) {
795                 warn("error sending CAMIOCOMMAND ioctl");
796                 cam_freeccb(ccb);
797                 cam_close_device(dev);
798                 return(1);
799         }
800         if (advi->ccb_h.status != CAM_REQ_CMP) {
801                 warnx("got CAM error %#x", advi->ccb_h.status);
802                 cam_freeccb(ccb);
803                 cam_close_device(dev);
804                 return(1);
805         }
806         cam_freeccb(ccb);
807         return 0;
808 }
809
810 static int
811 print_dev_nvme(struct device_match_result *dev_result, char *tmpstr)
812 {
813         struct cam_device *dev;
814         struct nvme_controller_data cdata;
815         char vendor[64], product[64];
816
817         dev = cam_open_btl(dev_result->path_id, dev_result->target_id,
818             dev_result->target_lun, O_RDWR, NULL);
819         if (dev == NULL) {
820                 warnx("%s", cam_errbuf);
821                 return (1);
822         }
823
824         if (nvme_get_cdata(dev, &cdata))
825                 return (1);
826
827         cam_strvis(vendor, cdata.mn, sizeof(cdata.mn), sizeof(vendor));
828         cam_strvis(product, cdata.fr, sizeof(cdata.fr), sizeof(product));
829         sprintf(tmpstr, "<%s %s>", vendor, product);
830
831         cam_close_device(dev);
832         return (0);
833 }
834 #endif
835
836 #ifndef MINIMALISTIC
837 static int
838 testunitready(struct cam_device *device, int task_attr, int retry_count,
839               int timeout, int quiet)
840 {
841         int error = 0;
842         union ccb *ccb;
843
844         ccb = cam_getccb(device);
845
846         scsi_test_unit_ready(&ccb->csio,
847                              /* retries */ retry_count,
848                              /* cbfcnp */ NULL,
849                              /* tag_action */ task_attr,
850                              /* sense_len */ SSD_FULL_SIZE,
851                              /* timeout */ timeout ? timeout : 5000);
852
853         /* Disable freezing the device queue */
854         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
855
856         if (arglist & CAM_ARG_ERR_RECOVER)
857                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
858
859         if (cam_send_ccb(device, ccb) < 0) {
860                 if (quiet == 0)
861                         perror("error sending test unit ready");
862
863                 if (arglist & CAM_ARG_VERBOSE) {
864                         cam_error_print(device, ccb, CAM_ESF_ALL,
865                                         CAM_EPF_ALL, stderr);
866                 }
867
868                 cam_freeccb(ccb);
869                 return (1);
870         }
871
872         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
873                 if (quiet == 0)
874                         fprintf(stdout, "Unit is ready\n");
875         } else {
876                 if (quiet == 0)
877                         fprintf(stdout, "Unit is not ready\n");
878                 error = 1;
879
880                 if (arglist & CAM_ARG_VERBOSE) {
881                         cam_error_print(device, ccb, CAM_ESF_ALL,
882                                         CAM_EPF_ALL, stderr);
883                 }
884         }
885
886         cam_freeccb(ccb);
887
888         return (error);
889 }
890
891 static int
892 scsistart(struct cam_device *device, int startstop, int loadeject,
893           int task_attr, int retry_count, int timeout)
894 {
895         union ccb *ccb;
896         int error = 0;
897
898         ccb = cam_getccb(device);
899
900         /*
901          * If we're stopping, send an ordered tag so the drive in question
902          * will finish any previously queued writes before stopping.  If
903          * the device isn't capable of tagged queueing, or if tagged
904          * queueing is turned off, the tag action is a no-op.  We override
905          * the default simple tag, although this also has the effect of
906          * overriding the user's wishes if he wanted to specify a simple
907          * tag.
908          */
909         if ((startstop == 0)
910          && (task_attr == MSG_SIMPLE_Q_TAG))
911                 task_attr = MSG_ORDERED_Q_TAG;
912
913         scsi_start_stop(&ccb->csio,
914                         /* retries */ retry_count,
915                         /* cbfcnp */ NULL,
916                         /* tag_action */ task_attr,
917                         /* start/stop */ startstop,
918                         /* load_eject */ loadeject,
919                         /* immediate */ 0,
920                         /* sense_len */ SSD_FULL_SIZE,
921                         /* timeout */ timeout ? timeout : 120000);
922
923         /* Disable freezing the device queue */
924         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
925
926         if (arglist & CAM_ARG_ERR_RECOVER)
927                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
928
929         if (cam_send_ccb(device, ccb) < 0) {
930                 perror("error sending start unit");
931
932                 if (arglist & CAM_ARG_VERBOSE) {
933                         cam_error_print(device, ccb, CAM_ESF_ALL,
934                                         CAM_EPF_ALL, stderr);
935                 }
936
937                 cam_freeccb(ccb);
938                 return (1);
939         }
940
941         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
942                 if (startstop) {
943                         fprintf(stdout, "Unit started successfully");
944                         if (loadeject)
945                                 fprintf(stdout,", Media loaded\n");
946                         else
947                                 fprintf(stdout,"\n");
948                 } else {
949                         fprintf(stdout, "Unit stopped successfully");
950                         if (loadeject)
951                                 fprintf(stdout, ", Media ejected\n");
952                         else
953                                 fprintf(stdout, "\n");
954                 }
955         else {
956                 error = 1;
957                 if (startstop)
958                         fprintf(stdout,
959                                 "Error received from start unit command\n");
960                 else
961                         fprintf(stdout,
962                                 "Error received from stop unit command\n");
963
964                 if (arglist & CAM_ARG_VERBOSE) {
965                         cam_error_print(device, ccb, CAM_ESF_ALL,
966                                         CAM_EPF_ALL, stderr);
967                 }
968         }
969
970         cam_freeccb(ccb);
971
972         return (error);
973 }
974
975 int
976 scsidoinquiry(struct cam_device *device, int argc, char **argv,
977               char *combinedopt, int task_attr, int retry_count, int timeout)
978 {
979         int c;
980         int error = 0;
981
982         while ((c = getopt(argc, argv, combinedopt)) != -1) {
983                 switch(c) {
984                 case 'D':
985                         arglist |= CAM_ARG_GET_STDINQ;
986                         break;
987                 case 'R':
988                         arglist |= CAM_ARG_GET_XFERRATE;
989                         break;
990                 case 'S':
991                         arglist |= CAM_ARG_GET_SERIAL;
992                         break;
993                 default:
994                         break;
995                 }
996         }
997
998         /*
999          * If the user didn't specify any inquiry options, he wants all of
1000          * them.
1001          */
1002         if ((arglist & CAM_ARG_INQ_MASK) == 0)
1003                 arglist |= CAM_ARG_INQ_MASK;
1004
1005         if (arglist & CAM_ARG_GET_STDINQ)
1006                 error = scsiinquiry(device, task_attr, retry_count, timeout);
1007
1008         if (error != 0)
1009                 return (error);
1010
1011         if (arglist & CAM_ARG_GET_SERIAL)
1012                 scsiserial(device, task_attr, retry_count, timeout);
1013
1014         if (arglist & CAM_ARG_GET_XFERRATE)
1015                 error = camxferrate(device);
1016
1017         return (error);
1018 }
1019
1020 static int
1021 scsiinquiry(struct cam_device *device, int task_attr, int retry_count,
1022             int timeout)
1023 {
1024         union ccb *ccb;
1025         struct scsi_inquiry_data *inq_buf;
1026         int error = 0;
1027
1028         ccb = cam_getccb(device);
1029
1030         if (ccb == NULL) {
1031                 warnx("couldn't allocate CCB");
1032                 return (1);
1033         }
1034
1035         /* cam_getccb cleans up the header, caller has to zero the payload */
1036         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
1037
1038         inq_buf = (struct scsi_inquiry_data *)malloc(
1039                 sizeof(struct scsi_inquiry_data));
1040
1041         if (inq_buf == NULL) {
1042                 cam_freeccb(ccb);
1043                 warnx("can't malloc memory for inquiry\n");
1044                 return (1);
1045         }
1046         bzero(inq_buf, sizeof(*inq_buf));
1047
1048         /*
1049          * Note that although the size of the inquiry buffer is the full
1050          * 256 bytes specified in the SCSI spec, we only tell the device
1051          * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
1052          * two reasons for this:
1053          *
1054          *  - The SCSI spec says that when a length field is only 1 byte,
1055          *    a value of 0 will be interpreted as 256.  Therefore
1056          *    scsi_inquiry() will convert an inq_len (which is passed in as
1057          *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
1058          *    to 0.  Evidently, very few devices meet the spec in that
1059          *    regard.  Some devices, like many Seagate disks, take the 0 as
1060          *    0, and don't return any data.  One Pioneer DVD-R drive
1061          *    returns more data than the command asked for.
1062          *
1063          *    So, since there are numerous devices that just don't work
1064          *    right with the full inquiry size, we don't send the full size.
1065          *
1066          *  - The second reason not to use the full inquiry data length is
1067          *    that we don't need it here.  The only reason we issue a
1068          *    standard inquiry is to get the vendor name, device name,
1069          *    and revision so scsi_print_inquiry() can print them.
1070          *
1071          * If, at some point in the future, more inquiry data is needed for
1072          * some reason, this code should use a procedure similar to the
1073          * probe code.  i.e., issue a short inquiry, and determine from
1074          * the additional length passed back from the device how much
1075          * inquiry data the device supports.  Once the amount the device
1076          * supports is determined, issue an inquiry for that amount and no
1077          * more.
1078          *
1079          * KDM, 2/18/2000
1080          */
1081         scsi_inquiry(&ccb->csio,
1082                      /* retries */ retry_count,
1083                      /* cbfcnp */ NULL,
1084                      /* tag_action */ task_attr,
1085                      /* inq_buf */ (u_int8_t *)inq_buf,
1086                      /* inq_len */ SHORT_INQUIRY_LENGTH,
1087                      /* evpd */ 0,
1088                      /* page_code */ 0,
1089                      /* sense_len */ SSD_FULL_SIZE,
1090                      /* timeout */ timeout ? timeout : 5000);
1091
1092         /* Disable freezing the device queue */
1093         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1094
1095         if (arglist & CAM_ARG_ERR_RECOVER)
1096                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1097
1098         if (cam_send_ccb(device, ccb) < 0) {
1099                 perror("error sending SCSI inquiry");
1100
1101                 if (arglist & CAM_ARG_VERBOSE) {
1102                         cam_error_print(device, ccb, CAM_ESF_ALL,
1103                                         CAM_EPF_ALL, stderr);
1104                 }
1105
1106                 cam_freeccb(ccb);
1107                 return (1);
1108         }
1109
1110         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1111                 error = 1;
1112
1113                 if (arglist & CAM_ARG_VERBOSE) {
1114                         cam_error_print(device, ccb, CAM_ESF_ALL,
1115                                         CAM_EPF_ALL, stderr);
1116                 }
1117         }
1118
1119         cam_freeccb(ccb);
1120
1121         if (error != 0) {
1122                 free(inq_buf);
1123                 return (error);
1124         }
1125
1126         fprintf(stdout, "%s%d: ", device->device_name,
1127                 device->dev_unit_num);
1128         scsi_print_inquiry(inq_buf);
1129
1130         free(inq_buf);
1131
1132         return (0);
1133 }
1134
1135 static int
1136 scsiserial(struct cam_device *device, int task_attr, int retry_count,
1137            int timeout)
1138 {
1139         union ccb *ccb;
1140         struct scsi_vpd_unit_serial_number *serial_buf;
1141         char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
1142         int error = 0;
1143
1144         ccb = cam_getccb(device);
1145
1146         if (ccb == NULL) {
1147                 warnx("couldn't allocate CCB");
1148                 return (1);
1149         }
1150
1151         /* cam_getccb cleans up the header, caller has to zero the payload */
1152         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
1153
1154         serial_buf = (struct scsi_vpd_unit_serial_number *)
1155                 malloc(sizeof(*serial_buf));
1156
1157         if (serial_buf == NULL) {
1158                 cam_freeccb(ccb);
1159                 warnx("can't malloc memory for serial number");
1160                 return (1);
1161         }
1162
1163         scsi_inquiry(&ccb->csio,
1164                      /*retries*/ retry_count,
1165                      /*cbfcnp*/ NULL,
1166                      /* tag_action */ task_attr,
1167                      /* inq_buf */ (u_int8_t *)serial_buf,
1168                      /* inq_len */ sizeof(*serial_buf),
1169                      /* evpd */ 1,
1170                      /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
1171                      /* sense_len */ SSD_FULL_SIZE,
1172                      /* timeout */ timeout ? timeout : 5000);
1173
1174         /* Disable freezing the device queue */
1175         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1176
1177         if (arglist & CAM_ARG_ERR_RECOVER)
1178                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1179
1180         if (cam_send_ccb(device, ccb) < 0) {
1181                 warn("error getting serial number");
1182
1183                 if (arglist & CAM_ARG_VERBOSE) {
1184                         cam_error_print(device, ccb, CAM_ESF_ALL,
1185                                         CAM_EPF_ALL, stderr);
1186                 }
1187
1188                 cam_freeccb(ccb);
1189                 free(serial_buf);
1190                 return (1);
1191         }
1192
1193         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1194                 error = 1;
1195
1196                 if (arglist & CAM_ARG_VERBOSE) {
1197                         cam_error_print(device, ccb, CAM_ESF_ALL,
1198                                         CAM_EPF_ALL, stderr);
1199                 }
1200         }
1201
1202         cam_freeccb(ccb);
1203
1204         if (error != 0) {
1205                 free(serial_buf);
1206                 return (error);
1207         }
1208
1209         bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
1210         serial_num[serial_buf->length] = '\0';
1211
1212         if ((arglist & CAM_ARG_GET_STDINQ)
1213          || (arglist & CAM_ARG_GET_XFERRATE))
1214                 fprintf(stdout, "%s%d: Serial Number ",
1215                         device->device_name, device->dev_unit_num);
1216
1217         fprintf(stdout, "%.60s\n", serial_num);
1218
1219         free(serial_buf);
1220
1221         return (0);
1222 }
1223
1224 int
1225 camxferrate(struct cam_device *device)
1226 {
1227         struct ccb_pathinq cpi;
1228         u_int32_t freq = 0;
1229         u_int32_t speed = 0;
1230         union ccb *ccb;
1231         u_int mb;
1232         int retval = 0;
1233
1234         if ((retval = get_cpi(device, &cpi)) != 0)
1235                 return (1);
1236
1237         ccb = cam_getccb(device);
1238
1239         if (ccb == NULL) {
1240                 warnx("couldn't allocate CCB");
1241                 return (1);
1242         }
1243
1244         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
1245
1246         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1247         ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
1248
1249         if (((retval = cam_send_ccb(device, ccb)) < 0)
1250          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1251                 const char error_string[] = "error getting transfer settings";
1252
1253                 if (retval < 0)
1254                         warn(error_string);
1255                 else
1256                         warnx(error_string);
1257
1258                 if (arglist & CAM_ARG_VERBOSE)
1259                         cam_error_print(device, ccb, CAM_ESF_ALL,
1260                                         CAM_EPF_ALL, stderr);
1261
1262                 retval = 1;
1263
1264                 goto xferrate_bailout;
1265
1266         }
1267
1268         speed = cpi.base_transfer_speed;
1269         freq = 0;
1270         if (ccb->cts.transport == XPORT_SPI) {
1271                 struct ccb_trans_settings_spi *spi =
1272                     &ccb->cts.xport_specific.spi;
1273
1274                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1275                         freq = scsi_calc_syncsrate(spi->sync_period);
1276                         speed = freq;
1277                 }
1278                 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1279                         speed *= (0x01 << spi->bus_width);
1280                 }
1281         } else if (ccb->cts.transport == XPORT_FC) {
1282                 struct ccb_trans_settings_fc *fc =
1283                     &ccb->cts.xport_specific.fc;
1284
1285                 if (fc->valid & CTS_FC_VALID_SPEED)
1286                         speed = fc->bitrate;
1287         } else if (ccb->cts.transport == XPORT_SAS) {
1288                 struct ccb_trans_settings_sas *sas =
1289                     &ccb->cts.xport_specific.sas;
1290
1291                 if (sas->valid & CTS_SAS_VALID_SPEED)
1292                         speed = sas->bitrate;
1293         } else if (ccb->cts.transport == XPORT_ATA) {
1294                 struct ccb_trans_settings_pata *pata =
1295                     &ccb->cts.xport_specific.ata;
1296
1297                 if (pata->valid & CTS_ATA_VALID_MODE)
1298                         speed = ata_mode2speed(pata->mode);
1299         } else if (ccb->cts.transport == XPORT_SATA) {
1300                 struct  ccb_trans_settings_sata *sata =
1301                     &ccb->cts.xport_specific.sata;
1302
1303                 if (sata->valid & CTS_SATA_VALID_REVISION)
1304                         speed = ata_revision2speed(sata->revision);
1305         }
1306
1307         mb = speed / 1000;
1308         if (mb > 0) {
1309                 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1310                         device->device_name, device->dev_unit_num,
1311                         mb, speed % 1000);
1312         } else {
1313                 fprintf(stdout, "%s%d: %dKB/s transfers",
1314                         device->device_name, device->dev_unit_num,
1315                         speed);
1316         }
1317
1318         if (ccb->cts.transport == XPORT_SPI) {
1319                 struct ccb_trans_settings_spi *spi =
1320                     &ccb->cts.xport_specific.spi;
1321
1322                 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1323                  && (spi->sync_offset != 0))
1324                         fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1325                                 freq % 1000, spi->sync_offset);
1326
1327                 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1328                  && (spi->bus_width > 0)) {
1329                         if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1330                          && (spi->sync_offset != 0)) {
1331                                 fprintf(stdout, ", ");
1332                         } else {
1333                                 fprintf(stdout, " (");
1334                         }
1335                         fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1336                 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1337                  && (spi->sync_offset != 0)) {
1338                         fprintf(stdout, ")");
1339                 }
1340         } else if (ccb->cts.transport == XPORT_ATA) {
1341                 struct ccb_trans_settings_pata *pata =
1342                     &ccb->cts.xport_specific.ata;
1343
1344                 printf(" (");
1345                 if (pata->valid & CTS_ATA_VALID_MODE)
1346                         printf("%s, ", ata_mode2string(pata->mode));
1347                 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1348                         printf("ATAPI %dbytes, ", pata->atapi);
1349                 if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1350                         printf("PIO %dbytes", pata->bytecount);
1351                 printf(")");
1352         } else if (ccb->cts.transport == XPORT_SATA) {
1353                 struct ccb_trans_settings_sata *sata =
1354                     &ccb->cts.xport_specific.sata;
1355
1356                 printf(" (");
1357                 if (sata->valid & CTS_SATA_VALID_REVISION)
1358                         printf("SATA %d.x, ", sata->revision);
1359                 else
1360                         printf("SATA, ");
1361                 if (sata->valid & CTS_SATA_VALID_MODE)
1362                         printf("%s, ", ata_mode2string(sata->mode));
1363                 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1364                         printf("ATAPI %dbytes, ", sata->atapi);
1365                 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1366                         printf("PIO %dbytes", sata->bytecount);
1367                 printf(")");
1368         }
1369
1370         if (ccb->cts.protocol == PROTO_SCSI) {
1371                 struct ccb_trans_settings_scsi *scsi =
1372                     &ccb->cts.proto_specific.scsi;
1373                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1374                         if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1375                                 fprintf(stdout, ", Command Queueing Enabled");
1376                         }
1377                 }
1378         }
1379
1380         fprintf(stdout, "\n");
1381
1382 xferrate_bailout:
1383
1384         cam_freeccb(ccb);
1385
1386         return (retval);
1387 }
1388
1389 static void
1390 atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
1391 {
1392         u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1393                                 ((u_int32_t)parm->lba_size_2 << 16);
1394
1395         u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1396                                 ((u_int64_t)parm->lba_size48_2 << 16) |
1397                                 ((u_int64_t)parm->lba_size48_3 << 32) |
1398                                 ((u_int64_t)parm->lba_size48_4 << 48);
1399
1400         if (header) {
1401                 printf("\nFeature                      "
1402                        "Support  Enabled   Value\n");
1403         }
1404
1405         printf("Host Protected Area (HPA)      ");
1406         if (parm->support.command1 & ATA_SUPPORT_PROTECTED) {
1407                 u_int64_t lba = lbasize48 ? lbasize48 : lbasize;
1408                 printf("yes      %s     %ju/%ju\n", (hpasize > lba) ? "yes" : "no ",
1409                         lba, hpasize);
1410
1411                 printf("HPA - Security                 ");
1412                 if (parm->support.command1 & ATA_SUPPORT_MAXSECURITY)
1413                         printf("yes\n");
1414                 else
1415                         printf("no\n");
1416         } else {
1417                 printf("no\n");
1418         }
1419 }
1420
1421 static int
1422 atasata(struct ata_params *parm)
1423 {
1424
1425
1426         if (parm->satacapabilities != 0xffff &&
1427             parm->satacapabilities != 0x0000)
1428                 return 1;
1429
1430         return 0;
1431 }
1432
1433 static void
1434 atacapprint(struct ata_params *parm)
1435 {
1436         u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1437                                 ((u_int32_t)parm->lba_size_2 << 16);
1438
1439         u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1440                                 ((u_int64_t)parm->lba_size48_2 << 16) |
1441                                 ((u_int64_t)parm->lba_size48_3 << 32) |
1442                                 ((u_int64_t)parm->lba_size48_4 << 48);
1443
1444         printf("\n");
1445         printf("protocol              ");
1446         printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1447         if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1448                 if (parm->satacapabilities & ATA_SATA_GEN3)
1449                         printf(" SATA 3.x\n");
1450                 else if (parm->satacapabilities & ATA_SATA_GEN2)
1451                         printf(" SATA 2.x\n");
1452                 else if (parm->satacapabilities & ATA_SATA_GEN1)
1453                         printf(" SATA 1.x\n");
1454                 else
1455                         printf(" SATA\n");
1456         }
1457         else
1458                 printf("\n");
1459         printf("device model          %.40s\n", parm->model);
1460         printf("firmware revision     %.8s\n", parm->revision);
1461         printf("serial number         %.20s\n", parm->serial);
1462         if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1463                 printf("WWN                   %04x%04x%04x%04x\n",
1464                     parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1465         }
1466         if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1467                 printf("media serial number   %.30s\n",
1468                     parm->media_serial);
1469         }
1470
1471         printf("cylinders             %d\n", parm->cylinders);
1472         printf("heads                 %d\n", parm->heads);
1473         printf("sectors/track         %d\n", parm->sectors);
1474         printf("sector size           logical %u, physical %lu, offset %lu\n",
1475             ata_logical_sector_size(parm),
1476             (unsigned long)ata_physical_sector_size(parm),
1477             (unsigned long)ata_logical_sector_offset(parm));
1478
1479         if (parm->config == ATA_PROTO_CFA ||
1480             (parm->support.command2 & ATA_SUPPORT_CFA))
1481                 printf("CFA supported\n");
1482
1483         printf("LBA%ssupported         ",
1484                 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1485         if (lbasize)
1486                 printf("%d sectors\n", lbasize);
1487         else
1488                 printf("\n");
1489
1490         printf("LBA48%ssupported       ",
1491                 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1492         if (lbasize48)
1493                 printf("%ju sectors\n", (uintmax_t)lbasize48);
1494         else
1495                 printf("\n");
1496
1497         printf("PIO supported         PIO");
1498         switch (ata_max_pmode(parm)) {
1499         case ATA_PIO4:
1500                 printf("4");
1501                 break;
1502         case ATA_PIO3:
1503                 printf("3");
1504                 break;
1505         case ATA_PIO2:
1506                 printf("2");
1507                 break;
1508         case ATA_PIO1:
1509                 printf("1");
1510                 break;
1511         default:
1512                 printf("0");
1513         }
1514         if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1515                 printf(" w/o IORDY");
1516         printf("\n");
1517
1518         printf("DMA%ssupported         ",
1519                 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1520         if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1521                 if (parm->mwdmamodes & 0xff) {
1522                         printf("WDMA");
1523                         if (parm->mwdmamodes & 0x04)
1524                                 printf("2");
1525                         else if (parm->mwdmamodes & 0x02)
1526                                 printf("1");
1527                         else if (parm->mwdmamodes & 0x01)
1528                                 printf("0");
1529                         printf(" ");
1530                 }
1531                 if ((parm->atavalid & ATA_FLAG_88) &&
1532                     (parm->udmamodes & 0xff)) {
1533                         printf("UDMA");
1534                         if (parm->udmamodes & 0x40)
1535                                 printf("6");
1536                         else if (parm->udmamodes & 0x20)
1537                                 printf("5");
1538                         else if (parm->udmamodes & 0x10)
1539                                 printf("4");
1540                         else if (parm->udmamodes & 0x08)
1541                                 printf("3");
1542                         else if (parm->udmamodes & 0x04)
1543                                 printf("2");
1544                         else if (parm->udmamodes & 0x02)
1545                                 printf("1");
1546                         else if (parm->udmamodes & 0x01)
1547                                 printf("0");
1548                         printf(" ");
1549                 }
1550         }
1551         printf("\n");
1552
1553         if (parm->media_rotation_rate == 1) {
1554                 printf("media RPM             non-rotating\n");
1555         } else if (parm->media_rotation_rate >= 0x0401 &&
1556             parm->media_rotation_rate <= 0xFFFE) {
1557                 printf("media RPM             %d\n",
1558                         parm->media_rotation_rate);
1559         }
1560
1561         printf("Zoned-Device Commands ");
1562         switch (parm->support3 & ATA_SUPPORT_ZONE_MASK) {
1563                 case ATA_SUPPORT_ZONE_DEV_MANAGED:
1564                         printf("device managed\n");
1565                         break;
1566                 case ATA_SUPPORT_ZONE_HOST_AWARE:
1567                         printf("host aware\n");
1568                         break;
1569                 default:
1570                         printf("no\n");
1571         }
1572
1573         printf("\nFeature                      "
1574                 "Support  Enabled   Value           Vendor\n");
1575         printf("read ahead                     %s       %s\n",
1576                 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1577                 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1578         printf("write cache                    %s       %s\n",
1579                 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1580                 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1581         printf("flush cache                    %s       %s\n",
1582                 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1583                 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1584         printf("overlap                        %s\n",
1585                 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1586         printf("Tagged Command Queuing (TCQ)   %s       %s",
1587                 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1588                 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1589                 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1590                         printf("        %d tags\n",
1591                             ATA_QUEUE_LEN(parm->queue) + 1);
1592                 } else
1593                         printf("\n");
1594         printf("Native Command Queuing (NCQ)   ");
1595         if (parm->satacapabilities != 0xffff &&
1596             (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1597                 printf("yes             %d tags\n",
1598                     ATA_QUEUE_LEN(parm->queue) + 1);
1599         } else
1600                 printf("no\n");
1601
1602         printf("NCQ Queue Management           %s\n", atasata(parm) &&
1603                 parm->satacapabilities2 & ATA_SUPPORT_NCQ_QMANAGEMENT ?
1604                 "yes" : "no");
1605         printf("NCQ Streaming                  %s\n", atasata(parm) &&
1606                 parm->satacapabilities2 & ATA_SUPPORT_NCQ_STREAM ?
1607                 "yes" : "no");
1608         printf("Receive & Send FPDMA Queued    %s\n", atasata(parm) &&
1609                 parm->satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED ?
1610                 "yes" : "no");
1611
1612         printf("SMART                          %s       %s\n",
1613                 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1614                 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1615         printf("microcode download             %s       %s\n",
1616                 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1617                 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1618         printf("security                       %s       %s\n",
1619                 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1620                 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1621         printf("power management               %s       %s\n",
1622                 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1623                 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1624         printf("advanced power management      %s       %s",
1625                 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1626                 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1627                 if (parm->support.command2 & ATA_SUPPORT_APM) {
1628                         printf("        %d/0x%02X\n",
1629                             parm->apm_value & 0xff, parm->apm_value & 0xff);
1630                 } else
1631                         printf("\n");
1632         printf("automatic acoustic management  %s       %s",
1633                 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1634                 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1635                 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1636                         printf("        %d/0x%02X       %d/0x%02X\n",
1637                             ATA_ACOUSTIC_CURRENT(parm->acoustic),
1638                             ATA_ACOUSTIC_CURRENT(parm->acoustic),
1639                             ATA_ACOUSTIC_VENDOR(parm->acoustic),
1640                             ATA_ACOUSTIC_VENDOR(parm->acoustic));
1641                 } else
1642                         printf("\n");
1643         printf("media status notification      %s       %s\n",
1644                 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1645                 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1646         printf("power-up in Standby            %s       %s\n",
1647                 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1648                 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1649         printf("write-read-verify              %s       %s",
1650                 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1651                 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1652                 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1653                         printf("        %d/0x%x\n",
1654                             parm->wrv_mode, parm->wrv_mode);
1655                 } else
1656                         printf("\n");
1657         printf("unload                         %s       %s\n",
1658                 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1659                 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1660         printf("general purpose logging        %s       %s\n",
1661                 parm->support.extension & ATA_SUPPORT_GENLOG ? "yes" : "no",
1662                 parm->enabled.extension & ATA_SUPPORT_GENLOG ? "yes" : "no");
1663         printf("free-fall                      %s       %s\n",
1664                 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1665                 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1666         printf("Data Set Management (DSM/TRIM) ");
1667         if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) {
1668                 printf("yes\n");
1669                 printf("DSM - max 512byte blocks       ");
1670                 if (parm->max_dsm_blocks == 0x00)
1671                         printf("yes              not specified\n");
1672                 else
1673                         printf("yes              %d\n",
1674                                 parm->max_dsm_blocks);
1675
1676                 printf("DSM - deterministic read       ");
1677                 if (parm->support3 & ATA_SUPPORT_DRAT) {
1678                         if (parm->support3 & ATA_SUPPORT_RZAT)
1679                                 printf("yes              zeroed\n");
1680                         else
1681                                 printf("yes              any value\n");
1682                 } else {
1683                         printf("no\n");
1684                 }
1685         } else {
1686                 printf("no\n");
1687         }
1688 }
1689
1690 static int
1691 scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
1692 {
1693         struct ata_pass_16 *ata_pass_16;
1694         struct ata_cmd ata_cmd;
1695
1696         ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
1697         ata_cmd.command = ata_pass_16->command;
1698         ata_cmd.control = ata_pass_16->control;
1699         ata_cmd.features = ata_pass_16->features;
1700
1701         if (arglist & CAM_ARG_VERBOSE) {
1702                 warnx("sending ATA %s via pass_16 with timeout of %u msecs",
1703                       ata_op_string(&ata_cmd),
1704                       ccb->csio.ccb_h.timeout);
1705         }
1706
1707         /* Disable freezing the device queue */
1708         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1709
1710         if (arglist & CAM_ARG_ERR_RECOVER)
1711                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1712
1713         if (cam_send_ccb(device, ccb) < 0) {
1714                 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1715                         warn("error sending ATA %s via pass_16",
1716                              ata_op_string(&ata_cmd));
1717                 }
1718
1719                 if (arglist & CAM_ARG_VERBOSE) {
1720                         cam_error_print(device, ccb, CAM_ESF_ALL,
1721                                         CAM_EPF_ALL, stderr);
1722                 }
1723
1724                 return (1);
1725         }
1726
1727         if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
1728             (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1729                 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1730                         warnx("ATA %s via pass_16 failed",
1731                               ata_op_string(&ata_cmd));
1732                 }
1733                 if (arglist & CAM_ARG_VERBOSE) {
1734                         cam_error_print(device, ccb, CAM_ESF_ALL,
1735                                         CAM_EPF_ALL, stderr);
1736                 }
1737
1738                 return (1);
1739         }
1740
1741         return (0);
1742 }
1743
1744
1745 static int
1746 ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
1747 {
1748         if (arglist & CAM_ARG_VERBOSE) {
1749                 warnx("sending ATA %s with timeout of %u msecs",
1750                       ata_op_string(&(ccb->ataio.cmd)),
1751                       ccb->ataio.ccb_h.timeout);
1752         }
1753
1754         /* Disable freezing the device queue */
1755         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1756
1757         if (arglist & CAM_ARG_ERR_RECOVER)
1758                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1759
1760         if (cam_send_ccb(device, ccb) < 0) {
1761                 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1762                         warn("error sending ATA %s",
1763                              ata_op_string(&(ccb->ataio.cmd)));
1764                 }
1765
1766                 if (arglist & CAM_ARG_VERBOSE) {
1767                         cam_error_print(device, ccb, CAM_ESF_ALL,
1768                                         CAM_EPF_ALL, stderr);
1769                 }
1770
1771                 return (1);
1772         }
1773
1774         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1775                 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1776                         warnx("ATA %s failed: %d",
1777                               ata_op_string(&(ccb->ataio.cmd)), quiet);
1778                 }
1779
1780                 if (arglist & CAM_ARG_VERBOSE) {
1781                         cam_error_print(device, ccb, CAM_ESF_ALL,
1782                                         CAM_EPF_ALL, stderr);
1783                 }
1784
1785                 return (1);
1786         }
1787
1788         return (0);
1789 }
1790
1791 static int
1792 ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
1793                u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1794                u_int8_t tag_action, u_int8_t command, u_int8_t features,
1795                u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1796                u_int16_t dxfer_len, int timeout, int quiet)
1797 {
1798         if (data_ptr != NULL) {
1799                 ata_flags |= AP_FLAG_BYT_BLOK_BYTES |
1800                             AP_FLAG_TLEN_SECT_CNT;
1801                 if (flags & CAM_DIR_OUT)
1802                         ata_flags |= AP_FLAG_TDIR_TO_DEV;
1803                 else
1804                         ata_flags |= AP_FLAG_TDIR_FROM_DEV;
1805         } else {
1806                 ata_flags |= AP_FLAG_TLEN_NO_DATA;
1807         }
1808
1809         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
1810
1811         scsi_ata_pass_16(&ccb->csio,
1812                          retries,
1813                          NULL,
1814                          flags,
1815                          tag_action,
1816                          protocol,
1817                          ata_flags,
1818                          features,
1819                          sector_count,
1820                          lba,
1821                          command,
1822                          /*control*/0,
1823                          data_ptr,
1824                          dxfer_len,
1825                          /*sense_len*/SSD_FULL_SIZE,
1826                          timeout);
1827
1828         return scsi_cam_pass_16_send(device, ccb, quiet);
1829 }
1830
1831 static int
1832 ata_try_pass_16(struct cam_device *device)
1833 {
1834         struct ccb_pathinq cpi;
1835
1836         if (get_cpi(device, &cpi) != 0) {
1837                 warnx("couldn't get CPI");
1838                 return (-1);
1839         }
1840
1841         if (cpi.protocol == PROTO_SCSI) {
1842                 /* possibly compatible with pass_16 */
1843                 return (1);
1844         }
1845
1846         /* likely not compatible with pass_16 */
1847         return (0);
1848 }
1849
1850 static int
1851 ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries,
1852                  u_int32_t flags, u_int8_t protocol, u_int8_t tag_action,
1853                  u_int8_t command, u_int8_t features, u_int32_t lba,
1854                  u_int8_t sector_count, u_int8_t *data_ptr, u_int16_t dxfer_len,
1855                  int timeout, int quiet)
1856 {
1857
1858
1859         switch (ata_try_pass_16(device)) {
1860         case -1:
1861                 return (1);
1862         case 1:
1863                 /* Try using SCSI Passthrough */
1864                 return ata_do_pass_16(device, ccb, retries, flags, protocol,
1865                                       0, tag_action, command, features, lba,
1866                                       sector_count, data_ptr, dxfer_len,
1867                                       timeout, quiet);
1868         }
1869
1870         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->ataio);
1871         cam_fill_ataio(&ccb->ataio,
1872                        retries,
1873                        NULL,
1874                        flags,
1875                        tag_action,
1876                        data_ptr,
1877                        dxfer_len,
1878                        timeout);
1879
1880         ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1881         return ata_cam_send(device, ccb, quiet);
1882 }
1883
1884 static int
1885 ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
1886            u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1887            u_int8_t tag_action, u_int8_t command, u_int8_t features,
1888            u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1889            u_int16_t dxfer_len, int timeout, int force48bit)
1890 {
1891         int retval;
1892
1893         retval = ata_try_pass_16(device);
1894         if (retval == -1)
1895                 return (1);
1896
1897         if (retval == 1) {
1898                 int error;
1899
1900                 /* Try using SCSI Passthrough */
1901                 error = ata_do_pass_16(device, ccb, retries, flags, protocol,
1902                                       ata_flags, tag_action, command, features,
1903                                       lba, sector_count, data_ptr, dxfer_len,
1904                                       timeout, 0);
1905
1906                 if (ata_flags & AP_FLAG_CHK_COND) {
1907                         /* Decode ata_res from sense data */
1908                         struct ata_res_pass16 *res_pass16;
1909                         struct ata_res *res;
1910                         u_int i;
1911                         u_int16_t *ptr;
1912
1913                         /* sense_data is 4 byte aligned */
1914                         ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data;
1915                         for (i = 0; i < sizeof(*res_pass16) / 2; i++)
1916                                 ptr[i] = le16toh(ptr[i]);
1917
1918                         /* sense_data is 4 byte aligned */
1919                         res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
1920                             &ccb->csio.sense_data;
1921                         res = &ccb->ataio.res;
1922                         res->flags = res_pass16->flags;
1923                         res->status = res_pass16->status;
1924                         res->error = res_pass16->error;
1925                         res->lba_low = res_pass16->lba_low;
1926                         res->lba_mid = res_pass16->lba_mid;
1927                         res->lba_high = res_pass16->lba_high;
1928                         res->device = res_pass16->device;
1929                         res->lba_low_exp = res_pass16->lba_low_exp;
1930                         res->lba_mid_exp = res_pass16->lba_mid_exp;
1931                         res->lba_high_exp = res_pass16->lba_high_exp;
1932                         res->sector_count = res_pass16->sector_count;
1933                         res->sector_count_exp = res_pass16->sector_count_exp;
1934                 }
1935
1936                 return (error);
1937         }
1938
1939         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->ataio);
1940         cam_fill_ataio(&ccb->ataio,
1941                        retries,
1942                        NULL,
1943                        flags,
1944                        tag_action,
1945                        data_ptr,
1946                        dxfer_len,
1947                        timeout);
1948
1949         if (force48bit || lba > ATA_MAX_28BIT_LBA)
1950                 ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1951         else
1952                 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1953
1954         if (ata_flags & AP_FLAG_CHK_COND)
1955                 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
1956
1957         return ata_cam_send(device, ccb, 0);
1958 }
1959
1960 static void
1961 dump_data(uint16_t *ptr, uint32_t len)
1962 {
1963         u_int i;
1964
1965         for (i = 0; i < len / 2; i++) {
1966                 if ((i % 8) == 0)
1967                         printf(" %3d: ", i);
1968                 printf("%04hx ", ptr[i]);
1969                 if ((i % 8) == 7)
1970                         printf("\n");
1971         }
1972         if ((i % 8) != 7)
1973                 printf("\n");
1974 }
1975
1976 static int
1977 atahpa_proc_resp(struct cam_device *device, union ccb *ccb,
1978                  int is48bit, u_int64_t *hpasize)
1979 {
1980         struct ata_res *res;
1981
1982         res = &ccb->ataio.res;
1983         if (res->status & ATA_STATUS_ERROR) {
1984                 if (arglist & CAM_ARG_VERBOSE) {
1985                         cam_error_print(device, ccb, CAM_ESF_ALL,
1986                                         CAM_EPF_ALL, stderr);
1987                         printf("error = 0x%02x, sector_count = 0x%04x, "
1988                                "device = 0x%02x, status = 0x%02x\n",
1989                                res->error, res->sector_count,
1990                                res->device, res->status);
1991                 }
1992
1993                 if (res->error & ATA_ERROR_ID_NOT_FOUND) {
1994                         warnx("Max address has already been set since "
1995                               "last power-on or hardware reset");
1996                 }
1997
1998                 return (1);
1999         }
2000
2001         if (arglist & CAM_ARG_VERBOSE) {
2002                 fprintf(stdout, "%s%d: Raw native max data:\n",
2003                         device->device_name, device->dev_unit_num);
2004                 /* res is 4 byte aligned */
2005                 dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
2006
2007                 printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
2008                        "status = 0x%02x\n", res->error, res->sector_count,
2009                        res->device, res->status);
2010         }
2011
2012         if (hpasize != NULL) {
2013                 if (is48bit) {
2014                         *hpasize = (((u_int64_t)((res->lba_high_exp << 16) |
2015                             (res->lba_mid_exp << 8) | res->lba_low_exp) << 24) |
2016                             ((res->lba_high << 16) | (res->lba_mid << 8) |
2017                             res->lba_low)) + 1;
2018                 } else {
2019                         *hpasize = (((res->device & 0x0f) << 24) |
2020                             (res->lba_high << 16) | (res->lba_mid << 8) |
2021                             res->lba_low) + 1;
2022                 }
2023         }
2024
2025         return (0);
2026 }
2027
2028 static int
2029 ata_read_native_max(struct cam_device *device, int retry_count,
2030                       u_int32_t timeout, union ccb *ccb,
2031                       struct ata_params *parm, u_int64_t *hpasize)
2032 {
2033         int error;
2034         u_int cmd, is48bit;
2035         u_int8_t protocol;
2036
2037         is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48;
2038         protocol = AP_PROTO_NON_DATA;
2039
2040         if (is48bit) {
2041                 cmd = ATA_READ_NATIVE_MAX_ADDRESS48;
2042                 protocol |= AP_EXTEND;
2043         } else {
2044                 cmd = ATA_READ_NATIVE_MAX_ADDRESS;
2045         }
2046
2047         error = ata_do_cmd(device,
2048                            ccb,
2049                            retry_count,
2050                            /*flags*/CAM_DIR_NONE,
2051                            /*protocol*/protocol,
2052                            /*ata_flags*/AP_FLAG_CHK_COND,
2053                            /*tag_action*/MSG_SIMPLE_Q_TAG,
2054                            /*command*/cmd,
2055                            /*features*/0,
2056                            /*lba*/0,
2057                            /*sector_count*/0,
2058                            /*data_ptr*/NULL,
2059                            /*dxfer_len*/0,
2060                            timeout ? timeout : 1000,
2061                            is48bit);
2062
2063         if (error)
2064                 return (error);
2065
2066         return atahpa_proc_resp(device, ccb, is48bit, hpasize);
2067 }
2068
2069 static int
2070 atahpa_set_max(struct cam_device *device, int retry_count,
2071               u_int32_t timeout, union ccb *ccb,
2072               int is48bit, u_int64_t maxsize, int persist)
2073 {
2074         int error;
2075         u_int cmd;
2076         u_int8_t protocol;
2077
2078         protocol = AP_PROTO_NON_DATA;
2079
2080         if (is48bit) {
2081                 cmd = ATA_SET_MAX_ADDRESS48;
2082                 protocol |= AP_EXTEND;
2083         } else {
2084                 cmd = ATA_SET_MAX_ADDRESS;
2085         }
2086
2087         /* lba's are zero indexed so the max lba is requested max - 1 */
2088         if (maxsize)
2089                 maxsize--;
2090
2091         error = ata_do_cmd(device,
2092                            ccb,
2093                            retry_count,
2094                            /*flags*/CAM_DIR_NONE,
2095                            /*protocol*/protocol,
2096                            /*ata_flags*/AP_FLAG_CHK_COND,
2097                            /*tag_action*/MSG_SIMPLE_Q_TAG,
2098                            /*command*/cmd,
2099                            /*features*/ATA_HPA_FEAT_MAX_ADDR,
2100                            /*lba*/maxsize,
2101                            /*sector_count*/persist,
2102                            /*data_ptr*/NULL,
2103                            /*dxfer_len*/0,
2104                            timeout ? timeout : 1000,
2105                            is48bit);
2106
2107         if (error)
2108                 return (error);
2109
2110         return atahpa_proc_resp(device, ccb, is48bit, NULL);
2111 }
2112
2113 static int
2114 atahpa_password(struct cam_device *device, int retry_count,
2115                 u_int32_t timeout, union ccb *ccb,
2116                 int is48bit, struct ata_set_max_pwd *pwd)
2117 {
2118         int error;
2119         u_int cmd;
2120         u_int8_t protocol;
2121
2122         protocol = AP_PROTO_PIO_OUT;
2123         cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2124
2125         error = ata_do_cmd(device,
2126                            ccb,
2127                            retry_count,
2128                            /*flags*/CAM_DIR_OUT,
2129                            /*protocol*/protocol,
2130                            /*ata_flags*/AP_FLAG_CHK_COND,
2131                            /*tag_action*/MSG_SIMPLE_Q_TAG,
2132                            /*command*/cmd,
2133                            /*features*/ATA_HPA_FEAT_SET_PWD,
2134                            /*lba*/0,
2135                            /*sector_count*/0,
2136                            /*data_ptr*/(u_int8_t*)pwd,
2137                            /*dxfer_len*/sizeof(struct ata_set_max_pwd),
2138                            timeout ? timeout : 1000,
2139                            is48bit);
2140
2141         if (error)
2142                 return (error);
2143
2144         return atahpa_proc_resp(device, ccb, is48bit, NULL);
2145 }
2146
2147 static int
2148 atahpa_lock(struct cam_device *device, int retry_count,
2149             u_int32_t timeout, union ccb *ccb, int is48bit)
2150 {
2151         int error;
2152         u_int cmd;
2153         u_int8_t protocol;
2154
2155         protocol = AP_PROTO_NON_DATA;
2156         cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2157
2158         error = ata_do_cmd(device,
2159                            ccb,
2160                            retry_count,
2161                            /*flags*/CAM_DIR_NONE,
2162                            /*protocol*/protocol,
2163                            /*ata_flags*/AP_FLAG_CHK_COND,
2164                            /*tag_action*/MSG_SIMPLE_Q_TAG,
2165                            /*command*/cmd,
2166                            /*features*/ATA_HPA_FEAT_LOCK,
2167                            /*lba*/0,
2168                            /*sector_count*/0,
2169                            /*data_ptr*/NULL,
2170                            /*dxfer_len*/0,
2171                            timeout ? timeout : 1000,
2172                            is48bit);
2173
2174         if (error)
2175                 return (error);
2176
2177         return atahpa_proc_resp(device, ccb, is48bit, NULL);
2178 }
2179
2180 static int
2181 atahpa_unlock(struct cam_device *device, int retry_count,
2182               u_int32_t timeout, union ccb *ccb,
2183               int is48bit, struct ata_set_max_pwd *pwd)
2184 {
2185         int error;
2186         u_int cmd;
2187         u_int8_t protocol;
2188
2189         protocol = AP_PROTO_PIO_OUT;
2190         cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2191
2192         error = ata_do_cmd(device,
2193                            ccb,
2194                            retry_count,
2195                            /*flags*/CAM_DIR_OUT,
2196                            /*protocol*/protocol,
2197                            /*ata_flags*/AP_FLAG_CHK_COND,
2198                            /*tag_action*/MSG_SIMPLE_Q_TAG,
2199                            /*command*/cmd,
2200                            /*features*/ATA_HPA_FEAT_UNLOCK,
2201                            /*lba*/0,
2202                            /*sector_count*/0,
2203                            /*data_ptr*/(u_int8_t*)pwd,
2204                            /*dxfer_len*/sizeof(struct ata_set_max_pwd),
2205                            timeout ? timeout : 1000,
2206                            is48bit);
2207
2208         if (error)
2209                 return (error);
2210
2211         return atahpa_proc_resp(device, ccb, is48bit, NULL);
2212 }
2213
2214 static int
2215 atahpa_freeze_lock(struct cam_device *device, int retry_count,
2216                    u_int32_t timeout, union ccb *ccb, int is48bit)
2217 {
2218         int error;
2219         u_int cmd;
2220         u_int8_t protocol;
2221
2222         protocol = AP_PROTO_NON_DATA;
2223         cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2224
2225         error = ata_do_cmd(device,
2226                            ccb,
2227                            retry_count,
2228                            /*flags*/CAM_DIR_NONE,
2229                            /*protocol*/protocol,
2230                            /*ata_flags*/AP_FLAG_CHK_COND,
2231                            /*tag_action*/MSG_SIMPLE_Q_TAG,
2232                            /*command*/cmd,
2233                            /*features*/ATA_HPA_FEAT_FREEZE,
2234                            /*lba*/0,
2235                            /*sector_count*/0,
2236                            /*data_ptr*/NULL,
2237                            /*dxfer_len*/0,
2238                            timeout ? timeout : 1000,
2239                            is48bit);
2240
2241         if (error)
2242                 return (error);
2243
2244         return atahpa_proc_resp(device, ccb, is48bit, NULL);
2245 }
2246
2247
2248 int
2249 ata_do_identify(struct cam_device *device, int retry_count, int timeout,
2250                 union ccb *ccb, struct ata_params** ident_bufp)
2251 {
2252         struct ata_params *ident_buf;
2253         struct ccb_pathinq cpi;
2254         struct ccb_getdev cgd;
2255         u_int i, error;
2256         int16_t *ptr;
2257         u_int8_t command, retry_command;
2258
2259         if (get_cpi(device, &cpi) != 0) {
2260                 warnx("couldn't get CPI");
2261                 return (-1);
2262         }
2263
2264         /* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */
2265         if (cpi.protocol == PROTO_ATA) {
2266                 if (get_cgd(device, &cgd) != 0) {
2267                         warnx("couldn't get CGD");
2268                         return (-1);
2269                 }
2270
2271                 command = (cgd.protocol == PROTO_ATA) ?
2272                     ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
2273                 retry_command = 0;
2274         } else {
2275                 /* We don't know which for sure so try both */
2276                 command = ATA_ATA_IDENTIFY;
2277                 retry_command = ATA_ATAPI_IDENTIFY;
2278         }
2279
2280         ptr = (uint16_t *)calloc(1, sizeof(struct ata_params));
2281         if (ptr == NULL) {
2282                 warnx("can't calloc memory for identify\n");
2283                 return (1);
2284         }
2285
2286         error = ata_do_28bit_cmd(device,
2287                                  ccb,
2288                                  /*retries*/retry_count,
2289                                  /*flags*/CAM_DIR_IN,
2290                                  /*protocol*/AP_PROTO_PIO_IN,
2291                                  /*tag_action*/MSG_SIMPLE_Q_TAG,
2292                                  /*command*/command,
2293                                  /*features*/0,
2294                                  /*lba*/0,
2295                                  /*sector_count*/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;
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         numblocks = 0;
7176         quiet = 0;
7177         sizeonly = 0;
7178         baseten = 0;
7179         retval = 0;
7180
7181         ccb = cam_getccb(device);
7182
7183         if (ccb == NULL) {
7184                 warnx("%s: error allocating ccb", __func__);
7185                 return (1);
7186         }
7187
7188         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
7189
7190         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7191                 switch (c) {
7192                 case 'b':
7193                         blocksizeonly++;
7194                         break;
7195                 case 'h':
7196                         humanize++;
7197                         baseten = 0;
7198                         break;
7199                 case 'H':
7200                         humanize++;
7201                         baseten++;
7202                         break;
7203                 case 'N':
7204                         numblocks++;
7205                         break;
7206                 case 'q':
7207                         quiet++;
7208                         break;
7209                 case 's':
7210                         sizeonly++;
7211                         break;
7212                 default:
7213                         break;
7214                 }
7215         }
7216
7217         if ((blocksizeonly != 0)
7218          && (numblocks != 0)) {
7219                 warnx("%s: you can only specify one of -b or -N", __func__);
7220                 retval = 1;
7221                 goto bailout;
7222         }
7223
7224         if ((blocksizeonly != 0)
7225          && (sizeonly != 0)) {
7226                 warnx("%s: you can only specify one of -b or -s", __func__);
7227                 retval = 1;
7228                 goto bailout;
7229         }
7230
7231         if ((humanize != 0)
7232          && (quiet != 0)) {
7233                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
7234                 retval = 1;
7235                 goto bailout;
7236         }
7237
7238         if ((humanize != 0)
7239          && (blocksizeonly != 0)) {
7240                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
7241                 retval = 1;
7242                 goto bailout;
7243         }
7244
7245         scsi_read_capacity(&ccb->csio,
7246                            /*retries*/ retry_count,
7247                            /*cbfcnp*/ NULL,
7248                            /*tag_action*/ task_attr,
7249                            &rcap,
7250                            SSD_FULL_SIZE,
7251                            /*timeout*/ timeout ? timeout : 5000);
7252
7253         /* Disable freezing the device queue */
7254         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7255
7256         if (arglist & CAM_ARG_ERR_RECOVER)
7257                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7258
7259         if (cam_send_ccb(device, ccb) < 0) {
7260                 warn("error sending READ CAPACITY command");
7261
7262                 if (arglist & CAM_ARG_VERBOSE)
7263                         cam_error_print(device, ccb, CAM_ESF_ALL,
7264                                         CAM_EPF_ALL, stderr);
7265
7266                 retval = 1;
7267                 goto bailout;
7268         }
7269
7270         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7271                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7272                 retval = 1;
7273                 goto bailout;
7274         }
7275
7276         maxsector = scsi_4btoul(rcap.addr);
7277         block_len = scsi_4btoul(rcap.length);
7278
7279         /*
7280          * A last block of 2^32-1 means that the true capacity is over 2TB,
7281          * and we need to issue the long READ CAPACITY to get the real
7282          * capacity.  Otherwise, we're all set.
7283          */
7284         if (maxsector != 0xffffffff)
7285                 goto do_print;
7286
7287         scsi_read_capacity_16(&ccb->csio,
7288                               /*retries*/ retry_count,
7289                               /*cbfcnp*/ NULL,
7290                               /*tag_action*/ task_attr,
7291                               /*lba*/ 0,
7292                               /*reladdr*/ 0,
7293                               /*pmi*/ 0,
7294                               /*rcap_buf*/ (uint8_t *)&rcaplong,
7295                               /*rcap_buf_len*/ sizeof(rcaplong),
7296                               /*sense_len*/ SSD_FULL_SIZE,
7297                               /*timeout*/ timeout ? timeout : 5000);
7298
7299         /* Disable freezing the device queue */
7300         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7301
7302         if (arglist & CAM_ARG_ERR_RECOVER)
7303                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7304
7305         if (cam_send_ccb(device, ccb) < 0) {
7306                 warn("error sending READ CAPACITY (16) command");
7307
7308                 if (arglist & CAM_ARG_VERBOSE)
7309                         cam_error_print(device, ccb, CAM_ESF_ALL,
7310                                         CAM_EPF_ALL, stderr);
7311
7312                 retval = 1;
7313                 goto bailout;
7314         }
7315
7316         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7317                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7318                 retval = 1;
7319                 goto bailout;
7320         }
7321
7322         maxsector = scsi_8btou64(rcaplong.addr);
7323         block_len = scsi_4btoul(rcaplong.length);
7324
7325 do_print:
7326         if (blocksizeonly == 0) {
7327                 /*
7328                  * Humanize implies !quiet, and also implies numblocks.
7329                  */
7330                 if (humanize != 0) {
7331                         char tmpstr[6];
7332                         int64_t tmpbytes;
7333                         int ret;
7334
7335                         tmpbytes = (maxsector + 1) * block_len;
7336                         ret = humanize_number(tmpstr, sizeof(tmpstr),
7337                                               tmpbytes, "", HN_AUTOSCALE,
7338                                               HN_B | HN_DECIMAL |
7339                                               ((baseten != 0) ?
7340                                               HN_DIVISOR_1000 : 0));
7341                         if (ret == -1) {
7342                                 warnx("%s: humanize_number failed!", __func__);
7343                                 retval = 1;
7344                                 goto bailout;
7345                         }
7346                         fprintf(stdout, "Device Size: %s%s", tmpstr,
7347                                 (sizeonly == 0) ?  ", " : "\n");
7348                 } else if (numblocks != 0) {
7349                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7350                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
7351                                 (sizeonly == 0) ? ", " : "\n");
7352                 } else {
7353                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7354                                 "Last Block: " : "", (uintmax_t)maxsector,
7355                                 (sizeonly == 0) ? ", " : "\n");
7356                 }
7357         }
7358         if (sizeonly == 0)
7359                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
7360                         "Block Length: " : "", block_len, (quiet == 0) ?
7361                         " bytes" : "");
7362 bailout:
7363         cam_freeccb(ccb);
7364
7365         return (retval);
7366 }
7367
7368 static int
7369 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
7370        int retry_count, int timeout)
7371 {
7372         int c, error = 0;
7373         union ccb *ccb;
7374         uint8_t *smp_request = NULL, *smp_response = NULL;
7375         int request_size = 0, response_size = 0;
7376         int fd_request = 0, fd_response = 0;
7377         char *datastr = NULL;
7378         struct get_hook hook;
7379         int retval;
7380         int flags = 0;
7381
7382         /*
7383          * Note that at the moment we don't support sending SMP CCBs to
7384          * devices that aren't probed by CAM.
7385          */
7386         ccb = cam_getccb(device);
7387         if (ccb == NULL) {
7388                 warnx("%s: error allocating CCB", __func__);
7389                 return (1);
7390         }
7391
7392         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7393
7394         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7395                 switch (c) {
7396                 case 'R':
7397                         arglist |= CAM_ARG_CMD_IN;
7398                         response_size = strtol(optarg, NULL, 0);
7399                         if (response_size <= 0) {
7400                                 warnx("invalid number of response bytes %d",
7401                                       response_size);
7402                                 error = 1;
7403                                 goto smpcmd_bailout;
7404                         }
7405                         hook.argc = argc - optind;
7406                         hook.argv = argv + optind;
7407                         hook.got = 0;
7408                         optind++;
7409                         datastr = cget(&hook, NULL);
7410                         /*
7411                          * If the user supplied "-" instead of a format, he
7412                          * wants the data to be written to stdout.
7413                          */
7414                         if ((datastr != NULL)
7415                          && (datastr[0] == '-'))
7416                                 fd_response = 1;
7417
7418                         smp_response = (u_int8_t *)malloc(response_size);
7419                         if (smp_response == NULL) {
7420                                 warn("can't malloc memory for SMP response");
7421                                 error = 1;
7422                                 goto smpcmd_bailout;
7423                         }
7424                         break;
7425                 case 'r':
7426                         arglist |= CAM_ARG_CMD_OUT;
7427                         request_size = strtol(optarg, NULL, 0);
7428                         if (request_size <= 0) {
7429                                 warnx("invalid number of request bytes %d",
7430                                       request_size);
7431                                 error = 1;
7432                                 goto smpcmd_bailout;
7433                         }
7434                         hook.argc = argc - optind;
7435                         hook.argv = argv + optind;
7436                         hook.got = 0;
7437                         datastr = cget(&hook, NULL);
7438                         smp_request = (u_int8_t *)malloc(request_size);
7439                         if (smp_request == NULL) {
7440                                 warn("can't malloc memory for SMP request");
7441                                 error = 1;
7442                                 goto smpcmd_bailout;
7443                         }
7444                         bzero(smp_request, request_size);
7445                         /*
7446                          * If the user supplied "-" instead of a format, he
7447                          * wants the data to be read from stdin.
7448                          */
7449                         if ((datastr != NULL)
7450                          && (datastr[0] == '-'))
7451                                 fd_request = 1;
7452                         else
7453                                 buff_encode_visit(smp_request, request_size,
7454                                                   datastr,
7455                                                   iget, &hook);
7456                         optind += hook.got;
7457                         break;
7458                 default:
7459                         break;
7460                 }
7461         }
7462
7463         /*
7464          * If fd_data is set, and we're writing to the device, we need to
7465          * read the data the user wants written from stdin.
7466          */
7467         if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
7468                 ssize_t amt_read;
7469                 int amt_to_read = request_size;
7470                 u_int8_t *buf_ptr = smp_request;
7471
7472                 for (amt_read = 0; amt_to_read > 0;
7473                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
7474                         if (amt_read == -1) {
7475                                 warn("error reading data from stdin");
7476                                 error = 1;
7477                                 goto smpcmd_bailout;
7478                         }
7479                         amt_to_read -= amt_read;
7480                         buf_ptr += amt_read;
7481                 }
7482         }
7483
7484         if (((arglist & CAM_ARG_CMD_IN) == 0)
7485          || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
7486                 warnx("%s: need both the request (-r) and response (-R) "
7487                       "arguments", __func__);
7488                 error = 1;
7489                 goto smpcmd_bailout;
7490         }
7491
7492         flags |= CAM_DEV_QFRZDIS;
7493
7494         cam_fill_smpio(&ccb->smpio,
7495                        /*retries*/ retry_count,
7496                        /*cbfcnp*/ NULL,
7497                        /*flags*/ flags,
7498                        /*smp_request*/ smp_request,
7499                        /*smp_request_len*/ request_size,
7500                        /*smp_response*/ smp_response,
7501                        /*smp_response_len*/ response_size,
7502                        /*timeout*/ timeout ? timeout : 5000);
7503
7504         ccb->smpio.flags = SMP_FLAG_NONE;
7505
7506         if (((retval = cam_send_ccb(device, ccb)) < 0)
7507          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7508                 const char warnstr[] = "error sending command";
7509
7510                 if (retval < 0)
7511                         warn(warnstr);
7512                 else
7513                         warnx(warnstr);
7514
7515                 if (arglist & CAM_ARG_VERBOSE) {
7516                         cam_error_print(device, ccb, CAM_ESF_ALL,
7517                                         CAM_EPF_ALL, stderr);
7518                 }
7519         }
7520
7521         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
7522          && (response_size > 0)) {
7523                 if (fd_response == 0) {
7524                         buff_decode_visit(smp_response, response_size,
7525                                           datastr, arg_put, NULL);
7526                         fprintf(stdout, "\n");
7527                 } else {
7528                         ssize_t amt_written;
7529                         int amt_to_write = response_size;
7530                         u_int8_t *buf_ptr = smp_response;
7531
7532                         for (amt_written = 0; (amt_to_write > 0) &&
7533                              (amt_written = write(STDOUT_FILENO, buf_ptr,
7534                                                   amt_to_write)) > 0;){
7535                                 amt_to_write -= amt_written;
7536                                 buf_ptr += amt_written;
7537                         }
7538                         if (amt_written == -1) {
7539                                 warn("error writing data to stdout");
7540                                 error = 1;
7541                                 goto smpcmd_bailout;
7542                         } else if ((amt_written == 0)
7543                                 && (amt_to_write > 0)) {
7544                                 warnx("only wrote %u bytes out of %u",
7545                                       response_size - amt_to_write,
7546                                       response_size);
7547                         }
7548                 }
7549         }
7550 smpcmd_bailout:
7551         if (ccb != NULL)
7552                 cam_freeccb(ccb);
7553
7554         if (smp_request != NULL)
7555                 free(smp_request);
7556
7557         if (smp_response != NULL)
7558                 free(smp_response);
7559
7560         return (error);
7561 }
7562
7563 static int
7564 mmcsdcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
7565        int retry_count, int timeout)
7566 {
7567         int c, error = 0;
7568         union ccb *ccb;
7569         int32_t mmc_opcode = 0, mmc_arg = 0;
7570         int32_t mmc_flags = -1;
7571         int retval;
7572         int is_write = 0;
7573         int is_bw_4 = 0, is_bw_1 = 0;
7574         int is_highspeed = 0, is_stdspeed = 0;
7575         int is_info_request = 0;
7576         int flags = 0;
7577         uint8_t mmc_data_byte = 0;
7578
7579         /* For IO_RW_EXTENDED command */
7580         uint8_t *mmc_data = NULL;
7581         struct mmc_data mmc_d;
7582         int mmc_data_len = 0;
7583
7584         /*
7585          * Note that at the moment we don't support sending SMP CCBs to
7586          * devices that aren't probed by CAM.
7587          */
7588         ccb = cam_getccb(device);
7589         if (ccb == NULL) {
7590                 warnx("%s: error allocating CCB", __func__);
7591                 return (1);
7592         }
7593
7594         bzero(&(&ccb->ccb_h)[1],
7595               sizeof(union ccb) - sizeof(struct ccb_hdr));
7596
7597         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7598                 switch (c) {
7599                 case '4':
7600                         is_bw_4 = 1;
7601                         break;
7602                 case '1':
7603                         is_bw_1 = 1;
7604                         break;
7605                 case 'S':
7606                         if (!strcmp(optarg, "high"))
7607                                 is_highspeed = 1;
7608                         else
7609                                 is_stdspeed = 1;
7610                         break;
7611                 case 'I':
7612                         is_info_request = 1;
7613                         break;
7614                 case 'c':
7615                         mmc_opcode = strtol(optarg, NULL, 0);
7616                         if (mmc_opcode < 0) {
7617                                 warnx("invalid MMC opcode %d",
7618                                       mmc_opcode);
7619                                 error = 1;
7620                                 goto mmccmd_bailout;
7621                         }
7622                         break;
7623                 case 'a':
7624                         mmc_arg = strtol(optarg, NULL, 0);
7625                         if (mmc_arg < 0) {
7626                                 warnx("invalid MMC arg %d",
7627                                       mmc_arg);
7628                                 error = 1;
7629                                 goto mmccmd_bailout;
7630                         }
7631                         break;
7632                 case 'f':
7633                         mmc_flags = strtol(optarg, NULL, 0);
7634                         if (mmc_flags < 0) {
7635                                 warnx("invalid MMC flags %d",
7636                                       mmc_flags);
7637                                 error = 1;
7638                                 goto mmccmd_bailout;
7639                         }
7640                         break;
7641                 case 'l':
7642                         mmc_data_len = strtol(optarg, NULL, 0);
7643                         if (mmc_data_len <= 0) {
7644                                 warnx("invalid MMC data len %d",
7645                                       mmc_data_len);
7646                                 error = 1;
7647                                 goto mmccmd_bailout;
7648                         }
7649                         break;
7650                 case 'W':
7651                         is_write = 1;
7652                         break;
7653                 case 'b':
7654                         mmc_data_byte = strtol(optarg, NULL, 0);
7655                         break;
7656                 default:
7657                         break;
7658                 }
7659         }
7660         flags |= CAM_DEV_QFRZDIS; /* masks are broken?! */
7661
7662         /* If flags are left default, supply the right flags */
7663         if (mmc_flags < 0)
7664                 switch (mmc_opcode) {
7665                 case MMC_GO_IDLE_STATE:
7666                         mmc_flags = MMC_RSP_NONE | MMC_CMD_BC;
7667                         break;
7668                 case IO_SEND_OP_COND:
7669                         mmc_flags = MMC_RSP_R4;
7670                         break;
7671                 case SD_SEND_RELATIVE_ADDR:
7672                         mmc_flags = MMC_RSP_R6 | MMC_CMD_BCR;
7673                         break;
7674                 case MMC_SELECT_CARD:
7675                         mmc_flags = MMC_RSP_R1B | MMC_CMD_AC;
7676                         mmc_arg = mmc_arg << 16;
7677                         break;
7678                 case SD_IO_RW_DIRECT:
7679                         mmc_flags = MMC_RSP_R5 | MMC_CMD_AC;
7680                         mmc_arg = SD_IO_RW_ADR(mmc_arg);
7681                         if (is_write)
7682                                 mmc_arg |= SD_IO_RW_WR | SD_IO_RW_RAW | SD_IO_RW_DAT(mmc_data_byte);
7683                         break;
7684                 case SD_IO_RW_EXTENDED:
7685                         mmc_flags = MMC_RSP_R5 | MMC_CMD_ADTC;
7686                         mmc_arg = SD_IO_RW_ADR(mmc_arg);
7687                         int len_arg = mmc_data_len;
7688                         if (mmc_data_len == 512)
7689                                 len_arg = 0;
7690
7691                         // Byte mode
7692                         mmc_arg |= SD_IOE_RW_LEN(len_arg) | SD_IO_RW_INCR;
7693                         // Block mode
7694 //                        mmc_arg |= SD_IOE_RW_BLK | SD_IOE_RW_LEN(len_arg) | SD_IO_RW_INCR;
7695                         break;
7696                 default:
7697                         mmc_flags = MMC_RSP_R1;
7698                         break;
7699                 }
7700
7701         // Switch bus width instead of sending IO command
7702         if (is_bw_4 || is_bw_1) {
7703                 struct ccb_trans_settings_mmc *cts;
7704                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
7705                 ccb->ccb_h.flags = 0;
7706                 cts = &ccb->cts.proto_specific.mmc;
7707                 cts->ios.bus_width = is_bw_4 == 1 ? bus_width_4 : bus_width_1;
7708                 cts->ios_valid = MMC_BW;
7709                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7710                     || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7711                         warn("Error sending command");
7712                 } else {
7713                         printf("Parameters set OK\n");
7714                 }
7715                 cam_freeccb(ccb);
7716                 return (retval);
7717         }
7718
7719         // Switch bus speed instead of sending IO command
7720         if (is_stdspeed || is_highspeed) {
7721                 struct ccb_trans_settings_mmc *cts;
7722                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
7723                 ccb->ccb_h.flags = 0;
7724                 cts = &ccb->cts.proto_specific.mmc;
7725                 cts->ios.timing = is_highspeed == 1 ? bus_timing_hs : bus_timing_normal;
7726                 cts->ios_valid = MMC_BT;
7727                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7728                     || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7729                         warn("Error sending command");
7730                 } else {
7731                         printf("Speed set OK (HS: %d)\n", is_highspeed);
7732                 }
7733                 cam_freeccb(ccb);
7734                 return (retval);
7735         }
7736
7737         // Get information about controller and its settings
7738         if (is_info_request) {
7739                 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
7740                 ccb->ccb_h.flags = 0;
7741                 struct ccb_trans_settings_mmc *cts;
7742                 cts = &ccb->cts.proto_specific.mmc;
7743                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7744                     || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7745                         warn("Error sending command");
7746                         return (retval);
7747                 }
7748                 printf("Host controller information\n");
7749                 printf("Host OCR: 0x%x\n", cts->host_ocr);
7750                 printf("Min frequency: %u KHz\n", cts->host_f_min / 1000);
7751                 printf("Max frequency: %u MHz\n", cts->host_f_max / 1000000);
7752                 printf("Supported bus width: ");
7753                 if (cts->host_caps & MMC_CAP_4_BIT_DATA)
7754                         printf(" 4 bit\n");
7755                 if (cts->host_caps & MMC_CAP_8_BIT_DATA)
7756                         printf(" 8 bit\n");
7757                 printf("\nCurrent settings:\n");
7758                 printf("Bus width: ");
7759                 switch (cts->ios.bus_width) {
7760                 case bus_width_1:
7761                         printf("1 bit\n");
7762                         break;
7763                 case bus_width_4:
7764                         printf("4 bit\n");
7765                         break;
7766                 case bus_width_8:
7767                         printf("8 bit\n");
7768                         break;
7769                 }
7770                 printf("Freq: %d.%03d MHz%s\n",
7771                        cts->ios.clock / 1000000,
7772                        (cts->ios.clock / 1000) % 1000,
7773                        cts->ios.timing == bus_timing_hs ? "(high-speed timing)" : "");
7774                 return (0);
7775         }
7776
7777         printf("CMD %d arg %d flags %02x\n", mmc_opcode, mmc_arg, mmc_flags);
7778
7779         if (mmc_data_len > 0) {
7780                 flags |= CAM_DIR_IN;
7781                 mmc_data = malloc(mmc_data_len);
7782                 memset(mmc_data, 0, mmc_data_len);
7783                 mmc_d.len = mmc_data_len;
7784                 mmc_d.data = mmc_data;
7785                 mmc_d.flags = MMC_DATA_READ;
7786         } else flags |= CAM_DIR_NONE;
7787
7788         cam_fill_mmcio(&ccb->mmcio,
7789                        /*retries*/ retry_count,
7790                        /*cbfcnp*/ NULL,
7791                        /*flags*/ flags,
7792                        /*mmc_opcode*/ mmc_opcode,
7793                        /*mmc_arg*/ mmc_arg,
7794                        /*mmc_flags*/ mmc_flags,
7795                        /*mmc_data*/ mmc_data_len > 0 ? &mmc_d : NULL,
7796                        /*timeout*/ timeout ? timeout : 5000);
7797
7798         if (((retval = cam_send_ccb(device, ccb)) < 0)
7799          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7800                 const char warnstr[] = "error sending command";
7801
7802                 if (retval < 0)
7803                         warn(warnstr);
7804                 else
7805                         warnx(warnstr);
7806
7807                 if (arglist & CAM_ARG_VERBOSE) {
7808                         cam_error_print(device, ccb, CAM_ESF_ALL,
7809                                         CAM_EPF_ALL, stderr);
7810                 }
7811         }
7812
7813         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)) {
7814                 printf("MMCIO: error %d, %08x %08x %08x %08x\n",
7815                        ccb->mmcio.cmd.error, ccb->mmcio.cmd.resp[0],
7816                        ccb->mmcio.cmd.resp[1],
7817                        ccb->mmcio.cmd.resp[2],
7818                        ccb->mmcio.cmd.resp[3]);
7819
7820                 switch (mmc_opcode) {
7821                 case SD_IO_RW_DIRECT:
7822                         printf("IO_RW_DIRECT: resp byte %02x, cur state %d\n",
7823                                SD_R5_DATA(ccb->mmcio.cmd.resp),
7824                                (ccb->mmcio.cmd.resp[0] >> 12) & 0x3);
7825                         break;
7826                 case SD_IO_RW_EXTENDED:
7827                         printf("IO_RW_EXTENDED: read %d bytes w/o error:\n", mmc_data_len);
7828                         hexdump(mmc_data, mmc_data_len, NULL, 0);
7829                         break;
7830                 case SD_SEND_RELATIVE_ADDR:
7831                         printf("SEND_RELATIVE_ADDR: published RCA %02x\n", ccb->mmcio.cmd.resp[0] >> 16);
7832                         break;
7833                 default:
7834                         printf("No command-specific decoder for CMD %d\n", mmc_opcode);
7835                 }
7836         }
7837 mmccmd_bailout:
7838         if (ccb != NULL)
7839                 cam_freeccb(ccb);
7840
7841         if (mmc_data_len > 0 && mmc_data != NULL)
7842                 free(mmc_data);
7843
7844         return (error);
7845 }
7846
7847 static int
7848 smpreportgeneral(struct cam_device *device, int argc, char **argv,
7849                  char *combinedopt, int retry_count, int timeout)
7850 {
7851         union ccb *ccb;
7852         struct smp_report_general_request *request = NULL;
7853         struct smp_report_general_response *response = NULL;
7854         struct sbuf *sb = NULL;
7855         int error = 0;
7856         int c, long_response = 0;
7857         int retval;
7858
7859         /*
7860          * Note that at the moment we don't support sending SMP CCBs to
7861          * devices that aren't probed by CAM.
7862          */
7863         ccb = cam_getccb(device);
7864         if (ccb == NULL) {
7865                 warnx("%s: error allocating CCB", __func__);
7866                 return (1);
7867         }
7868
7869         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7870
7871         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7872                 switch (c) {
7873                 case 'l':
7874                         long_response = 1;
7875                         break;
7876                 default:
7877                         break;
7878                 }
7879         }
7880         request = malloc(sizeof(*request));
7881         if (request == NULL) {
7882                 warn("%s: unable to allocate %zd bytes", __func__,
7883                      sizeof(*request));
7884                 error = 1;
7885                 goto bailout;
7886         }
7887
7888         response = malloc(sizeof(*response));
7889         if (response == NULL) {
7890                 warn("%s: unable to allocate %zd bytes", __func__,
7891                      sizeof(*response));
7892                 error = 1;
7893                 goto bailout;
7894         }
7895
7896 try_long:
7897         smp_report_general(&ccb->smpio,
7898                            retry_count,
7899                            /*cbfcnp*/ NULL,
7900                            request,
7901                            /*request_len*/ sizeof(*request),
7902                            (uint8_t *)response,
7903                            /*response_len*/ sizeof(*response),
7904                            /*long_response*/ long_response,
7905                            timeout);
7906
7907         if (((retval = cam_send_ccb(device, ccb)) < 0)
7908          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7909                 const char warnstr[] = "error sending command";
7910
7911                 if (retval < 0)
7912                         warn(warnstr);
7913                 else
7914                         warnx(warnstr);
7915
7916                 if (arglist & CAM_ARG_VERBOSE) {
7917                         cam_error_print(device, ccb, CAM_ESF_ALL,
7918                                         CAM_EPF_ALL, stderr);
7919                 }
7920                 error = 1;
7921                 goto bailout;
7922         }
7923
7924         /*
7925          * If the device supports the long response bit, try again and see
7926          * if we can get all of the data.
7927          */
7928         if ((response->long_response & SMP_RG_LONG_RESPONSE)
7929          && (long_response == 0)) {
7930                 ccb->ccb_h.status = CAM_REQ_INPROG;
7931                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7932                 long_response = 1;
7933                 goto try_long;
7934         }
7935
7936         /*
7937          * XXX KDM detect and decode SMP errors here.
7938          */
7939         sb = sbuf_new_auto();
7940         if (sb == NULL) {
7941                 warnx("%s: error allocating sbuf", __func__);
7942                 goto bailout;
7943         }
7944
7945         smp_report_general_sbuf(response, sizeof(*response), sb);
7946
7947         if (sbuf_finish(sb) != 0) {
7948                 warnx("%s: sbuf_finish", __func__);
7949                 goto bailout;
7950         }
7951
7952         printf("%s", sbuf_data(sb));
7953
7954 bailout:
7955         if (ccb != NULL)
7956                 cam_freeccb(ccb);
7957
7958         if (request != NULL)
7959                 free(request);
7960
7961         if (response != NULL)
7962                 free(response);
7963
7964         if (sb != NULL)
7965                 sbuf_delete(sb);
7966
7967         return (error);
7968 }
7969
7970 static struct camcontrol_opts phy_ops[] = {
7971         {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7972         {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7973         {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7974         {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7975         {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7976         {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7977         {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7978         {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7979         {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7980         {NULL, 0, 0, NULL}
7981 };
7982
7983 static int
7984 smpphycontrol(struct cam_device *device, int argc, char **argv,
7985               char *combinedopt, int retry_count, int timeout)
7986 {
7987         union ccb *ccb;
7988         struct smp_phy_control_request *request = NULL;
7989         struct smp_phy_control_response *response = NULL;
7990         int long_response = 0;
7991         int retval = 0;
7992         int phy = -1;
7993         uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7994         int phy_op_set = 0;
7995         uint64_t attached_dev_name = 0;
7996         int dev_name_set = 0;
7997         uint32_t min_plr = 0, max_plr = 0;
7998         uint32_t pp_timeout_val = 0;
7999         int slumber_partial = 0;
8000         int set_pp_timeout_val = 0;
8001         int c;
8002
8003         /*
8004          * Note that at the moment we don't support sending SMP CCBs to
8005          * devices that aren't probed by CAM.
8006          */
8007         ccb = cam_getccb(device);
8008         if (ccb == NULL) {
8009                 warnx("%s: error allocating CCB", __func__);
8010                 return (1);
8011         }
8012
8013         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8014
8015         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8016                 switch (c) {
8017                 case 'a':
8018                 case 'A':
8019                 case 's':
8020                 case 'S': {
8021                         int enable = -1;
8022
8023                         if (strcasecmp(optarg, "enable") == 0)
8024                                 enable = 1;
8025                         else if (strcasecmp(optarg, "disable") == 0)
8026                                 enable = 2;
8027                         else {
8028                                 warnx("%s: Invalid argument %s", __func__,
8029                                       optarg);
8030                                 retval = 1;
8031                                 goto bailout;
8032                         }
8033                         switch (c) {
8034                         case 's':
8035                                 slumber_partial |= enable <<
8036                                                    SMP_PC_SAS_SLUMBER_SHIFT;
8037                                 break;
8038                         case 'S':
8039                                 slumber_partial |= enable <<
8040                                                    SMP_PC_SAS_PARTIAL_SHIFT;
8041                                 break;
8042                         case 'a':
8043                                 slumber_partial |= enable <<
8044                                                    SMP_PC_SATA_SLUMBER_SHIFT;
8045                                 break;
8046                         case 'A':
8047                                 slumber_partial |= enable <<
8048                                                    SMP_PC_SATA_PARTIAL_SHIFT;
8049                                 break;
8050                         default:
8051                                 warnx("%s: programmer error", __func__);
8052                                 retval = 1;
8053                                 goto bailout;
8054                                 break; /*NOTREACHED*/
8055                         }
8056                         break;
8057                 }
8058                 case 'd':
8059                         attached_dev_name = (uintmax_t)strtoumax(optarg,
8060                                                                  NULL,0);
8061                         dev_name_set = 1;
8062                         break;
8063                 case 'l':
8064                         long_response = 1;
8065                         break;
8066                 case 'm':
8067                         /*
8068                          * We don't do extensive checking here, so this
8069                          * will continue to work when new speeds come out.
8070                          */
8071                         min_plr = strtoul(optarg, NULL, 0);
8072                         if ((min_plr == 0)
8073                          || (min_plr > 0xf)) {
8074                                 warnx("%s: invalid link rate %x",
8075                                       __func__, min_plr);
8076                                 retval = 1;
8077                                 goto bailout;
8078                         }
8079                         break;
8080                 case 'M':
8081                         /*
8082                          * We don't do extensive checking here, so this
8083                          * will continue to work when new speeds come out.
8084                          */
8085                         max_plr = strtoul(optarg, NULL, 0);
8086                         if ((max_plr == 0)
8087                          || (max_plr > 0xf)) {
8088                                 warnx("%s: invalid link rate %x",
8089                                       __func__, max_plr);
8090                                 retval = 1;
8091                                 goto bailout;
8092                         }
8093                         break;
8094                 case 'o': {
8095                         camcontrol_optret optreturn;
8096                         cam_argmask argnums;
8097                         const char *subopt;
8098
8099                         if (phy_op_set != 0) {
8100                                 warnx("%s: only one phy operation argument "
8101                                       "(-o) allowed", __func__);
8102                                 retval = 1;
8103                                 goto bailout;
8104                         }
8105
8106                         phy_op_set = 1;
8107
8108                         /*
8109                          * Allow the user to specify the phy operation
8110                          * numerically, as well as with a name.  This will
8111                          * future-proof it a bit, so options that are added
8112                          * in future specs can be used.
8113                          */
8114                         if (isdigit(optarg[0])) {
8115                                 phy_operation = strtoul(optarg, NULL, 0);
8116                                 if ((phy_operation == 0)
8117                                  || (phy_operation > 0xff)) {
8118                                         warnx("%s: invalid phy operation %#x",
8119                                               __func__, phy_operation);
8120                                         retval = 1;
8121                                         goto bailout;
8122                                 }
8123                                 break;
8124                         }
8125                         optreturn = getoption(phy_ops, optarg, &phy_operation,
8126                                               &argnums, &subopt);
8127
8128                         if (optreturn == CC_OR_AMBIGUOUS) {
8129                                 warnx("%s: ambiguous option %s", __func__,
8130                                       optarg);
8131                                 usage(0);
8132                                 retval = 1;
8133                                 goto bailout;
8134                         } else if (optreturn == CC_OR_NOT_FOUND) {
8135                                 warnx("%s: option %s not found", __func__,
8136                                       optarg);
8137                                 usage(0);
8138                                 retval = 1;
8139                                 goto bailout;
8140                         }
8141                         break;
8142                 }
8143                 case 'p':
8144                         phy = atoi(optarg);
8145                         break;
8146                 case 'T':
8147                         pp_timeout_val = strtoul(optarg, NULL, 0);
8148                         if (pp_timeout_val > 15) {
8149                                 warnx("%s: invalid partial pathway timeout "
8150                                       "value %u, need a value less than 16",
8151                                       __func__, pp_timeout_val);
8152                                 retval = 1;
8153                                 goto bailout;
8154                         }
8155                         set_pp_timeout_val = 1;
8156                         break;
8157                 default:
8158                         break;
8159                 }
8160         }
8161
8162         if (phy == -1) {
8163                 warnx("%s: a PHY (-p phy) argument is required",__func__);
8164                 retval = 1;
8165                 goto bailout;
8166         }
8167
8168         if (((dev_name_set != 0)
8169           && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
8170          || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
8171           && (dev_name_set == 0))) {
8172                 warnx("%s: -d name and -o setdevname arguments both "
8173                       "required to set device name", __func__);
8174                 retval = 1;
8175                 goto bailout;
8176         }
8177
8178         request = malloc(sizeof(*request));
8179         if (request == NULL) {
8180                 warn("%s: unable to allocate %zd bytes", __func__,
8181                      sizeof(*request));
8182                 retval = 1;
8183                 goto bailout;
8184         }
8185
8186         response = malloc(sizeof(*response));
8187         if (response == NULL) {
8188                 warn("%s: unable to allocate %zd bytes", __func__,
8189                      sizeof(*response));
8190                 retval = 1;
8191                 goto bailout;
8192         }
8193
8194         smp_phy_control(&ccb->smpio,
8195                         retry_count,
8196                         /*cbfcnp*/ NULL,
8197                         request,
8198                         sizeof(*request),
8199                         (uint8_t *)response,
8200                         sizeof(*response),
8201                         long_response,
8202                         /*expected_exp_change_count*/ 0,
8203                         phy,
8204                         phy_operation,
8205                         (set_pp_timeout_val != 0) ? 1 : 0,
8206                         attached_dev_name,
8207                         min_plr,
8208                         max_plr,
8209                         slumber_partial,
8210                         pp_timeout_val,
8211                         timeout);
8212
8213         if (((retval = cam_send_ccb(device, ccb)) < 0)
8214          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8215                 const char warnstr[] = "error sending command";
8216
8217                 if (retval < 0)
8218                         warn(warnstr);
8219                 else
8220                         warnx(warnstr);
8221
8222                 if (arglist & CAM_ARG_VERBOSE) {
8223                         /*
8224                          * Use CAM_EPF_NORMAL so we only get one line of
8225                          * SMP command decoding.
8226                          */
8227                         cam_error_print(device, ccb, CAM_ESF_ALL,
8228                                         CAM_EPF_NORMAL, stderr);
8229                 }
8230                 retval = 1;
8231                 goto bailout;
8232         }
8233
8234         /* XXX KDM print out something here for success? */
8235 bailout:
8236         if (ccb != NULL)
8237                 cam_freeccb(ccb);
8238
8239         if (request != NULL)
8240                 free(request);
8241
8242         if (response != NULL)
8243                 free(response);
8244
8245         return (retval);
8246 }
8247
8248 static int
8249 smpmaninfo(struct cam_device *device, int argc, char **argv,
8250            char *combinedopt, int retry_count, int timeout)
8251 {
8252         union ccb *ccb;
8253         struct smp_report_manuf_info_request request;
8254         struct smp_report_manuf_info_response response;
8255         struct sbuf *sb = NULL;
8256         int long_response = 0;
8257         int retval = 0;
8258         int c;
8259
8260         /*
8261          * Note that at the moment we don't support sending SMP CCBs to
8262          * devices that aren't probed by CAM.
8263          */
8264         ccb = cam_getccb(device);
8265         if (ccb == NULL) {
8266                 warnx("%s: error allocating CCB", __func__);
8267                 return (1);
8268         }
8269
8270         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8271
8272         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8273                 switch (c) {
8274                 case 'l':
8275                         long_response = 1;
8276                         break;
8277                 default:
8278                         break;
8279                 }
8280         }
8281         bzero(&request, sizeof(request));
8282         bzero(&response, sizeof(response));
8283
8284         smp_report_manuf_info(&ccb->smpio,
8285                               retry_count,
8286                               /*cbfcnp*/ NULL,
8287                               &request,
8288                               sizeof(request),
8289                               (uint8_t *)&response,
8290                               sizeof(response),
8291                               long_response,
8292                               timeout);
8293
8294         if (((retval = cam_send_ccb(device, ccb)) < 0)
8295          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8296                 const char warnstr[] = "error sending command";
8297
8298                 if (retval < 0)
8299                         warn(warnstr);
8300                 else
8301                         warnx(warnstr);
8302
8303                 if (arglist & CAM_ARG_VERBOSE) {
8304                         cam_error_print(device, ccb, CAM_ESF_ALL,
8305                                         CAM_EPF_ALL, stderr);
8306                 }
8307                 retval = 1;
8308                 goto bailout;
8309         }
8310
8311         sb = sbuf_new_auto();
8312         if (sb == NULL) {
8313                 warnx("%s: error allocating sbuf", __func__);
8314                 goto bailout;
8315         }
8316
8317         smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
8318
8319         if (sbuf_finish(sb) != 0) {
8320                 warnx("%s: sbuf_finish", __func__);
8321                 goto bailout;
8322         }
8323
8324         printf("%s", sbuf_data(sb));
8325
8326 bailout:
8327
8328         if (ccb != NULL)
8329                 cam_freeccb(ccb);
8330
8331         if (sb != NULL)
8332                 sbuf_delete(sb);
8333
8334         return (retval);
8335 }
8336
8337 static int
8338 getdevid(struct cam_devitem *item)
8339 {
8340         int retval = 0;
8341         union ccb *ccb = NULL;
8342
8343         struct cam_device *dev;
8344
8345         dev = cam_open_btl(item->dev_match.path_id,
8346                            item->dev_match.target_id,
8347                            item->dev_match.target_lun, O_RDWR, NULL);
8348
8349         if (dev == NULL) {
8350                 warnx("%s", cam_errbuf);
8351                 retval = 1;
8352                 goto bailout;
8353         }
8354
8355         item->device_id_len = 0;
8356
8357         ccb = cam_getccb(dev);
8358         if (ccb == NULL) {
8359                 warnx("%s: error allocating CCB", __func__);
8360                 retval = 1;
8361                 goto bailout;
8362         }
8363
8364         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai);
8365
8366         /*
8367          * On the first try, we just probe for the size of the data, and
8368          * then allocate that much memory and try again.
8369          */
8370 retry:
8371         ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
8372         ccb->ccb_h.flags = CAM_DIR_IN;
8373         ccb->cdai.flags = CDAI_FLAG_NONE;
8374         ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
8375         ccb->cdai.bufsiz = item->device_id_len;
8376         if (item->device_id_len != 0)
8377                 ccb->cdai.buf = (uint8_t *)item->device_id;
8378
8379         if (cam_send_ccb(dev, ccb) < 0) {
8380                 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
8381                 retval = 1;
8382                 goto bailout;
8383         }
8384
8385         if (ccb->ccb_h.status != CAM_REQ_CMP) {
8386                 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
8387                 retval = 1;
8388                 goto bailout;
8389         }
8390
8391         if (item->device_id_len == 0) {
8392                 /*
8393                  * This is our first time through.  Allocate the buffer,
8394                  * and then go back to get the data.
8395                  */
8396                 if (ccb->cdai.provsiz == 0) {
8397                         warnx("%s: invalid .provsiz field returned with "
8398                              "XPT_GDEV_ADVINFO CCB", __func__);
8399                         retval = 1;
8400                         goto bailout;
8401                 }
8402                 item->device_id_len = ccb->cdai.provsiz;
8403                 item->device_id = malloc(item->device_id_len);
8404                 if (item->device_id == NULL) {
8405                         warn("%s: unable to allocate %d bytes", __func__,
8406                              item->device_id_len);
8407                         retval = 1;
8408                         goto bailout;
8409                 }
8410                 ccb->ccb_h.status = CAM_REQ_INPROG;
8411                 goto retry;
8412         }
8413
8414 bailout:
8415         if (dev != NULL)
8416                 cam_close_device(dev);
8417
8418         if (ccb != NULL)
8419                 cam_freeccb(ccb);
8420
8421         return (retval);
8422 }
8423
8424 /*
8425  * XXX KDM merge this code with getdevtree()?
8426  */
8427 static int
8428 buildbusdevlist(struct cam_devlist *devlist)
8429 {
8430         union ccb ccb;
8431         int bufsize, fd = -1;
8432         struct dev_match_pattern *patterns;
8433         struct cam_devitem *item = NULL;
8434         int skip_device = 0;
8435         int retval = 0;
8436
8437         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
8438                 warn("couldn't open %s", XPT_DEVICE);
8439                 return (1);
8440         }
8441
8442         bzero(&ccb, sizeof(union ccb));
8443
8444         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
8445         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
8446         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
8447
8448         ccb.ccb_h.func_code = XPT_DEV_MATCH;
8449         bufsize = sizeof(struct dev_match_result) * 100;
8450         ccb.cdm.match_buf_len = bufsize;
8451         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
8452         if (ccb.cdm.matches == NULL) {
8453                 warnx("can't malloc memory for matches");
8454                 close(fd);
8455                 return (1);
8456         }
8457         ccb.cdm.num_matches = 0;
8458         ccb.cdm.num_patterns = 2;
8459         ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
8460                 ccb.cdm.num_patterns;
8461
8462         patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
8463         if (patterns == NULL) {
8464                 warnx("can't malloc memory for patterns");
8465                 retval = 1;
8466                 goto bailout;
8467         }
8468
8469         ccb.cdm.patterns = patterns;
8470         bzero(patterns, ccb.cdm.pattern_buf_len);
8471
8472         patterns[0].type = DEV_MATCH_DEVICE;
8473         patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
8474         patterns[0].pattern.device_pattern.path_id = devlist->path_id;
8475         patterns[1].type = DEV_MATCH_PERIPH;
8476         patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
8477         patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
8478
8479         /*
8480          * We do the ioctl multiple times if necessary, in case there are
8481          * more than 100 nodes in the EDT.
8482          */
8483         do {
8484                 unsigned int i;
8485
8486                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
8487                         warn("error sending CAMIOCOMMAND ioctl");
8488                         retval = 1;
8489                         goto bailout;
8490                 }
8491
8492                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
8493                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
8494                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
8495                         warnx("got CAM error %#x, CDM error %d\n",
8496                               ccb.ccb_h.status, ccb.cdm.status);
8497                         retval = 1;
8498                         goto bailout;
8499                 }
8500
8501                 for (i = 0; i < ccb.cdm.num_matches; i++) {
8502                         switch (ccb.cdm.matches[i].type) {
8503                         case DEV_MATCH_DEVICE: {
8504                                 struct device_match_result *dev_result;
8505
8506                                 dev_result =
8507                                      &ccb.cdm.matches[i].result.device_result;
8508
8509                                 if (dev_result->flags &
8510                                     DEV_RESULT_UNCONFIGURED) {
8511                                         skip_device = 1;
8512                                         break;
8513                                 } else
8514                                         skip_device = 0;
8515
8516                                 item = malloc(sizeof(*item));
8517                                 if (item == NULL) {
8518                                         warn("%s: unable to allocate %zd bytes",
8519                                              __func__, sizeof(*item));
8520                                         retval = 1;
8521                                         goto bailout;
8522                                 }
8523                                 bzero(item, sizeof(*item));
8524                                 bcopy(dev_result, &item->dev_match,
8525                                       sizeof(*dev_result));
8526                                 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
8527                                                    links);
8528
8529                                 if (getdevid(item) != 0) {
8530                                         retval = 1;
8531                                         goto bailout;
8532                                 }
8533                                 break;
8534                         }
8535                         case DEV_MATCH_PERIPH: {
8536                                 struct periph_match_result *periph_result;
8537
8538                                 periph_result =
8539                                       &ccb.cdm.matches[i].result.periph_result;
8540
8541                                 if (skip_device != 0)
8542                                         break;
8543                                 item->num_periphs++;
8544                                 item->periph_matches = realloc(
8545                                         item->periph_matches,
8546                                         item->num_periphs *
8547                                         sizeof(struct periph_match_result));
8548                                 if (item->periph_matches == NULL) {
8549                                         warn("%s: error allocating periph "
8550                                              "list", __func__);
8551                                         retval = 1;
8552                                         goto bailout;
8553                                 }
8554                                 bcopy(periph_result, &item->periph_matches[
8555                                       item->num_periphs - 1],
8556                                       sizeof(*periph_result));
8557                                 break;
8558                         }
8559                         default:
8560                                 fprintf(stderr, "%s: unexpected match "
8561                                         "type %d\n", __func__,
8562                                         ccb.cdm.matches[i].type);
8563                                 retval = 1;
8564                                 goto bailout;
8565                                 break; /*NOTREACHED*/
8566                         }
8567                 }
8568         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
8569                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
8570 bailout:
8571
8572         if (fd != -1)
8573                 close(fd);
8574
8575         free(patterns);
8576
8577         free(ccb.cdm.matches);
8578
8579         if (retval != 0)
8580                 freebusdevlist(devlist);
8581
8582         return (retval);
8583 }
8584
8585 static void
8586 freebusdevlist(struct cam_devlist *devlist)
8587 {
8588         struct cam_devitem *item, *item2;
8589
8590         STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
8591                 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
8592                               links);
8593                 free(item->device_id);
8594                 free(item->periph_matches);
8595                 free(item);
8596         }
8597 }
8598
8599 static struct cam_devitem *
8600 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
8601 {
8602         struct cam_devitem *item;
8603
8604         STAILQ_FOREACH(item, &devlist->dev_queue, links) {
8605                 struct scsi_vpd_id_descriptor *idd;
8606
8607                 /*
8608                  * XXX KDM look for LUN IDs as well?
8609                  */
8610                 idd = scsi_get_devid(item->device_id,
8611                                            item->device_id_len,
8612                                            scsi_devid_is_sas_target);
8613                 if (idd == NULL)
8614                         continue;
8615
8616                 if (scsi_8btou64(idd->identifier) == sasaddr)
8617                         return (item);
8618         }
8619
8620         return (NULL);
8621 }
8622
8623 static int
8624 smpphylist(struct cam_device *device, int argc, char **argv,
8625            char *combinedopt, int retry_count, int timeout)
8626 {
8627         struct smp_report_general_request *rgrequest = NULL;
8628         struct smp_report_general_response *rgresponse = NULL;
8629         struct smp_discover_request *disrequest = NULL;
8630         struct smp_discover_response *disresponse = NULL;
8631         struct cam_devlist devlist;
8632         union ccb *ccb;
8633         int long_response = 0;
8634         int num_phys = 0;
8635         int quiet = 0;
8636         int retval;
8637         int i, c;
8638
8639         /*
8640          * Note that at the moment we don't support sending SMP CCBs to
8641          * devices that aren't probed by CAM.
8642          */
8643         ccb = cam_getccb(device);
8644         if (ccb == NULL) {
8645                 warnx("%s: error allocating CCB", __func__);
8646                 return (1);
8647         }
8648
8649         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8650         STAILQ_INIT(&devlist.dev_queue);
8651
8652         rgrequest = malloc(sizeof(*rgrequest));
8653         if (rgrequest == NULL) {
8654                 warn("%s: unable to allocate %zd bytes", __func__,
8655                      sizeof(*rgrequest));
8656                 retval = 1;
8657                 goto bailout;
8658         }
8659
8660         rgresponse = malloc(sizeof(*rgresponse));
8661         if (rgresponse == NULL) {
8662                 warn("%s: unable to allocate %zd bytes", __func__,
8663                      sizeof(*rgresponse));
8664                 retval = 1;
8665                 goto bailout;
8666         }
8667
8668         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8669                 switch (c) {
8670                 case 'l':
8671                         long_response = 1;
8672                         break;
8673                 case 'q':
8674                         quiet = 1;
8675                         break;
8676                 default:
8677                         break;
8678                 }
8679         }
8680
8681         smp_report_general(&ccb->smpio,
8682                            retry_count,
8683                            /*cbfcnp*/ NULL,
8684                            rgrequest,
8685                            /*request_len*/ sizeof(*rgrequest),
8686                            (uint8_t *)rgresponse,
8687                            /*response_len*/ sizeof(*rgresponse),
8688                            /*long_response*/ long_response,
8689                            timeout);
8690
8691         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8692
8693         if (((retval = cam_send_ccb(device, ccb)) < 0)
8694          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8695                 const char warnstr[] = "error sending command";
8696
8697                 if (retval < 0)
8698                         warn(warnstr);
8699                 else
8700                         warnx(warnstr);
8701
8702                 if (arglist & CAM_ARG_VERBOSE) {
8703                         cam_error_print(device, ccb, CAM_ESF_ALL,
8704                                         CAM_EPF_ALL, stderr);
8705                 }
8706                 retval = 1;
8707                 goto bailout;
8708         }
8709
8710         num_phys = rgresponse->num_phys;
8711
8712         if (num_phys == 0) {
8713                 if (quiet == 0)
8714                         fprintf(stdout, "%s: No Phys reported\n", __func__);
8715                 retval = 1;
8716                 goto bailout;
8717         }
8718
8719         devlist.path_id = device->path_id;
8720
8721         retval = buildbusdevlist(&devlist);
8722         if (retval != 0)
8723                 goto bailout;
8724
8725         if (quiet == 0) {
8726                 fprintf(stdout, "%d PHYs:\n", num_phys);
8727                 fprintf(stdout, "PHY  Attached SAS Address\n");
8728         }
8729
8730         disrequest = malloc(sizeof(*disrequest));
8731         if (disrequest == NULL) {
8732                 warn("%s: unable to allocate %zd bytes", __func__,
8733                      sizeof(*disrequest));
8734                 retval = 1;
8735                 goto bailout;
8736         }
8737
8738         disresponse = malloc(sizeof(*disresponse));
8739         if (disresponse == NULL) {
8740                 warn("%s: unable to allocate %zd bytes", __func__,
8741                      sizeof(*disresponse));
8742                 retval = 1;
8743                 goto bailout;
8744         }
8745
8746         for (i = 0; i < num_phys; i++) {
8747                 struct cam_devitem *item;
8748                 struct device_match_result *dev_match;
8749                 char vendor[16], product[48], revision[16];
8750                 char tmpstr[256];
8751                 int j;
8752
8753                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8754
8755                 ccb->ccb_h.status = CAM_REQ_INPROG;
8756                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8757
8758                 smp_discover(&ccb->smpio,
8759                              retry_count,
8760                              /*cbfcnp*/ NULL,
8761                              disrequest,
8762                              sizeof(*disrequest),
8763                              (uint8_t *)disresponse,
8764                              sizeof(*disresponse),
8765                              long_response,
8766                              /*ignore_zone_group*/ 0,
8767                              /*phy*/ i,
8768                              timeout);
8769
8770                 if (((retval = cam_send_ccb(device, ccb)) < 0)
8771                  || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
8772                   && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
8773                         const char warnstr[] = "error sending command";
8774
8775                         if (retval < 0)
8776                                 warn(warnstr);
8777                         else
8778                                 warnx(warnstr);
8779
8780                         if (arglist & CAM_ARG_VERBOSE) {
8781                                 cam_error_print(device, ccb, CAM_ESF_ALL,
8782                                                 CAM_EPF_ALL, stderr);
8783                         }
8784                         retval = 1;
8785                         goto bailout;
8786                 }
8787
8788                 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
8789                         if (quiet == 0)
8790                                 fprintf(stdout, "%3d  <vacant>\n", i);
8791                         continue;
8792                 }
8793
8794                 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
8795                         item = NULL;
8796                 } else {
8797                         item = findsasdevice(&devlist,
8798                             scsi_8btou64(disresponse->attached_sas_address));
8799                 }
8800
8801                 if ((quiet == 0)
8802                  || (item != NULL)) {
8803                         fprintf(stdout, "%3d  0x%016jx", i,
8804                                 (uintmax_t)scsi_8btou64(
8805                                 disresponse->attached_sas_address));
8806                         if (item == NULL) {
8807                                 fprintf(stdout, "\n");
8808                                 continue;
8809                         }
8810                 } else if (quiet != 0)
8811                         continue;
8812
8813                 dev_match = &item->dev_match;
8814
8815                 if (dev_match->protocol == PROTO_SCSI) {
8816                         cam_strvis(vendor, dev_match->inq_data.vendor,
8817                                    sizeof(dev_match->inq_data.vendor),
8818                                    sizeof(vendor));
8819                         cam_strvis(product, dev_match->inq_data.product,
8820                                    sizeof(dev_match->inq_data.product),
8821                                    sizeof(product));
8822                         cam_strvis(revision, dev_match->inq_data.revision,
8823                                    sizeof(dev_match->inq_data.revision),
8824                                    sizeof(revision));
8825                         sprintf(tmpstr, "<%s %s %s>", vendor, product,
8826                                 revision);
8827                 } else if ((dev_match->protocol == PROTO_ATA)
8828                         || (dev_match->protocol == PROTO_SATAPM)) {
8829                         cam_strvis(product, dev_match->ident_data.model,
8830                                    sizeof(dev_match->ident_data.model),
8831                                    sizeof(product));
8832                         cam_strvis(revision, dev_match->ident_data.revision,
8833                                    sizeof(dev_match->ident_data.revision),
8834                                    sizeof(revision));
8835                         sprintf(tmpstr, "<%s %s>", product, revision);
8836                 } else {
8837                         sprintf(tmpstr, "<>");
8838                 }
8839                 fprintf(stdout, "   %-33s ", tmpstr);
8840
8841                 /*
8842                  * If we have 0 periphs, that's a bug...
8843                  */
8844                 if (item->num_periphs == 0) {
8845                         fprintf(stdout, "\n");
8846                         continue;
8847                 }
8848
8849                 fprintf(stdout, "(");
8850                 for (j = 0; j < item->num_periphs; j++) {
8851                         if (j > 0)
8852                                 fprintf(stdout, ",");
8853
8854                         fprintf(stdout, "%s%d",
8855                                 item->periph_matches[j].periph_name,
8856                                 item->periph_matches[j].unit_number);
8857
8858                 }
8859                 fprintf(stdout, ")\n");
8860         }
8861 bailout:
8862         if (ccb != NULL)
8863                 cam_freeccb(ccb);
8864
8865         free(rgrequest);
8866
8867         free(rgresponse);
8868
8869         free(disrequest);
8870
8871         free(disresponse);
8872
8873         freebusdevlist(&devlist);
8874
8875         return (retval);
8876 }
8877
8878 static int
8879 atapm(struct cam_device *device, int argc, char **argv,
8880                  char *combinedopt, int retry_count, int timeout)
8881 {
8882         union ccb *ccb;
8883         int retval = 0;
8884         int t = -1;
8885         int c;
8886         u_char cmd, sc;
8887
8888         ccb = cam_getccb(device);
8889
8890         if (ccb == NULL) {
8891                 warnx("%s: error allocating ccb", __func__);
8892                 return (1);
8893         }
8894
8895         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8896                 switch (c) {
8897                 case 't':
8898                         t = atoi(optarg);
8899                         break;
8900                 default:
8901                         break;
8902                 }
8903         }
8904         if (strcmp(argv[1], "idle") == 0) {
8905                 if (t == -1)
8906                         cmd = ATA_IDLE_IMMEDIATE;
8907                 else
8908                         cmd = ATA_IDLE_CMD;
8909         } else if (strcmp(argv[1], "standby") == 0) {
8910                 if (t == -1)
8911                         cmd = ATA_STANDBY_IMMEDIATE;
8912                 else
8913                         cmd = ATA_STANDBY_CMD;
8914         } else {
8915                 cmd = ATA_SLEEP;
8916                 t = -1;
8917         }
8918
8919         if (t < 0)
8920                 sc = 0;
8921         else if (t <= (240 * 5))
8922                 sc = (t + 4) / 5;
8923         else if (t <= (252 * 5))
8924                 /* special encoding for 21 minutes */
8925                 sc = 252;
8926         else if (t <= (11 * 30 * 60))
8927                 sc = (t - 1) / (30 * 60) + 241;
8928         else
8929                 sc = 253;
8930
8931         retval = ata_do_28bit_cmd(device,
8932             ccb,
8933             /*retries*/retry_count,
8934             /*flags*/CAM_DIR_NONE,
8935             /*protocol*/AP_PROTO_NON_DATA,
8936             /*tag_action*/MSG_SIMPLE_Q_TAG,
8937             /*command*/cmd,
8938             /*features*/0,
8939             /*lba*/0,
8940             /*sector_count*/sc,
8941             /*data_ptr*/NULL,
8942             /*dxfer_len*/0,
8943             /*timeout*/timeout ? timeout : 30 * 1000,
8944             /*quiet*/1);
8945
8946         cam_freeccb(ccb);
8947         return (retval);
8948 }
8949
8950 static int
8951 ataaxm(struct cam_device *device, int argc, char **argv,
8952                  char *combinedopt, int retry_count, int timeout)
8953 {
8954         union ccb *ccb;
8955         int retval = 0;
8956         int l = -1;
8957         int c;
8958         u_char cmd, sc;
8959
8960         ccb = cam_getccb(device);
8961
8962         if (ccb == NULL) {
8963                 warnx("%s: error allocating ccb", __func__);
8964                 return (1);
8965         }
8966
8967         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8968                 switch (c) {
8969                 case 'l':
8970                         l = atoi(optarg);
8971                         break;
8972                 default:
8973                         break;
8974                 }
8975         }
8976         sc = 0;
8977         if (strcmp(argv[1], "apm") == 0) {
8978                 if (l == -1)
8979                         cmd = 0x85;
8980                 else {
8981                         cmd = 0x05;
8982                         sc = l;
8983                 }
8984         } else /* aam */ {
8985                 if (l == -1)
8986                         cmd = 0xC2;
8987                 else {
8988                         cmd = 0x42;
8989                         sc = l;
8990                 }
8991         }
8992
8993         retval = ata_do_28bit_cmd(device,
8994             ccb,
8995             /*retries*/retry_count,
8996             /*flags*/CAM_DIR_NONE,
8997             /*protocol*/AP_PROTO_NON_DATA,
8998             /*tag_action*/MSG_SIMPLE_Q_TAG,
8999             /*command*/ATA_SETFEATURES,
9000             /*features*/cmd,
9001             /*lba*/0,
9002             /*sector_count*/sc,
9003             /*data_ptr*/NULL,
9004             /*dxfer_len*/0,
9005             /*timeout*/timeout ? timeout : 30 * 1000,
9006             /*quiet*/1);
9007
9008         cam_freeccb(ccb);
9009         return (retval);
9010 }
9011
9012 int
9013 scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
9014                int show_sa_errors, int sa_set, int service_action,
9015                int timeout_desc, int task_attr, int retry_count, int timeout,
9016                int verbosemode, uint32_t *fill_len, uint8_t **data_ptr)
9017 {
9018         union ccb *ccb = NULL;
9019         uint8_t *buf = NULL;
9020         uint32_t alloc_len = 0, num_opcodes;
9021         uint32_t valid_len = 0;
9022         uint32_t avail_len = 0;
9023         struct scsi_report_supported_opcodes_all *all_hdr;
9024         struct scsi_report_supported_opcodes_one *one;
9025         int options = 0;
9026         int retval = 0;
9027
9028         /*
9029          * Make it clear that we haven't yet allocated or filled anything.
9030          */
9031         *fill_len = 0;
9032         *data_ptr = NULL;
9033
9034         ccb = cam_getccb(device);
9035         if (ccb == NULL) {
9036                 warnx("couldn't allocate CCB");
9037                 retval = 1;
9038                 goto bailout;
9039         }
9040
9041         /* cam_getccb cleans up the header, caller has to zero the payload */
9042         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
9043
9044         if (opcode_set != 0) {
9045                 options |= RSO_OPTIONS_OC;
9046                 num_opcodes = 1;
9047                 alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
9048         } else {
9049                 num_opcodes = 256;
9050                 alloc_len = sizeof(*all_hdr) + (num_opcodes *
9051                     sizeof(struct scsi_report_supported_opcodes_descr));
9052         }
9053
9054         if (timeout_desc != 0) {
9055                 options |= RSO_RCTD;
9056                 alloc_len += num_opcodes *
9057                     sizeof(struct scsi_report_supported_opcodes_timeout);
9058         }
9059
9060         if (sa_set != 0) {
9061                 options |= RSO_OPTIONS_OC_SA;
9062                 if (show_sa_errors != 0)
9063                         options &= ~RSO_OPTIONS_OC;
9064         }
9065
9066 retry_alloc:
9067         if (buf != NULL) {
9068                 free(buf);
9069                 buf = NULL;
9070         }
9071
9072         buf = malloc(alloc_len);
9073         if (buf == NULL) {
9074                 warn("Unable to allocate %u bytes", alloc_len);
9075                 retval = 1;
9076                 goto bailout;
9077         }
9078         bzero(buf, alloc_len);
9079
9080         scsi_report_supported_opcodes(&ccb->csio,
9081                                       /*retries*/ retry_count,
9082                                       /*cbfcnp*/ NULL,
9083                                       /*tag_action*/ task_attr,
9084                                       /*options*/ options,
9085                                       /*req_opcode*/ opcode,
9086                                       /*req_service_action*/ service_action,
9087                                       /*data_ptr*/ buf,
9088                                       /*dxfer_len*/ alloc_len,
9089                                       /*sense_len*/ SSD_FULL_SIZE,
9090                                       /*timeout*/ timeout ? timeout : 10000);
9091
9092         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
9093
9094         if (retry_count != 0)
9095                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
9096
9097         if (cam_send_ccb(device, ccb) < 0) {
9098                 perror("error sending REPORT SUPPORTED OPERATION CODES");
9099                 retval = 1;
9100                 goto bailout;
9101         }
9102
9103         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
9104                 if (verbosemode != 0)
9105                         cam_error_print(device, ccb, CAM_ESF_ALL,
9106                                         CAM_EPF_ALL, stderr);
9107                 retval = 1;
9108                 goto bailout;
9109         }
9110
9111         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
9112
9113         if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
9114          && (valid_len >= sizeof(*all_hdr))) {
9115                 all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
9116                 avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
9117         } else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
9118                 && (valid_len >= sizeof(*one))) {
9119                 uint32_t cdb_length;
9120
9121                 one = (struct scsi_report_supported_opcodes_one *)buf;
9122                 cdb_length = scsi_2btoul(one->cdb_length);
9123                 avail_len = sizeof(*one) + cdb_length;
9124                 if (one->support & RSO_ONE_CTDP) {
9125                         struct scsi_report_supported_opcodes_timeout *td;
9126
9127                         td = (struct scsi_report_supported_opcodes_timeout *)
9128                             &buf[avail_len];
9129                         if (valid_len >= (avail_len + sizeof(td->length))) {
9130                                 avail_len += scsi_2btoul(td->length) +
9131                                     sizeof(td->length);
9132                         } else {
9133                                 avail_len += sizeof(*td);
9134                         }
9135                 }
9136         }
9137
9138         /*
9139          * avail_len could be zero if we didn't get enough data back from
9140          * thet target to determine
9141          */
9142         if ((avail_len != 0)
9143          && (avail_len > valid_len)) {
9144                 alloc_len = avail_len;
9145                 goto retry_alloc;
9146         }
9147
9148         *fill_len = valid_len;
9149         *data_ptr = buf;
9150 bailout:
9151         if (retval != 0)
9152                 free(buf);
9153
9154         cam_freeccb(ccb);
9155
9156         return (retval);
9157 }
9158
9159 static int
9160 scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
9161                    int req_sa, uint8_t *buf, uint32_t valid_len)
9162 {
9163         struct scsi_report_supported_opcodes_one *one;
9164         struct scsi_report_supported_opcodes_timeout *td;
9165         uint32_t cdb_len = 0, td_len = 0;
9166         const char *op_desc = NULL;
9167         unsigned int i;
9168         int retval = 0;
9169
9170         one = (struct scsi_report_supported_opcodes_one *)buf;
9171
9172         /*
9173          * If we don't have the full single opcode descriptor, no point in
9174          * continuing.
9175          */
9176         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
9177             cdb_length)) {
9178                 warnx("Only %u bytes returned, not enough to verify support",
9179                       valid_len);
9180                 retval = 1;
9181                 goto bailout;
9182         }
9183
9184         op_desc = scsi_op_desc(req_opcode, &device->inq_data);
9185
9186         printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
9187                req_opcode);
9188         if (sa_set != 0)
9189                 printf(", SA 0x%x", req_sa);
9190         printf(": ");
9191
9192         switch (one->support & RSO_ONE_SUP_MASK) {
9193         case RSO_ONE_SUP_UNAVAIL:
9194                 printf("No command support information currently available\n");
9195                 break;
9196         case RSO_ONE_SUP_NOT_SUP:
9197                 printf("Command not supported\n");
9198                 retval = 1;
9199                 goto bailout;
9200                 break; /*NOTREACHED*/
9201         case RSO_ONE_SUP_AVAIL:
9202                 printf("Command is supported, complies with a SCSI standard\n");
9203                 break;
9204         case RSO_ONE_SUP_VENDOR:
9205                 printf("Command is supported, vendor-specific "
9206                        "implementation\n");
9207                 break;
9208         default:
9209                 printf("Unknown command support flags 0x%#x\n",
9210                        one->support & RSO_ONE_SUP_MASK);
9211                 break;
9212         }
9213
9214         /*
9215          * If we don't have the CDB length, it isn't exactly an error, the
9216          * command probably isn't supported.
9217          */
9218         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
9219             cdb_usage))
9220                 goto bailout;
9221
9222         cdb_len = scsi_2btoul(one->cdb_length);
9223
9224         /*
9225          * If our valid data doesn't include the full reported length,
9226          * return.  The caller should have detected this and adjusted his
9227          * allocation length to get all of the available data.
9228          */
9229         if (valid_len < sizeof(*one) + cdb_len) {
9230                 retval = 1;
9231                 goto bailout;
9232         }
9233
9234         /*
9235          * If all we have is the opcode, there is no point in printing out
9236          * the usage bitmap.
9237          */
9238         if (cdb_len <= 1) {
9239                 retval = 1;
9240                 goto bailout;
9241         }
9242
9243         printf("CDB usage bitmap:");
9244         for (i = 0; i < cdb_len; i++) {
9245                 printf(" %02x", one->cdb_usage[i]);
9246         }
9247         printf("\n");
9248
9249         /*
9250          * If we don't have a timeout descriptor, we're done.
9251          */
9252         if ((one->support & RSO_ONE_CTDP) == 0)
9253                 goto bailout;
9254
9255         /*
9256          * If we don't have enough valid length to include the timeout
9257          * descriptor length, we're done.
9258          */
9259         if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
9260                 goto bailout;
9261
9262         td = (struct scsi_report_supported_opcodes_timeout *)
9263             &buf[sizeof(*one) + cdb_len];
9264         td_len = scsi_2btoul(td->length);
9265         td_len += sizeof(td->length);
9266
9267         /*
9268          * If we don't have the full timeout descriptor, we're done.
9269          */
9270         if (td_len < sizeof(*td))
9271                 goto bailout;
9272
9273         /*
9274          * If we don't have enough valid length to contain the full timeout
9275          * descriptor, we're done.
9276          */
9277         if (valid_len < (sizeof(*one) + cdb_len + td_len))
9278                 goto bailout;
9279
9280         printf("Timeout information:\n");
9281         printf("Command-specific:    0x%02x\n", td->cmd_specific);
9282         printf("Nominal timeout:     %u seconds\n",
9283                scsi_4btoul(td->nominal_time));
9284         printf("Recommended timeout: %u seconds\n",
9285                scsi_4btoul(td->recommended_time));
9286
9287 bailout:
9288         return (retval);
9289 }
9290
9291 static int
9292 scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
9293                  uint32_t valid_len)
9294 {
9295         struct scsi_report_supported_opcodes_all *hdr;
9296         struct scsi_report_supported_opcodes_descr *desc;
9297         uint32_t avail_len = 0, used_len = 0;
9298         uint8_t *cur_ptr;
9299         int retval = 0;
9300
9301         if (valid_len < sizeof(*hdr)) {
9302                 warnx("%s: not enough returned data (%u bytes) opcode list",
9303                       __func__, valid_len);
9304                 retval = 1;
9305                 goto bailout;
9306         }
9307         hdr = (struct scsi_report_supported_opcodes_all *)buf;
9308         avail_len = scsi_4btoul(hdr->length);
9309         avail_len += sizeof(hdr->length);
9310         /*
9311          * Take the lesser of the amount of data the drive claims is
9312          * available, and the amount of data the HBA says was returned.
9313          */
9314         avail_len = MIN(avail_len, valid_len);
9315
9316         used_len = sizeof(hdr->length);
9317
9318         printf("%-6s %4s %8s ",
9319                "Opcode", "SA", "CDB len" );
9320
9321         if (td_req != 0)
9322                 printf("%5s %6s %6s ", "CS", "Nom", "Rec");
9323         printf(" Description\n");
9324
9325         while ((avail_len - used_len) > sizeof(*desc)) {
9326                 struct scsi_report_supported_opcodes_timeout *td;
9327                 uint32_t td_len;
9328                 const char *op_desc = NULL;
9329
9330                 cur_ptr = &buf[used_len];
9331                 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
9332
9333                 op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
9334                 if (op_desc == NULL)
9335                         op_desc = "UNKNOWN";
9336
9337                 printf("0x%02x   %#4x %8u ", desc->opcode,
9338                        scsi_2btoul(desc->service_action),
9339                        scsi_2btoul(desc->cdb_length));
9340
9341                 used_len += sizeof(*desc);
9342
9343                 if ((desc->flags & RSO_CTDP) == 0) {
9344                         printf(" %s\n", op_desc);
9345                         continue;
9346                 }
9347
9348                 /*
9349                  * If we don't have enough space to fit a timeout
9350                  * descriptor, then we're done.
9351                  */
9352                 if (avail_len - used_len < sizeof(*td)) {
9353                         used_len = avail_len;
9354                         printf(" %s\n", op_desc);
9355                         continue;
9356                 }
9357                 cur_ptr = &buf[used_len];
9358                 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
9359                 td_len = scsi_2btoul(td->length);
9360                 td_len += sizeof(td->length);
9361
9362                 used_len += td_len;
9363                 /*
9364                  * If the given timeout descriptor length is less than what
9365                  * we understand, skip it.
9366                  */
9367                 if (td_len < sizeof(*td)) {
9368                         printf(" %s\n", op_desc);
9369                         continue;
9370                 }
9371
9372                 printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
9373                        scsi_4btoul(td->nominal_time),
9374                        scsi_4btoul(td->recommended_time), op_desc);
9375         }
9376 bailout:
9377         return (retval);
9378 }
9379
9380 static int
9381 scsiopcodes(struct cam_device *device, int argc, char **argv,
9382             char *combinedopt, int task_attr, int retry_count, int timeout,
9383             int verbosemode)
9384 {
9385         int c;
9386         uint32_t opcode = 0, service_action = 0;
9387         int td_set = 0, opcode_set = 0, sa_set = 0;
9388         int show_sa_errors = 1;
9389         uint32_t valid_len = 0;
9390         uint8_t *buf = NULL;
9391         char *endptr;
9392         int retval = 0;
9393
9394         while ((c = getopt(argc, argv, combinedopt)) != -1) {
9395                 switch (c) {
9396                 case 'N':
9397                         show_sa_errors = 0;
9398                         break;
9399                 case 'o':
9400                         opcode = strtoul(optarg, &endptr, 0);
9401                         if (*endptr != '\0') {
9402                                 warnx("Invalid opcode \"%s\", must be a number",
9403                                       optarg);
9404                                 retval = 1;
9405                                 goto bailout;
9406                         }
9407                         if (opcode > 0xff) {
9408                                 warnx("Invalid opcode 0x%#x, must be between"
9409                                       "0 and 0xff inclusive", opcode);
9410                                 retval = 1;
9411                                 goto bailout;
9412                         }
9413                         opcode_set = 1;
9414                         break;
9415                 case 's':
9416                         service_action = strtoul(optarg, &endptr, 0);
9417                         if (*endptr != '\0') {
9418                                 warnx("Invalid service action \"%s\", must "
9419                                       "be a number", optarg);
9420                                 retval = 1;
9421                                 goto bailout;
9422                         }
9423                         if (service_action > 0xffff) {
9424                                 warnx("Invalid service action 0x%#x, must "
9425                                       "be between 0 and 0xffff inclusive",
9426                                       service_action);
9427                                 retval = 1;
9428                         }
9429                         sa_set = 1;
9430                         break;
9431                 case 'T':
9432                         td_set = 1;
9433                         break;
9434                 default:
9435                         break;
9436                 }
9437         }
9438
9439         if ((sa_set != 0)
9440          && (opcode_set == 0)) {
9441                 warnx("You must specify an opcode with -o if a service "
9442                       "action is given");
9443                 retval = 1;
9444                 goto bailout;
9445         }
9446         retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
9447                                 sa_set, service_action, td_set, task_attr,
9448                                 retry_count, timeout, verbosemode, &valid_len,
9449                                 &buf);
9450         if (retval != 0)
9451                 goto bailout;
9452
9453         if ((opcode_set != 0)
9454          || (sa_set != 0)) {
9455                 retval = scsiprintoneopcode(device, opcode, sa_set,
9456                                             service_action, buf, valid_len);
9457         } else {
9458                 retval = scsiprintopcodes(device, td_set, buf, valid_len);
9459         }
9460
9461 bailout:
9462         free(buf);
9463
9464         return (retval);
9465 }
9466
9467 #endif /* MINIMALISTIC */
9468
9469 static int
9470 scsireprobe(struct cam_device *device)
9471 {
9472         union ccb *ccb;
9473         int retval = 0;
9474
9475         ccb = cam_getccb(device);
9476
9477         if (ccb == NULL) {
9478                 warnx("%s: error allocating ccb", __func__);
9479                 return (1);
9480         }
9481
9482         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
9483
9484         ccb->ccb_h.func_code = XPT_REPROBE_LUN;
9485
9486         if (cam_send_ccb(device, ccb) < 0) {
9487                 warn("error sending XPT_REPROBE_LUN CCB");
9488                 retval = 1;
9489                 goto bailout;
9490         }
9491
9492         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
9493                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
9494                 retval = 1;
9495                 goto bailout;
9496         }
9497
9498 bailout:
9499         cam_freeccb(ccb);
9500
9501         return (retval);
9502 }
9503
9504 void
9505 usage(int printlong)
9506 {
9507
9508         fprintf(printlong ? stdout : stderr,
9509 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
9510 "        camcontrol devlist    [-b] [-v]\n"
9511 #ifndef MINIMALISTIC
9512 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
9513 "        camcontrol tur        [dev_id][generic args]\n"
9514 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
9515 "        camcontrol identify   [dev_id][generic args] [-v]\n"
9516 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
9517 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
9518 "                              [-q] [-s]\n"
9519 "        camcontrol start      [dev_id][generic args]\n"
9520 "        camcontrol stop       [dev_id][generic args]\n"
9521 "        camcontrol load       [dev_id][generic args]\n"
9522 "        camcontrol eject      [dev_id][generic args]\n"
9523 "        camcontrol reprobe    [dev_id][generic args]\n"
9524 #endif /* MINIMALISTIC */
9525 "        camcontrol rescan     <all | bus[:target:lun] | dev_id>\n"
9526 "        camcontrol reset      <all | bus[:target:lun] | dev_id>\n"
9527 #ifndef MINIMALISTIC
9528 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
9529 "                              [-q][-s][-S offset][-X]\n"
9530 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
9531 "                              [-P pagectl][-e | -b][-d]\n"
9532 "        camcontrol cmd        [dev_id][generic args]\n"
9533 "                              <-a cmd [args] | -c cmd [args]>\n"
9534 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
9535 "        camcontrol smpcmd     [dev_id][generic args]\n"
9536 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
9537 "        camcontrol smprg      [dev_id][generic args][-l]\n"
9538 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
9539 "                              [-o operation][-d name][-m rate][-M rate]\n"
9540 "                              [-T pp_timeout][-a enable|disable]\n"
9541 "                              [-A enable|disable][-s enable|disable]\n"
9542 "                              [-S enable|disable]\n"
9543 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
9544 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
9545 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
9546 "                              <all|bus[:target[:lun]]|off>\n"
9547 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
9548 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
9549 "                              [-D <enable|disable>][-M mode][-O offset]\n"
9550 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
9551 "                              [-U][-W bus_width]\n"
9552 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
9553 "        camcontrol sanitize   [dev_id][generic args]\n"
9554 "                              [-a overwrite|block|crypto|exitfailure]\n"
9555 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
9556 "                              [-y]\n"
9557 "        camcontrol idle       [dev_id][generic args][-t time]\n"
9558 "        camcontrol standby    [dev_id][generic args][-t time]\n"
9559 "        camcontrol sleep      [dev_id][generic args]\n"
9560 "        camcontrol apm        [dev_id][generic args][-l level]\n"
9561 "        camcontrol aam        [dev_id][generic args][-l level]\n"
9562 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
9563 "                              [-s][-y]\n"
9564 "        camcontrol security   [dev_id][generic args]\n"
9565 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
9566 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
9567 "                              [-U <user|master>] [-y]\n"
9568 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
9569 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
9570 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
9571 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
9572 "                              [-s scope][-S][-T type][-U]\n"
9573 "        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
9574 "                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
9575 "                              [-p part][-s start][-T type][-V vol]\n"
9576 "        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
9577 "                              [-N][-T]\n"
9578 "        camcontrol zone       [dev_id][generic args]<-c cmd> [-a] [-l LBA]\n"
9579 "                              [-o rep_opts] [-P print_opts]\n"
9580 "        camcontrol epc        [dev_id][generic_args]<-c cmd> [-d] [-D] [-e]\n"
9581 "                              [-H] [-p power_cond] [-P] [-r rst_src] [-s]\n"
9582 "                              [-S power_src] [-T timer]\n"
9583 "        camcontrol timestamp  [dev_id][generic_args] <-r [-f format|-m|-U]>|\n"
9584 "                              <-s <-f format -T time | -U >>\n"
9585 "                              \n"
9586 #endif /* MINIMALISTIC */
9587 "        camcontrol help\n");
9588         if (!printlong)
9589                 return;
9590 #ifndef MINIMALISTIC
9591         fprintf(stdout,
9592 "Specify one of the following options:\n"
9593 "devlist     list all CAM devices\n"
9594 "periphlist  list all CAM peripheral drivers attached to a device\n"
9595 "tur         send a test unit ready to the named device\n"
9596 "inquiry     send a SCSI inquiry command to the named device\n"
9597 "identify    send a ATA identify command to the named device\n"
9598 "reportluns  send a SCSI report luns command to the device\n"
9599 "readcap     send a SCSI read capacity command to the device\n"
9600 "start       send a Start Unit command to the device\n"
9601 "stop        send a Stop Unit command to the device\n"
9602 "load        send a Start Unit command to the device with the load bit set\n"
9603 "eject       send a Stop Unit command to the device with the eject bit set\n"
9604 "reprobe     update capacity information of the given device\n"
9605 "rescan      rescan all buses, the given bus, bus:target:lun or device\n"
9606 "reset       reset all buses, the given bus, bus:target:lun or device\n"
9607 "defects     read the defect list of the specified device\n"
9608 "modepage    display or edit (-e) the given mode page\n"
9609 "cmd         send the given SCSI command, may need -i or -o as well\n"
9610 "smpcmd      send the given SMP command, requires -o and -i\n"
9611 "smprg       send the SMP Report General command\n"
9612 "smppc       send the SMP PHY Control command, requires -p\n"
9613 "smpphylist  display phys attached to a SAS expander\n"
9614 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
9615 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
9616 "tags        report or set the number of transaction slots for a device\n"
9617 "negotiate   report or set device negotiation parameters\n"
9618 "format      send the SCSI FORMAT UNIT command to the named device\n"
9619 "sanitize    send the SCSI SANITIZE command to the named device\n"
9620 "idle        send the ATA IDLE command to the named device\n"
9621 "standby     send the ATA STANDBY command to the named device\n"
9622 "sleep       send the ATA SLEEP command to the named device\n"
9623 "fwdownload  program firmware of the named device with the given image\n"
9624 "security    report or send ATA security commands to the named device\n"
9625 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
9626 "attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
9627 "opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
9628 "zone        manage Zoned Block (Shingled) devices\n"
9629 "epc         send ATA Extended Power Conditions commands\n"
9630 "timestamp   report or set the device's timestamp\n"
9631 "help        this message\n"
9632 "Device Identifiers:\n"
9633 "bus:target        specify the bus and target, lun defaults to 0\n"
9634 "bus:target:lun    specify the bus, target and lun\n"
9635 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
9636 "Generic arguments:\n"
9637 "-v                be verbose, print out sense information\n"
9638 "-t timeout        command timeout in seconds, overrides default timeout\n"
9639 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
9640 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
9641 "-E                have the kernel attempt to perform SCSI error recovery\n"
9642 "-C count          specify the SCSI command retry count (needs -E to work)\n"
9643 "-Q task_attr      specify ordered, simple or head tag type for SCSI cmds\n"
9644 "modepage arguments:\n"
9645 "-l                list all available mode pages\n"
9646 "-m page           specify the mode page to view or edit\n"
9647 "-e                edit the specified mode page\n"
9648 "-b                force view to binary mode\n"
9649 "-d                disable block descriptors for mode sense\n"
9650 "-P pgctl          page control field 0-3\n"
9651 "defects arguments:\n"
9652 "-f format         specify defect list format (block, bfi or phys)\n"
9653 "-G                get the grown defect list\n"
9654 "-P                get the permanent defect list\n"
9655 "inquiry arguments:\n"
9656 "-D                get the standard inquiry data\n"
9657 "-S                get the serial number\n"
9658 "-R                get the transfer rate, etc.\n"
9659 "reportluns arguments:\n"
9660 "-c                only report a count of available LUNs\n"
9661 "-l                only print out luns, and not a count\n"
9662 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
9663 "readcap arguments\n"
9664 "-b                only report the blocksize\n"
9665 "-h                human readable device size, base 2\n"
9666 "-H                human readable device size, base 10\n"
9667 "-N                print the number of blocks instead of last block\n"
9668 "-q                quiet, print numbers only\n"
9669 "-s                only report the last block/device size\n"
9670 "cmd arguments:\n"
9671 "-c cdb [args]     specify the SCSI CDB\n"
9672 "-i len fmt        specify input data and input data format\n"
9673 "-o len fmt [args] specify output data and output data fmt\n"
9674 "smpcmd arguments:\n"
9675 "-r len fmt [args] specify the SMP command to be sent\n"
9676 "-R len fmt [args] specify SMP response format\n"
9677 "smprg arguments:\n"
9678 "-l                specify the long response format\n"
9679 "smppc arguments:\n"
9680 "-p phy            specify the PHY to operate on\n"
9681 "-l                specify the long request/response format\n"
9682 "-o operation      specify the phy control operation\n"
9683 "-d name           set the attached device name\n"
9684 "-m rate           set the minimum physical link rate\n"
9685 "-M rate           set the maximum physical link rate\n"
9686 "-T pp_timeout     set the partial pathway timeout value\n"
9687 "-a enable|disable enable or disable SATA slumber\n"
9688 "-A enable|disable enable or disable SATA partial phy power\n"
9689 "-s enable|disable enable or disable SAS slumber\n"
9690 "-S enable|disable enable or disable SAS partial phy power\n"
9691 "smpphylist arguments:\n"
9692 "-l                specify the long response format\n"
9693 "-q                only print phys with attached devices\n"
9694 "smpmaninfo arguments:\n"
9695 "-l                specify the long response format\n"
9696 "debug arguments:\n"
9697 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
9698 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
9699 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
9700 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
9701 "tags arguments:\n"
9702 "-N tags           specify the number of tags to use for this device\n"
9703 "-q                be quiet, don't report the number of tags\n"
9704 "-v                report a number of tag-related parameters\n"
9705 "negotiate arguments:\n"
9706 "-a                send a test unit ready after negotiation\n"
9707 "-c                report/set current negotiation settings\n"
9708 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
9709 "-M mode           set ATA mode\n"
9710 "-O offset         set command delay offset\n"
9711 "-q                be quiet, don't report anything\n"
9712 "-R syncrate       synchronization rate in MHz\n"
9713 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
9714 "-U                report/set user negotiation settings\n"
9715 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
9716 "-v                also print a Path Inquiry CCB for the controller\n"
9717 "format arguments:\n"
9718 "-q                be quiet, don't print status messages\n"
9719 "-r                run in report only mode\n"
9720 "-w                don't send immediate format command\n"
9721 "-y                don't ask any questions\n"
9722 "sanitize arguments:\n"
9723 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
9724 "-c passes         overwrite passes to perform (1 to 31)\n"
9725 "-I                invert overwrite pattern after each pass\n"
9726 "-P pattern        path to overwrite pattern file\n"
9727 "-q                be quiet, don't print status messages\n"
9728 "-r                run in report only mode\n"
9729 "-U                run operation in unrestricted completion exit mode\n"
9730 "-w                don't send immediate sanitize command\n"
9731 "-y                don't ask any questions\n"
9732 "idle/standby arguments:\n"
9733 "-t <arg>          number of seconds before respective state.\n"
9734 "fwdownload arguments:\n"
9735 "-f fw_image       path to firmware image file\n"
9736 "-q                don't print informational messages, only errors\n"
9737 "-s                run in simulation mode\n"
9738 "-v                print info for every firmware segment sent to device\n"
9739 "-y                don't ask any questions\n"
9740 "security arguments:\n"
9741 "-d pwd            disable security using the given password for the selected\n"
9742 "                  user\n"
9743 "-e pwd            erase the device using the given pwd for the selected user\n"
9744 "-f                freeze the security configuration of the specified device\n"
9745 "-h pwd            enhanced erase the device using the given pwd for the\n"
9746 "                  selected user\n"
9747 "-k pwd            unlock the device using the given pwd for the selected\n"
9748 "                  user\n"
9749 "-l <high|maximum> specifies which security level to set: high or maximum\n"
9750 "-q                be quiet, do not print any status messages\n"
9751 "-s pwd            password the device (enable security) using the given\n"
9752 "                  pwd for the selected user\n"
9753 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
9754 "-U <user|master>  specifies which user to set: user or master\n"
9755 "-y                don't ask any questions\n"
9756 "hpa arguments:\n"
9757 "-f                freeze the HPA configuration of the device\n"
9758 "-l                lock the HPA configuration of the device\n"
9759 "-P                make the HPA max sectors persist\n"
9760 "-p pwd            Set the HPA configuration password required for unlock\n"
9761 "                  calls\n"
9762 "-q                be quiet, do not print any status messages\n"
9763 "-s sectors        configures the maximum user accessible sectors of the\n"
9764 "                  device\n"
9765 "-U pwd            unlock the HPA configuration of the device\n"
9766 "-y                don't ask any questions\n"
9767 "persist arguments:\n"
9768 "-i action         specify read_keys, read_reservation, report_cap, or\n"
9769 "                  read_full_status\n"
9770 "-o action         specify register, register_ignore, reserve, release,\n"
9771 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
9772 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
9773 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
9774 "-k key            specify the Reservation Key\n"
9775 "-K sa_key         specify the Service Action Reservation Key\n"
9776 "-p                set the Activate Persist Through Power Loss bit\n"
9777 "-R rtp            specify the Relative Target Port\n"
9778 "-s scope          specify the scope: lun, extent, element or a number\n"
9779 "-S                specify Transport ID for register, requires -I\n"
9780 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
9781 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
9782 "-U                unregister the current initiator for register_move\n"
9783 "attrib arguments:\n"
9784 "-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
9785 "                  supp_attr\n"
9786 "-w attr           specify an attribute to write, one -w argument per attr\n"
9787 "-a attr_num       only display this attribute number\n"
9788 "-c                get cached attributes\n"
9789 "-e elem_addr      request attributes for the given element in a changer\n"
9790 "-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
9791 "                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
9792 "                  field_none, field_desc, field_num, field_size, field_rw\n"
9793 "-p partition      request attributes for the given partition\n"
9794 "-s start_attr     request attributes starting at the given number\n"
9795 "-T elem_type      specify the element type (used with -e)\n"
9796 "-V logical_vol    specify the logical volume ID\n"
9797 "opcodes arguments:\n"
9798 "-o opcode         specify the individual opcode to list\n"
9799 "-s service_action specify the service action for the opcode\n"
9800 "-N                do not return SCSI error for unsupported SA\n"
9801 "-T                request nominal and recommended timeout values\n"
9802 "zone arguments:\n"
9803 "-c cmd            required: rz, open, close, finish, or rwp\n"
9804 "-a                apply the action to all zones\n"
9805 "-l LBA            specify the zone starting LBA\n"
9806 "-o rep_opts       report zones options: all, empty, imp_open, exp_open,\n"
9807 "                  closed, full, ro, offline, reset, nonseq, nonwp\n"
9808 "-P print_opt      report zones printing:  normal, summary, script\n"
9809 "epc arguments:\n"
9810 "-c cmd            required: restore, goto, timer, state, enable, disable,\n"
9811 "                  source, status, list\n"
9812 "-d                disable power mode (timer, state)\n"
9813 "-D                delayed entry (goto)\n"
9814 "-e                enable power mode (timer, state)\n"
9815 "-H                hold power mode (goto)\n"
9816 "-p power_cond     Idle_a, Idle_b, Idle_c, Standby_y, Standby_z (timer,\n"
9817 "                  state, goto)\n"
9818 "-P                only display power mode (status)\n"
9819 "-r rst_src        restore settings from: default, saved (restore)\n"
9820 "-s                save mode (timer, state, restore)\n"
9821 "-S power_src      set power source: battery, nonbattery (source)\n"
9822 "-T timer          set timer, seconds, .1 sec resolution (timer)\n"
9823 "timestamp arguments:\n"
9824 "-r                report the timestamp of the device\n"
9825 "-f format         report the timestamp of the device with the given\n"
9826 "                  strftime(3) format string\n"
9827 "-m                report the timestamp of the device as milliseconds since\n"
9828 "                  January 1st, 1970\n"
9829 "-U                report the time with UTC instead of the local time zone\n"
9830 "-s                set the timestamp of the device\n"
9831 "-f format         the format of the time string passed into strptime(3)\n"
9832 "-T time           the time value passed into strptime(3)\n"
9833 "-U                set the timestamp of the device to UTC time\n"
9834 );
9835 #endif /* MINIMALISTIC */
9836 }
9837
9838 int
9839 main(int argc, char **argv)
9840 {
9841         int c;
9842         char *device = NULL;
9843         int unit = 0;
9844         struct cam_device *cam_dev = NULL;
9845         int timeout = 0, retry_count = 1;
9846         camcontrol_optret optreturn;
9847         char *tstr;
9848         const char *mainopt = "C:En:Q:t:u:v";
9849         const char *subopt = NULL;
9850         char combinedopt[256];
9851         int error = 0, optstart = 2;
9852         int task_attr = MSG_SIMPLE_Q_TAG;
9853         int devopen = 1;
9854 #ifndef MINIMALISTIC
9855         path_id_t bus;
9856         target_id_t target;
9857         lun_id_t lun;
9858 #endif /* MINIMALISTIC */
9859
9860         cmdlist = CAM_CMD_NONE;
9861         arglist = CAM_ARG_NONE;
9862
9863         if (argc < 2) {
9864                 usage(0);
9865                 exit(1);
9866         }
9867
9868         /*
9869          * Get the base option.
9870          */
9871         optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
9872
9873         if (optreturn == CC_OR_AMBIGUOUS) {
9874                 warnx("ambiguous option %s", argv[1]);
9875                 usage(0);
9876                 exit(1);
9877         } else if (optreturn == CC_OR_NOT_FOUND) {
9878                 warnx("option %s not found", argv[1]);
9879                 usage(0);
9880                 exit(1);
9881         }
9882
9883         /*
9884          * Ahh, getopt(3) is a pain.
9885          *
9886          * This is a gross hack.  There really aren't many other good
9887          * options (excuse the pun) for parsing options in a situation like
9888          * this.  getopt is kinda braindead, so you end up having to run
9889          * through the options twice, and give each invocation of getopt
9890          * the option string for the other invocation.
9891          *
9892          * You would think that you could just have two groups of options.
9893          * The first group would get parsed by the first invocation of
9894          * getopt, and the second group would get parsed by the second
9895          * invocation of getopt.  It doesn't quite work out that way.  When
9896          * the first invocation of getopt finishes, it leaves optind pointing
9897          * to the argument _after_ the first argument in the second group.
9898          * So when the second invocation of getopt comes around, it doesn't
9899          * recognize the first argument it gets and then bails out.
9900          *
9901          * A nice alternative would be to have a flag for getopt that says
9902          * "just keep parsing arguments even when you encounter an unknown
9903          * argument", but there isn't one.  So there's no real clean way to
9904          * easily parse two sets of arguments without having one invocation
9905          * of getopt know about the other.
9906          *
9907          * Without this hack, the first invocation of getopt would work as
9908          * long as the generic arguments are first, but the second invocation
9909          * (in the subfunction) would fail in one of two ways.  In the case
9910          * where you don't set optreset, it would fail because optind may be
9911          * pointing to the argument after the one it should be pointing at.
9912          * In the case where you do set optreset, and reset optind, it would
9913          * fail because getopt would run into the first set of options, which
9914          * it doesn't understand.
9915          *
9916          * All of this would "sort of" work if you could somehow figure out
9917          * whether optind had been incremented one option too far.  The
9918          * mechanics of that, however, are more daunting than just giving
9919          * both invocations all of the expect options for either invocation.
9920          *
9921          * Needless to say, I wouldn't mind if someone invented a better
9922          * (non-GPL!) command line parsing interface than getopt.  I
9923          * wouldn't mind if someone added more knobs to getopt to make it
9924          * work better.  Who knows, I may talk myself into doing it someday,
9925          * if the standards weenies let me.  As it is, it just leads to
9926          * hackery like this and causes people to avoid it in some cases.
9927          *
9928          * KDM, September 8th, 1998
9929          */
9930         if (subopt != NULL)
9931                 sprintf(combinedopt, "%s%s", mainopt, subopt);
9932         else
9933                 sprintf(combinedopt, "%s", mainopt);
9934
9935         /*
9936          * For these options we do not parse optional device arguments and
9937          * we do not open a passthrough device.
9938          */
9939         if ((cmdlist == CAM_CMD_RESCAN)
9940          || (cmdlist == CAM_CMD_RESET)
9941          || (cmdlist == CAM_CMD_DEVTREE)
9942          || (cmdlist == CAM_CMD_USAGE)
9943          || (cmdlist == CAM_CMD_DEBUG))
9944                 devopen = 0;
9945
9946 #ifndef MINIMALISTIC
9947         if ((devopen == 1)
9948          && (argc > 2 && argv[2][0] != '-')) {
9949                 char name[30];
9950                 int rv;
9951
9952                 if (isdigit(argv[2][0])) {
9953                         /* device specified as bus:target[:lun] */
9954                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9955                         if (rv < 2)
9956                                 errx(1, "numeric device specification must "
9957                                      "be either bus:target, or "
9958                                      "bus:target:lun");
9959                         /* default to 0 if lun was not specified */
9960                         if ((arglist & CAM_ARG_LUN) == 0) {
9961                                 lun = 0;
9962                                 arglist |= CAM_ARG_LUN;
9963                         }
9964                         optstart++;
9965                 } else {
9966                         if (cam_get_device(argv[2], name, sizeof name, &unit)
9967                             == -1)
9968                                 errx(1, "%s", cam_errbuf);
9969                         device = strdup(name);
9970                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9971                         optstart++;
9972                 }
9973         }
9974 #endif /* MINIMALISTIC */
9975         /*
9976          * Start getopt processing at argv[2/3], since we've already
9977          * accepted argv[1..2] as the command name, and as a possible
9978          * device name.
9979          */
9980         optind = optstart;
9981
9982         /*
9983          * Now we run through the argument list looking for generic
9984          * options, and ignoring options that possibly belong to
9985          * subfunctions.
9986          */
9987         while ((c = getopt(argc, argv, combinedopt))!= -1){
9988                 switch(c) {
9989                         case 'C':
9990                                 retry_count = strtol(optarg, NULL, 0);
9991                                 if (retry_count < 0)
9992                                         errx(1, "retry count %d is < 0",
9993                                              retry_count);
9994                                 arglist |= CAM_ARG_RETRIES;
9995                                 break;
9996                         case 'E':
9997                                 arglist |= CAM_ARG_ERR_RECOVER;
9998                                 break;
9999                         case 'n':
10000                                 arglist |= CAM_ARG_DEVICE;
10001                                 tstr = optarg;
10002                                 while (isspace(*tstr) && (*tstr != '\0'))
10003                                         tstr++;
10004                                 device = (char *)strdup(tstr);
10005                                 break;
10006                         case 'Q': {
10007                                 char *endptr;
10008                                 int table_entry = 0;
10009
10010                                 tstr = optarg;
10011                                 while (isspace(*tstr) && (*tstr != '\0'))
10012                                         tstr++;
10013                                 if (isdigit(*tstr)) {
10014                                         task_attr = strtol(tstr, &endptr, 0);
10015                                         if (*endptr != '\0') {
10016                                                 errx(1, "Invalid queue option "
10017                                                     "%s", tstr);
10018                                         }
10019                                 } else {
10020                                         size_t table_size;
10021                                         scsi_nv_status status;
10022
10023                                         table_size = sizeof(task_attrs) /
10024                                                      sizeof(task_attrs[0]);
10025                                         status = scsi_get_nv(task_attrs,
10026                                             table_size, tstr, &table_entry,
10027                                             SCSI_NV_FLAG_IG_CASE);
10028                                         if (status == SCSI_NV_FOUND)
10029                                                 task_attr = task_attrs[
10030                                                     table_entry].value;
10031                                         else {
10032                                                 errx(1, "%s option %s",
10033                                                   (status == SCSI_NV_AMBIGUOUS)?
10034                                                     "ambiguous" : "invalid",
10035                                                     tstr);
10036                                         }
10037                                 }
10038                                 break;
10039                         }
10040                         case 't':
10041                                 timeout = strtol(optarg, NULL, 0);
10042                                 if (timeout < 0)
10043                                         errx(1, "invalid timeout %d", timeout);
10044                                 /* Convert the timeout from seconds to ms */
10045                                 timeout *= 1000;
10046                                 arglist |= CAM_ARG_TIMEOUT;
10047                                 break;
10048                         case 'u':
10049                                 arglist |= CAM_ARG_UNIT;
10050                                 unit = strtol(optarg, NULL, 0);
10051                                 break;
10052                         case 'v':
10053                                 arglist |= CAM_ARG_VERBOSE;
10054                                 break;
10055                         default:
10056                                 break;
10057                 }
10058         }
10059
10060 #ifndef MINIMALISTIC
10061         /*
10062          * For most commands we'll want to open the passthrough device
10063          * associated with the specified device.  In the case of the rescan
10064          * commands, we don't use a passthrough device at all, just the
10065          * transport layer device.
10066          */
10067         if (devopen == 1) {
10068                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
10069                  && (((arglist & CAM_ARG_DEVICE) == 0)
10070                   || ((arglist & CAM_ARG_UNIT) == 0))) {
10071                         errx(1, "subcommand \"%s\" requires a valid device "
10072                              "identifier", argv[1]);
10073                 }
10074
10075                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
10076                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
10077                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
10078                      == NULL)
10079                         errx(1,"%s", cam_errbuf);
10080         }
10081 #endif /* MINIMALISTIC */
10082
10083         /*
10084          * Reset optind to 2, and reset getopt, so these routines can parse
10085          * the arguments again.
10086          */
10087         optind = optstart;
10088         optreset = 1;
10089
10090         switch(cmdlist) {
10091 #ifndef MINIMALISTIC
10092         case CAM_CMD_DEVLIST:
10093                 error = getdevlist(cam_dev);
10094                 break;
10095         case CAM_CMD_HPA:
10096                 error = atahpa(cam_dev, retry_count, timeout,
10097                                argc, argv, combinedopt);
10098                 break;
10099 #endif /* MINIMALISTIC */
10100         case CAM_CMD_DEVTREE:
10101                 error = getdevtree(argc, argv, combinedopt);
10102                 break;
10103 #ifndef MINIMALISTIC
10104         case CAM_CMD_TUR:
10105                 error = testunitready(cam_dev, task_attr, retry_count,
10106                     timeout, 0);
10107                 break;
10108         case CAM_CMD_INQUIRY:
10109                 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
10110                                       task_attr, retry_count, timeout);
10111                 break;
10112         case CAM_CMD_IDENTIFY:
10113                 error = identify(cam_dev, retry_count, timeout);
10114                 break;
10115         case CAM_CMD_STARTSTOP:
10116                 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
10117                                   arglist & CAM_ARG_EJECT, task_attr,
10118                                   retry_count, timeout);
10119                 break;
10120 #endif /* MINIMALISTIC */
10121         case CAM_CMD_RESCAN:
10122                 error = dorescan_or_reset(argc, argv, 1);
10123                 break;
10124         case CAM_CMD_RESET:
10125                 error = dorescan_or_reset(argc, argv, 0);
10126                 break;
10127 #ifndef MINIMALISTIC
10128         case CAM_CMD_READ_DEFECTS:
10129                 error = readdefects(cam_dev, argc, argv, combinedopt,
10130                                     task_attr, retry_count, timeout);
10131                 break;
10132         case CAM_CMD_MODE_PAGE:
10133                 modepage(cam_dev, argc, argv, combinedopt,
10134                          task_attr, retry_count, timeout);
10135                 break;
10136         case CAM_CMD_SCSI_CMD:
10137                 error = scsicmd(cam_dev, argc, argv, combinedopt,
10138                                 task_attr, retry_count, timeout);
10139                 break;
10140         case CAM_CMD_MMCSD_CMD:
10141                 error = mmcsdcmd(cam_dev, argc, argv, combinedopt,
10142                                         retry_count, timeout);
10143                 break;
10144         case CAM_CMD_SMP_CMD:
10145                 error = smpcmd(cam_dev, argc, argv, combinedopt,
10146                                retry_count, timeout);
10147                 break;
10148         case CAM_CMD_SMP_RG:
10149                 error = smpreportgeneral(cam_dev, argc, argv,
10150                                          combinedopt, retry_count,
10151                                          timeout);
10152                 break;
10153         case CAM_CMD_SMP_PC:
10154                 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
10155                                       retry_count, timeout);
10156                 break;
10157         case CAM_CMD_SMP_PHYLIST:
10158                 error = smpphylist(cam_dev, argc, argv, combinedopt,
10159                                    retry_count, timeout);
10160                 break;
10161         case CAM_CMD_SMP_MANINFO:
10162                 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
10163                                    retry_count, timeout);
10164                 break;
10165         case CAM_CMD_DEBUG:
10166                 error = camdebug(argc, argv, combinedopt);
10167                 break;
10168         case CAM_CMD_TAG:
10169                 error = tagcontrol(cam_dev, argc, argv, combinedopt);
10170                 break;
10171         case CAM_CMD_RATE:
10172                 error = ratecontrol(cam_dev, task_attr, retry_count,
10173                                     timeout, argc, argv, combinedopt);
10174                 break;
10175         case CAM_CMD_FORMAT:
10176                 error = scsiformat(cam_dev, argc, argv,
10177                                    combinedopt, task_attr, retry_count,
10178                                    timeout);
10179                 break;
10180         case CAM_CMD_REPORTLUNS:
10181                 error = scsireportluns(cam_dev, argc, argv,
10182                                        combinedopt, task_attr,
10183                                        retry_count, timeout);
10184                 break;
10185         case CAM_CMD_READCAP:
10186                 error = scsireadcapacity(cam_dev, argc, argv,
10187                                          combinedopt, task_attr,
10188                                          retry_count, timeout);
10189                 break;
10190         case CAM_CMD_IDLE:
10191         case CAM_CMD_STANDBY:
10192         case CAM_CMD_SLEEP:
10193                 error = atapm(cam_dev, argc, argv,
10194                               combinedopt, retry_count, timeout);
10195                 break;
10196         case CAM_CMD_APM:
10197         case CAM_CMD_AAM:
10198                 error = ataaxm(cam_dev, argc, argv,
10199                               combinedopt, retry_count, timeout);
10200                 break;
10201         case CAM_CMD_SECURITY:
10202                 error = atasecurity(cam_dev, retry_count, timeout,
10203                                     argc, argv, combinedopt);
10204                 break;
10205         case CAM_CMD_DOWNLOAD_FW:
10206                 error = fwdownload(cam_dev, argc, argv, combinedopt,
10207                     arglist & CAM_ARG_VERBOSE, task_attr, retry_count,
10208                     timeout);
10209                 break;
10210         case CAM_CMD_SANITIZE:
10211                 error = scsisanitize(cam_dev, argc, argv,
10212                                      combinedopt, task_attr,
10213                                      retry_count, timeout);
10214                 break;
10215         case CAM_CMD_PERSIST:
10216                 error = scsipersist(cam_dev, argc, argv, combinedopt,
10217                     task_attr, retry_count, timeout,
10218                     arglist & CAM_ARG_VERBOSE,
10219                     arglist & CAM_ARG_ERR_RECOVER);
10220                 break;
10221         case CAM_CMD_ATTRIB:
10222                 error = scsiattrib(cam_dev, argc, argv, combinedopt,
10223                     task_attr, retry_count, timeout,
10224                     arglist & CAM_ARG_VERBOSE,
10225                     arglist & CAM_ARG_ERR_RECOVER);
10226                 break;
10227         case CAM_CMD_OPCODES:
10228                 error = scsiopcodes(cam_dev, argc, argv, combinedopt,
10229                     task_attr, retry_count, timeout,
10230                     arglist & CAM_ARG_VERBOSE);
10231                 break;
10232         case CAM_CMD_REPROBE:
10233                 error = scsireprobe(cam_dev);
10234                 break;
10235         case CAM_CMD_ZONE:
10236                 error = zone(cam_dev, argc, argv, combinedopt,
10237                     task_attr, retry_count, timeout,
10238                     arglist & CAM_ARG_VERBOSE);
10239                 break;
10240         case CAM_CMD_EPC:
10241                 error = epc(cam_dev, argc, argv, combinedopt,
10242                     retry_count, timeout, arglist & CAM_ARG_VERBOSE);
10243                 break;
10244         case CAM_CMD_TIMESTAMP:
10245                 error = timestamp(cam_dev, argc, argv, combinedopt,
10246                     task_attr, retry_count, timeout,
10247                     arglist & CAM_ARG_VERBOSE);
10248                 break;
10249 #endif /* MINIMALISTIC */
10250         case CAM_CMD_USAGE:
10251                 usage(1);
10252                 break;
10253         default:
10254                 usage(0);
10255                 error = 1;
10256                 break;
10257         }
10258
10259         if (cam_dev != NULL)
10260                 cam_close_device(cam_dev);
10261
10262         exit(error);
10263 }