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