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