]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/camcontrol/camcontrol.c
Update to bmake-201802222
[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
5171 }
5172
5173 /*
5174  * Get a path inquiry CCB for the specified device.
5175  */
5176 static int
5177 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
5178 {
5179         union ccb *ccb;
5180         int retval = 0;
5181
5182         ccb = cam_getccb(device);
5183         if (ccb == NULL) {
5184                 warnx("get_cpi: couldn't allocate CCB");
5185                 return (1);
5186         }
5187         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
5188         ccb->ccb_h.func_code = XPT_PATH_INQ;
5189         if (cam_send_ccb(device, ccb) < 0) {
5190                 warn("get_cpi: error sending Path Inquiry CCB");
5191                 if (arglist & CAM_ARG_VERBOSE)
5192                         cam_error_print(device, ccb, CAM_ESF_ALL,
5193                                         CAM_EPF_ALL, stderr);
5194                 retval = 1;
5195                 goto get_cpi_bailout;
5196         }
5197         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5198                 if (arglist & CAM_ARG_VERBOSE)
5199                         cam_error_print(device, ccb, CAM_ESF_ALL,
5200                                         CAM_EPF_ALL, stderr);
5201                 retval = 1;
5202                 goto get_cpi_bailout;
5203         }
5204         bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
5205
5206 get_cpi_bailout:
5207         cam_freeccb(ccb);
5208         return (retval);
5209 }
5210
5211 /*
5212  * Get a get device CCB for the specified device.
5213  */
5214 static int
5215 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
5216 {
5217         union ccb *ccb;
5218         int retval = 0;
5219
5220         ccb = cam_getccb(device);
5221         if (ccb == NULL) {
5222                 warnx("get_cgd: couldn't allocate CCB");
5223                 return (1);
5224         }
5225         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgd);
5226         ccb->ccb_h.func_code = XPT_GDEV_TYPE;
5227         if (cam_send_ccb(device, ccb) < 0) {
5228                 warn("get_cgd: error sending Path Inquiry CCB");
5229                 if (arglist & CAM_ARG_VERBOSE)
5230                         cam_error_print(device, ccb, CAM_ESF_ALL,
5231                                         CAM_EPF_ALL, stderr);
5232                 retval = 1;
5233                 goto get_cgd_bailout;
5234         }
5235         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5236                 if (arglist & CAM_ARG_VERBOSE)
5237                         cam_error_print(device, ccb, CAM_ESF_ALL,
5238                                         CAM_EPF_ALL, stderr);
5239                 retval = 1;
5240                 goto get_cgd_bailout;
5241         }
5242         bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
5243
5244 get_cgd_bailout:
5245         cam_freeccb(ccb);
5246         return (retval);
5247 }
5248
5249 /*
5250  * Returns 1 if the device has the VPD page, 0 if it does not, and -1 on an
5251  * error.
5252  */
5253 int
5254 dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count,
5255                  int timeout, int verbosemode)
5256 {
5257         union ccb *ccb = NULL;
5258         struct scsi_vpd_supported_page_list sup_pages;
5259         int i;
5260         int retval = 0;
5261
5262         ccb = cam_getccb(dev);
5263         if (ccb == NULL) {
5264                 warn("Unable to allocate CCB");
5265                 retval = -1;
5266                 goto bailout;
5267         }
5268
5269         /* cam_getccb cleans up the header, caller has to zero the payload */
5270         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5271
5272         bzero(&sup_pages, sizeof(sup_pages));
5273
5274         scsi_inquiry(&ccb->csio,
5275                      /*retries*/ retry_count,
5276                      /*cbfcnp*/ NULL,
5277                      /* tag_action */ MSG_SIMPLE_Q_TAG,
5278                      /* inq_buf */ (u_int8_t *)&sup_pages,
5279                      /* inq_len */ sizeof(sup_pages),
5280                      /* evpd */ 1,
5281                      /* page_code */ SVPD_SUPPORTED_PAGE_LIST,
5282                      /* sense_len */ SSD_FULL_SIZE,
5283                      /* timeout */ timeout ? timeout : 5000);
5284
5285         /* Disable freezing the device queue */
5286         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5287
5288         if (retry_count != 0)
5289                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5290
5291         if (cam_send_ccb(dev, ccb) < 0) {
5292                 cam_freeccb(ccb);
5293                 ccb = NULL;
5294                 retval = -1;
5295                 goto bailout;
5296         }
5297
5298         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5299                 if (verbosemode != 0)
5300                         cam_error_print(dev, ccb, CAM_ESF_ALL,
5301                                         CAM_EPF_ALL, stderr);
5302                 retval = -1;
5303                 goto bailout;
5304         }
5305
5306         for (i = 0; i < sup_pages.length; i++) {
5307                 if (sup_pages.list[i] == page_id) {
5308                         retval = 1;
5309                         goto bailout;
5310                 }
5311         }
5312 bailout:
5313         if (ccb != NULL)
5314                 cam_freeccb(ccb);
5315
5316         return (retval);
5317 }
5318
5319 /*
5320  * devtype is filled in with the type of device.
5321  * Returns 0 for success, non-zero for failure.
5322  */
5323 int
5324 get_device_type(struct cam_device *dev, int retry_count, int timeout,
5325                     int verbosemode, camcontrol_devtype *devtype)
5326 {
5327         struct ccb_getdev cgd;
5328         int retval = 0;
5329
5330         retval = get_cgd(dev, &cgd);
5331         if (retval != 0)
5332                 goto bailout;
5333
5334         switch (cgd.protocol) {
5335         case PROTO_SCSI:
5336                 break;
5337         case PROTO_ATA:
5338         case PROTO_ATAPI:
5339         case PROTO_SATAPM:
5340                 *devtype = CC_DT_ATA;
5341                 goto bailout;
5342                 break; /*NOTREACHED*/
5343         default:
5344                 *devtype = CC_DT_UNKNOWN;
5345                 goto bailout;
5346                 break; /*NOTREACHED*/
5347         }
5348
5349         /*
5350          * Check for the ATA Information VPD page (0x89).  If this is an
5351          * ATA device behind a SCSI to ATA translation layer, this VPD page
5352          * should be present.
5353          *
5354          * If that VPD page isn't present, or we get an error back from the
5355          * INQUIRY command, we'll just treat it as a normal SCSI device.
5356          */
5357         retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5358                                   timeout, verbosemode);
5359         if (retval == 1)
5360                 *devtype = CC_DT_ATA_BEHIND_SCSI;
5361         else
5362                 *devtype = CC_DT_SCSI;
5363
5364         retval = 0;
5365
5366 bailout:
5367         return (retval);
5368 }
5369
5370 int
5371 build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5372     uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5373     uint16_t sector_count, uint64_t lba, uint8_t command, uint32_t auxiliary,
5374     uint8_t *data_ptr, uint32_t dxfer_len, uint8_t *cdb_storage,
5375     size_t cdb_storage_len, uint8_t sense_len, uint32_t timeout,
5376     int is48bit, camcontrol_devtype devtype)
5377 {
5378         int retval = 0;
5379
5380         if (devtype == CC_DT_ATA) {
5381                 cam_fill_ataio(&ccb->ataio,
5382                     /*retries*/ retry_count,
5383                     /*cbfcnp*/ NULL,
5384                     /*flags*/ flags,
5385                     /*tag_action*/ tag_action,
5386                     /*data_ptr*/ data_ptr,
5387                     /*dxfer_len*/ dxfer_len,
5388                     /*timeout*/ timeout);
5389                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5390                         ata_48bit_cmd(&ccb->ataio, command, features, lba,
5391                             sector_count);
5392                 else
5393                         ata_28bit_cmd(&ccb->ataio, command, features, lba,
5394                             sector_count);
5395
5396                 if (auxiliary != 0) {
5397                         ccb->ataio.ata_flags |= ATA_FLAG_AUX;
5398                         ccb->ataio.aux = auxiliary;
5399                 }
5400
5401                 if (ata_flags & AP_FLAG_CHK_COND)
5402                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
5403
5404                 if ((protocol & AP_PROTO_MASK) == AP_PROTO_DMA)
5405                         ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
5406                 else if ((protocol & AP_PROTO_MASK) == AP_PROTO_FPDMA)
5407                         ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
5408         } else {
5409                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5410                         protocol |= AP_EXTEND;
5411
5412                 retval = scsi_ata_pass(&ccb->csio,
5413                     /*retries*/ retry_count,
5414                     /*cbfcnp*/ NULL,
5415                     /*flags*/ flags,
5416                     /*tag_action*/ tag_action,
5417                     /*protocol*/ protocol,
5418                     /*ata_flags*/ ata_flags,
5419                     /*features*/ features,
5420                     /*sector_count*/ sector_count,
5421                     /*lba*/ lba,
5422                     /*command*/ command,
5423                     /*device*/ 0,
5424                     /*icc*/ 0,
5425                     /*auxiliary*/ auxiliary,
5426                     /*control*/ 0,
5427                     /*data_ptr*/ data_ptr,
5428                     /*dxfer_len*/ dxfer_len,
5429                     /*cdb_storage*/ cdb_storage,
5430                     /*cdb_storage_len*/ cdb_storage_len,
5431                     /*minimum_cmd_size*/ 0,
5432                     /*sense_len*/ sense_len,
5433                     /*timeout*/ timeout);
5434         }
5435
5436         return (retval);
5437 }
5438
5439 int
5440 get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
5441                uint16_t *count, uint64_t *lba, uint8_t *device, uint8_t *status)
5442 {
5443         int retval = 0;
5444
5445         switch (ccb->ccb_h.func_code) {
5446         case XPT_SCSI_IO: {
5447                 uint8_t opcode;
5448                 int error_code = 0, sense_key = 0, asc = 0, ascq = 0;
5449
5450                 /*
5451                  * In this case, we have SCSI ATA PASS-THROUGH command, 12
5452                  * or 16 byte, and need to see what
5453                  */
5454                 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
5455                         opcode = ccb->csio.cdb_io.cdb_ptr[0];
5456                 else
5457                         opcode = ccb->csio.cdb_io.cdb_bytes[0];
5458                 if ((opcode != ATA_PASS_12)
5459                  && (opcode != ATA_PASS_16)) {
5460                         retval = 1;
5461                         warnx("%s: unsupported opcode %02x", __func__, opcode);
5462                         goto bailout;
5463                 }
5464
5465                 retval = scsi_extract_sense_ccb(ccb, &error_code, &sense_key,
5466                                                 &asc, &ascq);
5467                 /* Note: the _ccb() variant returns 0 for an error */
5468                 if (retval == 0) {
5469                         retval = 1;
5470                         goto bailout;
5471                 } else
5472                         retval = 0;
5473
5474                 switch (error_code) {
5475                 case SSD_DESC_CURRENT_ERROR:
5476                 case SSD_DESC_DEFERRED_ERROR: {
5477                         struct scsi_sense_data_desc *sense;
5478                         struct scsi_sense_ata_ret_desc *desc;
5479                         uint8_t *desc_ptr;
5480
5481                         sense = (struct scsi_sense_data_desc *)
5482                             &ccb->csio.sense_data;
5483
5484                         desc_ptr = scsi_find_desc(sense, ccb->csio.sense_len -
5485                             ccb->csio.sense_resid, SSD_DESC_ATA);
5486                         if (desc_ptr == NULL) {
5487                                 cam_error_print(dev, ccb, CAM_ESF_ALL,
5488                                     CAM_EPF_ALL, stderr);
5489                                 retval = 1;
5490                                 goto bailout;
5491                         }
5492                         desc = (struct scsi_sense_ata_ret_desc *)desc_ptr;
5493
5494                         *error = desc->error;
5495                         *count = (desc->count_15_8 << 8) |
5496                                   desc->count_7_0;
5497                         *lba = ((uint64_t)desc->lba_47_40 << 40) |
5498                                ((uint64_t)desc->lba_39_32 << 32) |
5499                                ((uint64_t)desc->lba_31_24 << 24) |
5500                                (desc->lba_23_16 << 16) |
5501                                (desc->lba_15_8  <<  8) |
5502                                 desc->lba_7_0;
5503                         *device = desc->device;
5504                         *status = desc->status;
5505
5506                         /*
5507                          * If the extend bit isn't set, the result is for a
5508                          * 12-byte ATA PASS-THROUGH command or a 16 or 32 byte
5509                          * command without the extend bit set.  This means
5510                          * that the device is supposed to return 28-bit
5511                          * status.  The count field is only 8 bits, and the
5512                          * LBA field is only 8 bits.
5513                          */
5514                         if ((desc->flags & SSD_DESC_ATA_FLAG_EXTEND) == 0){
5515                                 *count &= 0xff;
5516                                 *lba &= 0x0fffffff;
5517                         }
5518                         break;
5519                 }
5520                 case SSD_CURRENT_ERROR:
5521                 case SSD_DEFERRED_ERROR: {
5522 #if 0
5523                         struct scsi_sense_data_fixed *sense;
5524 #endif
5525                         /*
5526                          * XXX KDM need to support fixed sense data.
5527                          */
5528                         warnx("%s: Fixed sense data not supported yet",
5529                             __func__);
5530                         retval = 1;
5531                         goto bailout;
5532                         break; /*NOTREACHED*/
5533                 }
5534                 default:
5535                         retval = 1;
5536                         goto bailout;
5537                         break;
5538                 }
5539
5540                 break;
5541         }
5542         case XPT_ATA_IO: {
5543                 struct ata_res *res;
5544
5545                 /*
5546                  * In this case, we have an ATA command, and we need to
5547                  * fill in the requested values from the result register
5548                  * set.
5549                  */
5550                 res = &ccb->ataio.res;
5551                 *error = res->error;
5552                 *status = res->status;
5553                 *device = res->device;
5554                 *count = res->sector_count;
5555                 *lba = (res->lba_high << 16) |
5556                        (res->lba_mid << 8) |
5557                        (res->lba_low);
5558                 if (res->flags & CAM_ATAIO_48BIT) {
5559                         *count |= (res->sector_count_exp << 8);
5560                         *lba |= ((uint64_t)res->lba_low_exp << 24) |
5561                                 ((uint64_t)res->lba_mid_exp << 32) |
5562                                 ((uint64_t)res->lba_high_exp << 40);
5563                 } else {
5564                         *lba |= (res->device & 0xf) << 24;
5565                 }
5566                 break;
5567         }
5568         default:
5569                 retval = 1;
5570                 break;
5571         }
5572 bailout:
5573         return (retval);
5574 }
5575
5576 static void
5577 cpi_print(struct ccb_pathinq *cpi)
5578 {
5579         char adapter_str[1024];
5580         uint64_t i;
5581
5582         snprintf(adapter_str, sizeof(adapter_str),
5583                  "%s%d:", cpi->dev_name, cpi->unit_number);
5584
5585         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5586                 cpi->version_num);
5587
5588         for (i = 1; i < UINT8_MAX; i = i << 1) {
5589                 const char *str;
5590
5591                 if ((i & cpi->hba_inquiry) == 0)
5592                         continue;
5593
5594                 fprintf(stdout, "%s supports ", adapter_str);
5595
5596                 switch(i) {
5597                 case PI_MDP_ABLE:
5598                         str = "MDP message";
5599                         break;
5600                 case PI_WIDE_32:
5601                         str = "32 bit wide SCSI";
5602                         break;
5603                 case PI_WIDE_16:
5604                         str = "16 bit wide SCSI";
5605                         break;
5606                 case PI_SDTR_ABLE:
5607                         str = "SDTR message";
5608                         break;
5609                 case PI_LINKED_CDB:
5610                         str = "linked CDBs";
5611                         break;
5612                 case PI_TAG_ABLE:
5613                         str = "tag queue messages";
5614                         break;
5615                 case PI_SOFT_RST:
5616                         str = "soft reset alternative";
5617                         break;
5618                 case PI_SATAPM:
5619                         str = "SATA Port Multiplier";
5620                         break;
5621                 default:
5622                         str = "unknown PI bit set";
5623                         break;
5624                 }
5625                 fprintf(stdout, "%s\n", str);
5626         }
5627
5628         for (i = 1; i < UINT32_MAX; i = i << 1) {
5629                 const char *str;
5630
5631                 if ((i & cpi->hba_misc) == 0)
5632                         continue;
5633
5634                 fprintf(stdout, "%s ", adapter_str);
5635
5636                 switch(i) {
5637                 case PIM_ATA_EXT:
5638                         str = "can understand ata_ext requests";
5639                         break;
5640                 case PIM_EXTLUNS:
5641                         str = "64bit extended LUNs supported";
5642                         break;
5643                 case PIM_SCANHILO:
5644                         str = "bus scans from high ID to low ID";
5645                         break;
5646                 case PIM_NOREMOVE:
5647                         str = "removable devices not included in scan";
5648                         break;
5649                 case PIM_NOINITIATOR:
5650                         str = "initiator role not supported";
5651                         break;
5652                 case PIM_NOBUSRESET:
5653                         str = "user has disabled initial BUS RESET or"
5654                               " controller is in target/mixed mode";
5655                         break;
5656                 case PIM_NO_6_BYTE:
5657                         str = "do not send 6-byte commands";
5658                         break;
5659                 case PIM_SEQSCAN:
5660                         str = "scan bus sequentially";
5661                         break;
5662                 case PIM_UNMAPPED:
5663                         str = "unmapped I/O supported";
5664                         break;
5665                 case PIM_NOSCAN:
5666                         str = "does its own scanning";
5667                         break;
5668                 default:
5669                         str = "unknown PIM bit set";
5670                         break;
5671                 }
5672                 fprintf(stdout, "%s\n", str);
5673         }
5674
5675         for (i = 1; i < UINT16_MAX; i = i << 1) {
5676                 const char *str;
5677
5678                 if ((i & cpi->target_sprt) == 0)
5679                         continue;
5680
5681                 fprintf(stdout, "%s supports ", adapter_str);
5682                 switch(i) {
5683                 case PIT_PROCESSOR:
5684                         str = "target mode processor mode";
5685                         break;
5686                 case PIT_PHASE:
5687                         str = "target mode phase cog. mode";
5688                         break;
5689                 case PIT_DISCONNECT:
5690                         str = "disconnects in target mode";
5691                         break;
5692                 case PIT_TERM_IO:
5693                         str = "terminate I/O message in target mode";
5694                         break;
5695                 case PIT_GRP_6:
5696                         str = "group 6 commands in target mode";
5697                         break;
5698                 case PIT_GRP_7:
5699                         str = "group 7 commands in target mode";
5700                         break;
5701                 default:
5702                         str = "unknown PIT bit set";
5703                         break;
5704                 }
5705
5706                 fprintf(stdout, "%s\n", str);
5707         }
5708         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5709                 cpi->hba_eng_cnt);
5710         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5711                 cpi->max_target);
5712         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5713                 cpi->max_lun);
5714         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5715                 adapter_str, cpi->hpath_id);
5716         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5717                 cpi->initiator_id);
5718         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5719         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5720         fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5721             adapter_str, cpi->hba_vendor);
5722         fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5723             adapter_str, cpi->hba_device);
5724         fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5725             adapter_str, cpi->hba_subvendor);
5726         fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5727             adapter_str, cpi->hba_subdevice);
5728         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5729         fprintf(stdout, "%s base transfer speed: ", adapter_str);
5730         if (cpi->base_transfer_speed > 1000)
5731                 fprintf(stdout, "%d.%03dMB/sec\n",
5732                         cpi->base_transfer_speed / 1000,
5733                         cpi->base_transfer_speed % 1000);
5734         else
5735                 fprintf(stdout, "%dKB/sec\n",
5736                         (cpi->base_transfer_speed % 1000) * 1000);
5737         fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5738             adapter_str, cpi->maxio);
5739 }
5740
5741 static int
5742 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5743               struct ccb_trans_settings *cts)
5744 {
5745         int retval;
5746         union ccb *ccb;
5747
5748         retval = 0;
5749         ccb = cam_getccb(device);
5750
5751         if (ccb == NULL) {
5752                 warnx("get_print_cts: error allocating ccb");
5753                 return (1);
5754         }
5755
5756         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5757
5758         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5759
5760         if (user_settings == 0)
5761                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5762         else
5763                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5764
5765         if (cam_send_ccb(device, ccb) < 0) {
5766                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5767                 if (arglist & CAM_ARG_VERBOSE)
5768                         cam_error_print(device, ccb, CAM_ESF_ALL,
5769                                         CAM_EPF_ALL, stderr);
5770                 retval = 1;
5771                 goto get_print_cts_bailout;
5772         }
5773
5774         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5775                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5776                 if (arglist & CAM_ARG_VERBOSE)
5777                         cam_error_print(device, ccb, CAM_ESF_ALL,
5778                                         CAM_EPF_ALL, stderr);
5779                 retval = 1;
5780                 goto get_print_cts_bailout;
5781         }
5782
5783         if (quiet == 0)
5784                 cts_print(device, &ccb->cts);
5785
5786         if (cts != NULL)
5787                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5788
5789 get_print_cts_bailout:
5790
5791         cam_freeccb(ccb);
5792
5793         return (retval);
5794 }
5795
5796 static int
5797 ratecontrol(struct cam_device *device, int task_attr, int retry_count,
5798             int timeout, int argc, char **argv, char *combinedopt)
5799 {
5800         int c;
5801         union ccb *ccb;
5802         int user_settings = 0;
5803         int retval = 0;
5804         int disc_enable = -1, tag_enable = -1;
5805         int mode = -1;
5806         int offset = -1;
5807         double syncrate = -1;
5808         int bus_width = -1;
5809         int quiet = 0;
5810         int change_settings = 0, send_tur = 0;
5811         struct ccb_pathinq cpi;
5812
5813         ccb = cam_getccb(device);
5814         if (ccb == NULL) {
5815                 warnx("ratecontrol: error allocating ccb");
5816                 return (1);
5817         }
5818         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5819                 switch(c){
5820                 case 'a':
5821                         send_tur = 1;
5822                         break;
5823                 case 'c':
5824                         user_settings = 0;
5825                         break;
5826                 case 'D':
5827                         if (strncasecmp(optarg, "enable", 6) == 0)
5828                                 disc_enable = 1;
5829                         else if (strncasecmp(optarg, "disable", 7) == 0)
5830                                 disc_enable = 0;
5831                         else {
5832                                 warnx("-D argument \"%s\" is unknown", optarg);
5833                                 retval = 1;
5834                                 goto ratecontrol_bailout;
5835                         }
5836                         change_settings = 1;
5837                         break;
5838                 case 'M':
5839                         mode = ata_string2mode(optarg);
5840                         if (mode < 0) {
5841                                 warnx("unknown mode '%s'", optarg);
5842                                 retval = 1;
5843                                 goto ratecontrol_bailout;
5844                         }
5845                         change_settings = 1;
5846                         break;
5847                 case 'O':
5848                         offset = strtol(optarg, NULL, 0);
5849                         if (offset < 0) {
5850                                 warnx("offset value %d is < 0", offset);
5851                                 retval = 1;
5852                                 goto ratecontrol_bailout;
5853                         }
5854                         change_settings = 1;
5855                         break;
5856                 case 'q':
5857                         quiet++;
5858                         break;
5859                 case 'R':
5860                         syncrate = atof(optarg);
5861                         if (syncrate < 0) {
5862                                 warnx("sync rate %f is < 0", syncrate);
5863                                 retval = 1;
5864                                 goto ratecontrol_bailout;
5865                         }
5866                         change_settings = 1;
5867                         break;
5868                 case 'T':
5869                         if (strncasecmp(optarg, "enable", 6) == 0)
5870                                 tag_enable = 1;
5871                         else if (strncasecmp(optarg, "disable", 7) == 0)
5872                                 tag_enable = 0;
5873                         else {
5874                                 warnx("-T argument \"%s\" is unknown", optarg);
5875                                 retval = 1;
5876                                 goto ratecontrol_bailout;
5877                         }
5878                         change_settings = 1;
5879                         break;
5880                 case 'U':
5881                         user_settings = 1;
5882                         break;
5883                 case 'W':
5884                         bus_width = strtol(optarg, NULL, 0);
5885                         if (bus_width < 0) {
5886                                 warnx("bus width %d is < 0", bus_width);
5887                                 retval = 1;
5888                                 goto ratecontrol_bailout;
5889                         }
5890                         change_settings = 1;
5891                         break;
5892                 default:
5893                         break;
5894                 }
5895         }
5896         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
5897         /*
5898          * Grab path inquiry information, so we can determine whether
5899          * or not the initiator is capable of the things that the user
5900          * requests.
5901          */
5902         ccb->ccb_h.func_code = XPT_PATH_INQ;
5903         if (cam_send_ccb(device, ccb) < 0) {
5904                 perror("error sending XPT_PATH_INQ CCB");
5905                 if (arglist & CAM_ARG_VERBOSE) {
5906                         cam_error_print(device, ccb, CAM_ESF_ALL,
5907                                         CAM_EPF_ALL, stderr);
5908                 }
5909                 retval = 1;
5910                 goto ratecontrol_bailout;
5911         }
5912         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5913                 warnx("XPT_PATH_INQ CCB failed");
5914                 if (arglist & CAM_ARG_VERBOSE) {
5915                         cam_error_print(device, ccb, CAM_ESF_ALL,
5916                                         CAM_EPF_ALL, stderr);
5917                 }
5918                 retval = 1;
5919                 goto ratecontrol_bailout;
5920         }
5921         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5922         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5923         if (quiet == 0) {
5924                 fprintf(stdout, "%s parameters:\n",
5925                     user_settings ? "User" : "Current");
5926         }
5927         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5928         if (retval != 0)
5929                 goto ratecontrol_bailout;
5930
5931         if (arglist & CAM_ARG_VERBOSE)
5932                 cpi_print(&cpi);
5933
5934         if (change_settings) {
5935                 int didsettings = 0;
5936                 struct ccb_trans_settings_spi *spi = NULL;
5937                 struct ccb_trans_settings_pata *pata = NULL;
5938                 struct ccb_trans_settings_sata *sata = NULL;
5939                 struct ccb_trans_settings_ata *ata = NULL;
5940                 struct ccb_trans_settings_scsi *scsi = NULL;
5941
5942                 if (ccb->cts.transport == XPORT_SPI)
5943                         spi = &ccb->cts.xport_specific.spi;
5944                 if (ccb->cts.transport == XPORT_ATA)
5945                         pata = &ccb->cts.xport_specific.ata;
5946                 if (ccb->cts.transport == XPORT_SATA)
5947                         sata = &ccb->cts.xport_specific.sata;
5948                 if (ccb->cts.protocol == PROTO_ATA)
5949                         ata = &ccb->cts.proto_specific.ata;
5950                 if (ccb->cts.protocol == PROTO_SCSI)
5951                         scsi = &ccb->cts.proto_specific.scsi;
5952                 ccb->cts.xport_specific.valid = 0;
5953                 ccb->cts.proto_specific.valid = 0;
5954                 if (spi && disc_enable != -1) {
5955                         spi->valid |= CTS_SPI_VALID_DISC;
5956                         if (disc_enable == 0)
5957                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5958                         else
5959                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5960                         didsettings++;
5961                 }
5962                 if (tag_enable != -1) {
5963                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5964                                 warnx("HBA does not support tagged queueing, "
5965                                       "so you cannot modify tag settings");
5966                                 retval = 1;
5967                                 goto ratecontrol_bailout;
5968                         }
5969                         if (ata) {
5970                                 ata->valid |= CTS_SCSI_VALID_TQ;
5971                                 if (tag_enable == 0)
5972                                         ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5973                                 else
5974                                         ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5975                                 didsettings++;
5976                         } else if (scsi) {
5977                                 scsi->valid |= CTS_SCSI_VALID_TQ;
5978                                 if (tag_enable == 0)
5979                                         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5980                                 else
5981                                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5982                                 didsettings++;
5983                         }
5984                 }
5985                 if (spi && offset != -1) {
5986                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5987                                 warnx("HBA is not capable of changing offset");
5988                                 retval = 1;
5989                                 goto ratecontrol_bailout;
5990                         }
5991                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5992                         spi->sync_offset = offset;
5993                         didsettings++;
5994                 }
5995                 if (spi && syncrate != -1) {
5996                         int prelim_sync_period;
5997
5998                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5999                                 warnx("HBA is not capable of changing "
6000                                       "transfer rates");
6001                                 retval = 1;
6002                                 goto ratecontrol_bailout;
6003                         }
6004                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
6005                         /*
6006                          * The sync rate the user gives us is in MHz.
6007                          * We need to translate it into KHz for this
6008                          * calculation.
6009                          */
6010                         syncrate *= 1000;
6011                         /*
6012                          * Next, we calculate a "preliminary" sync period
6013                          * in tenths of a nanosecond.
6014                          */
6015                         if (syncrate == 0)
6016                                 prelim_sync_period = 0;
6017                         else
6018                                 prelim_sync_period = 10000000 / syncrate;
6019                         spi->sync_period =
6020                                 scsi_calc_syncparam(prelim_sync_period);
6021                         didsettings++;
6022                 }
6023                 if (sata && syncrate != -1) {
6024                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
6025                                 warnx("HBA is not capable of changing "
6026                                       "transfer rates");
6027                                 retval = 1;
6028                                 goto ratecontrol_bailout;
6029                         }
6030                         if  (!user_settings) {
6031                                 warnx("You can modify only user rate "
6032                                     "settings for SATA");
6033                                 retval = 1;
6034                                 goto ratecontrol_bailout;
6035                         }
6036                         sata->revision = ata_speed2revision(syncrate * 100);
6037                         if (sata->revision < 0) {
6038                                 warnx("Invalid rate %f", syncrate);
6039                                 retval = 1;
6040                                 goto ratecontrol_bailout;
6041                         }
6042                         sata->valid |= CTS_SATA_VALID_REVISION;
6043                         didsettings++;
6044                 }
6045                 if ((pata || sata) && mode != -1) {
6046                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
6047                                 warnx("HBA is not capable of changing "
6048                                       "transfer rates");
6049                                 retval = 1;
6050                                 goto ratecontrol_bailout;
6051                         }
6052                         if  (!user_settings) {
6053                                 warnx("You can modify only user mode "
6054                                     "settings for ATA/SATA");
6055                                 retval = 1;
6056                                 goto ratecontrol_bailout;
6057                         }
6058                         if (pata) {
6059                                 pata->mode = mode;
6060                                 pata->valid |= CTS_ATA_VALID_MODE;
6061                         } else {
6062                                 sata->mode = mode;
6063                                 sata->valid |= CTS_SATA_VALID_MODE;
6064                         }
6065                         didsettings++;
6066                 }
6067                 /*
6068                  * The bus_width argument goes like this:
6069                  * 0 == 8 bit
6070                  * 1 == 16 bit
6071                  * 2 == 32 bit
6072                  * Therefore, if you shift the number of bits given on the
6073                  * command line right by 4, you should get the correct
6074                  * number.
6075                  */
6076                 if (spi && bus_width != -1) {
6077                         /*
6078                          * We might as well validate things here with a
6079                          * decipherable error message, rather than what
6080                          * will probably be an indecipherable error message
6081                          * by the time it gets back to us.
6082                          */
6083                         if ((bus_width == 16)
6084                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
6085                                 warnx("HBA does not support 16 bit bus width");
6086                                 retval = 1;
6087                                 goto ratecontrol_bailout;
6088                         } else if ((bus_width == 32)
6089                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
6090                                 warnx("HBA does not support 32 bit bus width");
6091                                 retval = 1;
6092                                 goto ratecontrol_bailout;
6093                         } else if ((bus_width != 8)
6094                                 && (bus_width != 16)
6095                                 && (bus_width != 32)) {
6096                                 warnx("Invalid bus width %d", bus_width);
6097                                 retval = 1;
6098                                 goto ratecontrol_bailout;
6099                         }
6100                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
6101                         spi->bus_width = bus_width >> 4;
6102                         didsettings++;
6103                 }
6104                 if  (didsettings == 0) {
6105                         goto ratecontrol_bailout;
6106                 }
6107                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
6108                 if (cam_send_ccb(device, ccb) < 0) {
6109                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
6110                         if (arglist & CAM_ARG_VERBOSE) {
6111                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6112                                                 CAM_EPF_ALL, stderr);
6113                         }
6114                         retval = 1;
6115                         goto ratecontrol_bailout;
6116                 }
6117                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6118                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
6119                         if (arglist & CAM_ARG_VERBOSE) {
6120                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6121                                                 CAM_EPF_ALL, stderr);
6122                         }
6123                         retval = 1;
6124                         goto ratecontrol_bailout;
6125                 }
6126         }
6127         if (send_tur) {
6128                 retval = testunitready(device, task_attr, retry_count, timeout,
6129                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
6130                 /*
6131                  * If the TUR didn't succeed, just bail.
6132                  */
6133                 if (retval != 0) {
6134                         if (quiet == 0)
6135                                 fprintf(stderr, "Test Unit Ready failed\n");
6136                         goto ratecontrol_bailout;
6137                 }
6138         }
6139         if ((change_settings || send_tur) && !quiet &&
6140             (ccb->cts.transport == XPORT_ATA ||
6141              ccb->cts.transport == XPORT_SATA || send_tur)) {
6142                 fprintf(stdout, "New parameters:\n");
6143                 retval = get_print_cts(device, user_settings, 0, NULL);
6144         }
6145
6146 ratecontrol_bailout:
6147         cam_freeccb(ccb);
6148         return (retval);
6149 }
6150
6151 static int
6152 scsiformat(struct cam_device *device, int argc, char **argv,
6153            char *combinedopt, int task_attr, int retry_count, int timeout)
6154 {
6155         union ccb *ccb;
6156         int c;
6157         int ycount = 0, quiet = 0;
6158         int error = 0, retval = 0;
6159         int use_timeout = 10800 * 1000;
6160         int immediate = 1;
6161         struct format_defect_list_header fh;
6162         u_int8_t *data_ptr = NULL;
6163         u_int32_t dxfer_len = 0;
6164         u_int8_t byte2 = 0;
6165         int num_warnings = 0;
6166         int reportonly = 0;
6167
6168         ccb = cam_getccb(device);
6169
6170         if (ccb == NULL) {
6171                 warnx("scsiformat: error allocating ccb");
6172                 return (1);
6173         }
6174
6175         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6176
6177         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6178                 switch(c) {
6179                 case 'q':
6180                         quiet++;
6181                         break;
6182                 case 'r':
6183                         reportonly = 1;
6184                         break;
6185                 case 'w':
6186                         immediate = 0;
6187                         break;
6188                 case 'y':
6189                         ycount++;
6190                         break;
6191                 }
6192         }
6193
6194         if (reportonly)
6195                 goto doreport;
6196
6197         if (quiet == 0) {
6198                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6199                         "following device:\n");
6200
6201                 error = scsidoinquiry(device, argc, argv, combinedopt,
6202                                       task_attr, retry_count, timeout);
6203
6204                 if (error != 0) {
6205                         warnx("scsiformat: error sending inquiry");
6206                         goto scsiformat_bailout;
6207                 }
6208         }
6209
6210         if (ycount == 0) {
6211                 if (!get_confirmation()) {
6212                         error = 1;
6213                         goto scsiformat_bailout;
6214                 }
6215         }
6216
6217         if (timeout != 0)
6218                 use_timeout = timeout;
6219
6220         if (quiet == 0) {
6221                 fprintf(stdout, "Current format timeout is %d seconds\n",
6222                         use_timeout / 1000);
6223         }
6224
6225         /*
6226          * If the user hasn't disabled questions and didn't specify a
6227          * timeout on the command line, ask them if they want the current
6228          * timeout.
6229          */
6230         if ((ycount == 0)
6231          && (timeout == 0)) {
6232                 char str[1024];
6233                 int new_timeout = 0;
6234
6235                 fprintf(stdout, "Enter new timeout in seconds or press\n"
6236                         "return to keep the current timeout [%d] ",
6237                         use_timeout / 1000);
6238
6239                 if (fgets(str, sizeof(str), stdin) != NULL) {
6240                         if (str[0] != '\0')
6241                                 new_timeout = atoi(str);
6242                 }
6243
6244                 if (new_timeout != 0) {
6245                         use_timeout = new_timeout * 1000;
6246                         fprintf(stdout, "Using new timeout value %d\n",
6247                                 use_timeout / 1000);
6248                 }
6249         }
6250
6251         /*
6252          * Keep this outside the if block below to silence any unused
6253          * variable warnings.
6254          */
6255         bzero(&fh, sizeof(fh));
6256
6257         /*
6258          * If we're in immediate mode, we've got to include the format
6259          * header
6260          */
6261         if (immediate != 0) {
6262                 fh.byte2 = FU_DLH_IMMED;
6263                 data_ptr = (u_int8_t *)&fh;
6264                 dxfer_len = sizeof(fh);
6265                 byte2 = FU_FMT_DATA;
6266         } else if (quiet == 0) {
6267                 fprintf(stdout, "Formatting...");
6268                 fflush(stdout);
6269         }
6270
6271         scsi_format_unit(&ccb->csio,
6272                          /* retries */ retry_count,
6273                          /* cbfcnp */ NULL,
6274                          /* tag_action */ task_attr,
6275                          /* byte2 */ byte2,
6276                          /* ileave */ 0,
6277                          /* data_ptr */ data_ptr,
6278                          /* dxfer_len */ dxfer_len,
6279                          /* sense_len */ SSD_FULL_SIZE,
6280                          /* timeout */ use_timeout);
6281
6282         /* Disable freezing the device queue */
6283         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6284
6285         if (arglist & CAM_ARG_ERR_RECOVER)
6286                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6287
6288         if (((retval = cam_send_ccb(device, ccb)) < 0)
6289          || ((immediate == 0)
6290            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
6291                 const char errstr[] = "error sending format command";
6292
6293                 if (retval < 0)
6294                         warn(errstr);
6295                 else
6296                         warnx(errstr);
6297
6298                 if (arglist & CAM_ARG_VERBOSE) {
6299                         cam_error_print(device, ccb, CAM_ESF_ALL,
6300                                         CAM_EPF_ALL, stderr);
6301                 }
6302                 error = 1;
6303                 goto scsiformat_bailout;
6304         }
6305
6306         /*
6307          * If we ran in non-immediate mode, we already checked for errors
6308          * above and printed out any necessary information.  If we're in
6309          * immediate mode, we need to loop through and get status
6310          * information periodically.
6311          */
6312         if (immediate == 0) {
6313                 if (quiet == 0) {
6314                         fprintf(stdout, "Format Complete\n");
6315                 }
6316                 goto scsiformat_bailout;
6317         }
6318
6319 doreport:
6320         do {
6321                 cam_status status;
6322
6323                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6324
6325                 /*
6326                  * There's really no need to do error recovery or
6327                  * retries here, since we're just going to sit in a
6328                  * loop and wait for the device to finish formatting.
6329                  */
6330                 scsi_test_unit_ready(&ccb->csio,
6331                                      /* retries */ 0,
6332                                      /* cbfcnp */ NULL,
6333                                      /* tag_action */ task_attr,
6334                                      /* sense_len */ SSD_FULL_SIZE,
6335                                      /* timeout */ 5000);
6336
6337                 /* Disable freezing the device queue */
6338                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6339
6340                 retval = cam_send_ccb(device, ccb);
6341
6342                 /*
6343                  * If we get an error from the ioctl, bail out.  SCSI
6344                  * errors are expected.
6345                  */
6346                 if (retval < 0) {
6347                         warn("error sending CAMIOCOMMAND ioctl");
6348                         if (arglist & CAM_ARG_VERBOSE) {
6349                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6350                                                 CAM_EPF_ALL, stderr);
6351                         }
6352                         error = 1;
6353                         goto scsiformat_bailout;
6354                 }
6355
6356                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6357
6358                 if ((status != CAM_REQ_CMP)
6359                  && (status == CAM_SCSI_STATUS_ERROR)
6360                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6361                         struct scsi_sense_data *sense;
6362                         int error_code, sense_key, asc, ascq;
6363
6364                         sense = &ccb->csio.sense_data;
6365                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6366                             ccb->csio.sense_resid, &error_code, &sense_key,
6367                             &asc, &ascq, /*show_errors*/ 1);
6368
6369                         /*
6370                          * According to the SCSI-2 and SCSI-3 specs, a
6371                          * drive that is in the middle of a format should
6372                          * return NOT READY with an ASC of "logical unit
6373                          * not ready, format in progress".  The sense key
6374                          * specific bytes will then be a progress indicator.
6375                          */
6376                         if ((sense_key == SSD_KEY_NOT_READY)
6377                          && (asc == 0x04) && (ascq == 0x04)) {
6378                                 uint8_t sks[3];
6379
6380                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6381                                      ccb->csio.sense_resid, sks) == 0)
6382                                  && (quiet == 0)) {
6383                                         uint32_t val;
6384                                         u_int64_t percentage;
6385
6386                                         val = scsi_2btoul(&sks[1]);
6387                                         percentage = 10000ull * val;
6388
6389                                         fprintf(stdout,
6390                                                 "\rFormatting:  %ju.%02u %% "
6391                                                 "(%u/%d) done",
6392                                                 (uintmax_t)(percentage /
6393                                                 (0x10000 * 100)),
6394                                                 (unsigned)((percentage /
6395                                                 0x10000) % 100),
6396                                                 val, 0x10000);
6397                                         fflush(stdout);
6398                                 } else if ((quiet == 0)
6399                                         && (++num_warnings <= 1)) {
6400                                         warnx("Unexpected SCSI Sense Key "
6401                                               "Specific value returned "
6402                                               "during format:");
6403                                         scsi_sense_print(device, &ccb->csio,
6404                                                          stderr);
6405                                         warnx("Unable to print status "
6406                                               "information, but format will "
6407                                               "proceed.");
6408                                         warnx("will exit when format is "
6409                                               "complete");
6410                                 }
6411                                 sleep(1);
6412                         } else {
6413                                 warnx("Unexpected SCSI error during format");
6414                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6415                                                 CAM_EPF_ALL, stderr);
6416                                 error = 1;
6417                                 goto scsiformat_bailout;
6418                         }
6419
6420                 } else if (status != CAM_REQ_CMP) {
6421                         warnx("Unexpected CAM status %#x", status);
6422                         if (arglist & CAM_ARG_VERBOSE)
6423                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6424                                                 CAM_EPF_ALL, stderr);
6425                         error = 1;
6426                         goto scsiformat_bailout;
6427                 }
6428
6429         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6430
6431         if (quiet == 0)
6432                 fprintf(stdout, "\nFormat Complete\n");
6433
6434 scsiformat_bailout:
6435
6436         cam_freeccb(ccb);
6437
6438         return (error);
6439 }
6440
6441 static int
6442 scsisanitize(struct cam_device *device, int argc, char **argv,
6443              char *combinedopt, int task_attr, int retry_count, int timeout)
6444 {
6445         union ccb *ccb;
6446         u_int8_t action = 0;
6447         int c;
6448         int ycount = 0, quiet = 0;
6449         int error = 0, retval = 0;
6450         int use_timeout = 10800 * 1000;
6451         int immediate = 1;
6452         int invert = 0;
6453         int passes = 0;
6454         int ause = 0;
6455         int fd = -1;
6456         const char *pattern = NULL;
6457         u_int8_t *data_ptr = NULL;
6458         u_int32_t dxfer_len = 0;
6459         u_int8_t byte2 = 0;
6460         int num_warnings = 0;
6461         int reportonly = 0;
6462
6463         ccb = cam_getccb(device);
6464
6465         if (ccb == NULL) {
6466                 warnx("scsisanitize: error allocating ccb");
6467                 return (1);
6468         }
6469
6470         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6471
6472         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6473                 switch(c) {
6474                 case 'a':
6475                         if (strcasecmp(optarg, "overwrite") == 0)
6476                                 action = SSZ_SERVICE_ACTION_OVERWRITE;
6477                         else if (strcasecmp(optarg, "block") == 0)
6478                                 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6479                         else if (strcasecmp(optarg, "crypto") == 0)
6480                                 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6481                         else if (strcasecmp(optarg, "exitfailure") == 0)
6482                                 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6483                         else {
6484                                 warnx("invalid service operation \"%s\"",
6485                                       optarg);
6486                                 error = 1;
6487                                 goto scsisanitize_bailout;
6488                         }
6489                         break;
6490                 case 'c':
6491                         passes = strtol(optarg, NULL, 0);
6492                         if (passes < 1 || passes > 31) {
6493                                 warnx("invalid passes value %d", passes);
6494                                 error = 1;
6495                                 goto scsisanitize_bailout;
6496                         }
6497                         break;
6498                 case 'I':
6499                         invert = 1;
6500                         break;
6501                 case 'P':
6502                         pattern = optarg;
6503                         break;
6504                 case 'q':
6505                         quiet++;
6506                         break;
6507                 case 'U':
6508                         ause = 1;
6509                         break;
6510                 case 'r':
6511                         reportonly = 1;
6512                         break;
6513                 case 'w':
6514                         immediate = 0;
6515                         break;
6516                 case 'y':
6517                         ycount++;
6518                         break;
6519                 }
6520         }
6521
6522         if (reportonly)
6523                 goto doreport;
6524
6525         if (action == 0) {
6526                 warnx("an action is required");
6527                 error = 1;
6528                 goto scsisanitize_bailout;
6529         } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6530                 struct scsi_sanitize_parameter_list *pl;
6531                 struct stat sb;
6532                 ssize_t sz, amt;
6533
6534                 if (pattern == NULL) {
6535                         warnx("overwrite action requires -P argument");
6536                         error = 1;
6537                         goto scsisanitize_bailout;
6538                 }
6539                 fd = open(pattern, O_RDONLY);
6540                 if (fd < 0) {
6541                         warn("cannot open pattern file %s", pattern);
6542                         error = 1;
6543                         goto scsisanitize_bailout;
6544                 }
6545                 if (fstat(fd, &sb) < 0) {
6546                         warn("cannot stat pattern file %s", pattern);
6547                         error = 1;
6548                         goto scsisanitize_bailout;
6549                 }
6550                 sz = sb.st_size;
6551                 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6552                         warnx("pattern file size exceeds maximum value %d",
6553                               SSZPL_MAX_PATTERN_LENGTH);
6554                         error = 1;
6555                         goto scsisanitize_bailout;
6556                 }
6557                 dxfer_len = sizeof(*pl) + sz;
6558                 data_ptr = calloc(1, dxfer_len);
6559                 if (data_ptr == NULL) {
6560                         warnx("cannot allocate parameter list buffer");
6561                         error = 1;
6562                         goto scsisanitize_bailout;
6563                 }
6564
6565                 amt = read(fd, data_ptr + sizeof(*pl), sz);
6566                 if (amt < 0) {
6567                         warn("cannot read pattern file");
6568                         error = 1;
6569                         goto scsisanitize_bailout;
6570                 } else if (amt != sz) {
6571                         warnx("short pattern file read");
6572                         error = 1;
6573                         goto scsisanitize_bailout;
6574                 }
6575
6576                 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6577                 if (passes == 0)
6578                         pl->byte1 = 1;
6579                 else
6580                         pl->byte1 = passes;
6581                 if (invert != 0)
6582                         pl->byte1 |= SSZPL_INVERT;
6583                 scsi_ulto2b(sz, pl->length);
6584         } else {
6585                 const char *arg;
6586
6587                 if (passes != 0)
6588                         arg = "-c";
6589                 else if (invert != 0)
6590                         arg = "-I";
6591                 else if (pattern != NULL)
6592                         arg = "-P";
6593                 else
6594                         arg = NULL;
6595                 if (arg != NULL) {
6596                         warnx("%s argument only valid with overwrite "
6597                               "operation", arg);
6598                         error = 1;
6599                         goto scsisanitize_bailout;
6600                 }
6601         }
6602
6603         if (quiet == 0) {
6604                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6605                         "following device:\n");
6606
6607                 error = scsidoinquiry(device, argc, argv, combinedopt,
6608                                       task_attr, retry_count, timeout);
6609
6610                 if (error != 0) {
6611                         warnx("scsisanitize: error sending inquiry");
6612                         goto scsisanitize_bailout;
6613                 }
6614         }
6615
6616         if (ycount == 0) {
6617                 if (!get_confirmation()) {
6618                         error = 1;
6619                         goto scsisanitize_bailout;
6620                 }
6621         }
6622
6623         if (timeout != 0)
6624                 use_timeout = timeout;
6625
6626         if (quiet == 0) {
6627                 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6628                         use_timeout / 1000);
6629         }
6630
6631         /*
6632          * If the user hasn't disabled questions and didn't specify a
6633          * timeout on the command line, ask them if they want the current
6634          * timeout.
6635          */
6636         if ((ycount == 0)
6637          && (timeout == 0)) {
6638                 char str[1024];
6639                 int new_timeout = 0;
6640
6641                 fprintf(stdout, "Enter new timeout in seconds or press\n"
6642                         "return to keep the current timeout [%d] ",
6643                         use_timeout / 1000);
6644
6645                 if (fgets(str, sizeof(str), stdin) != NULL) {
6646                         if (str[0] != '\0')
6647                                 new_timeout = atoi(str);
6648                 }
6649
6650                 if (new_timeout != 0) {
6651                         use_timeout = new_timeout * 1000;
6652                         fprintf(stdout, "Using new timeout value %d\n",
6653                                 use_timeout / 1000);
6654                 }
6655         }
6656
6657         byte2 = action;
6658         if (ause != 0)
6659                 byte2 |= SSZ_UNRESTRICTED_EXIT;
6660         if (immediate != 0)
6661                 byte2 |= SSZ_IMMED;
6662
6663         scsi_sanitize(&ccb->csio,
6664                       /* retries */ retry_count,
6665                       /* cbfcnp */ NULL,
6666                       /* tag_action */ task_attr,
6667                       /* byte2 */ byte2,
6668                       /* control */ 0,
6669                       /* data_ptr */ data_ptr,
6670                       /* dxfer_len */ dxfer_len,
6671                       /* sense_len */ SSD_FULL_SIZE,
6672                       /* timeout */ use_timeout);
6673
6674         /* Disable freezing the device queue */
6675         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6676
6677         if (arglist & CAM_ARG_ERR_RECOVER)
6678                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6679
6680         if (cam_send_ccb(device, ccb) < 0) {
6681                 warn("error sending sanitize command");
6682                 error = 1;
6683                 goto scsisanitize_bailout;
6684         }
6685
6686         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6687                 struct scsi_sense_data *sense;
6688                 int error_code, sense_key, asc, ascq;
6689
6690                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6691                     CAM_SCSI_STATUS_ERROR) {
6692                         sense = &ccb->csio.sense_data;
6693                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6694                             ccb->csio.sense_resid, &error_code, &sense_key,
6695                             &asc, &ascq, /*show_errors*/ 1);
6696
6697                         if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6698                             asc == 0x20 && ascq == 0x00)
6699                                 warnx("sanitize is not supported by "
6700                                       "this device");
6701                         else
6702                                 warnx("error sanitizing this device");
6703                 } else
6704                         warnx("error sanitizing this device");
6705
6706                 if (arglist & CAM_ARG_VERBOSE) {
6707                         cam_error_print(device, ccb, CAM_ESF_ALL,
6708                                         CAM_EPF_ALL, stderr);
6709                 }
6710                 error = 1;
6711                 goto scsisanitize_bailout;
6712         }
6713
6714         /*
6715          * If we ran in non-immediate mode, we already checked for errors
6716          * above and printed out any necessary information.  If we're in
6717          * immediate mode, we need to loop through and get status
6718          * information periodically.
6719          */
6720         if (immediate == 0) {
6721                 if (quiet == 0) {
6722                         fprintf(stdout, "Sanitize Complete\n");
6723                 }
6724                 goto scsisanitize_bailout;
6725         }
6726
6727 doreport:
6728         do {
6729                 cam_status status;
6730
6731                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6732
6733                 /*
6734                  * There's really no need to do error recovery or
6735                  * retries here, since we're just going to sit in a
6736                  * loop and wait for the device to finish sanitizing.
6737                  */
6738                 scsi_test_unit_ready(&ccb->csio,
6739                                      /* retries */ 0,
6740                                      /* cbfcnp */ NULL,
6741                                      /* tag_action */ task_attr,
6742                                      /* sense_len */ SSD_FULL_SIZE,
6743                                      /* timeout */ 5000);
6744
6745                 /* Disable freezing the device queue */
6746                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6747
6748                 retval = cam_send_ccb(device, ccb);
6749
6750                 /*
6751                  * If we get an error from the ioctl, bail out.  SCSI
6752                  * errors are expected.
6753                  */
6754                 if (retval < 0) {
6755                         warn("error sending CAMIOCOMMAND ioctl");
6756                         if (arglist & CAM_ARG_VERBOSE) {
6757                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6758                                                 CAM_EPF_ALL, stderr);
6759                         }
6760                         error = 1;
6761                         goto scsisanitize_bailout;
6762                 }
6763
6764                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6765
6766                 if ((status != CAM_REQ_CMP)
6767                  && (status == CAM_SCSI_STATUS_ERROR)
6768                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6769                         struct scsi_sense_data *sense;
6770                         int error_code, sense_key, asc, ascq;
6771
6772                         sense = &ccb->csio.sense_data;
6773                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6774                             ccb->csio.sense_resid, &error_code, &sense_key,
6775                             &asc, &ascq, /*show_errors*/ 1);
6776
6777                         /*
6778                          * According to the SCSI-3 spec, a drive that is in the
6779                          * middle of a sanitize should return NOT READY with an
6780                          * ASC of "logical unit not ready, sanitize in
6781                          * progress". The sense key specific bytes will then
6782                          * be a progress indicator.
6783                          */
6784                         if ((sense_key == SSD_KEY_NOT_READY)
6785                          && (asc == 0x04) && (ascq == 0x1b)) {
6786                                 uint8_t sks[3];
6787
6788                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6789                                      ccb->csio.sense_resid, sks) == 0)
6790                                  && (quiet == 0)) {
6791                                         int val;
6792                                         u_int64_t percentage;
6793
6794                                         val = scsi_2btoul(&sks[1]);
6795                                         percentage = 10000 * val;
6796
6797                                         fprintf(stdout,
6798                                                 "\rSanitizing:  %ju.%02u %% "
6799                                                 "(%d/%d) done",
6800                                                 (uintmax_t)(percentage /
6801                                                 (0x10000 * 100)),
6802                                                 (unsigned)((percentage /
6803                                                 0x10000) % 100),
6804                                                 val, 0x10000);
6805                                         fflush(stdout);
6806                                 } else if ((quiet == 0)
6807                                         && (++num_warnings <= 1)) {
6808                                         warnx("Unexpected SCSI Sense Key "
6809                                               "Specific value returned "
6810                                               "during sanitize:");
6811                                         scsi_sense_print(device, &ccb->csio,
6812                                                          stderr);
6813                                         warnx("Unable to print status "
6814                                               "information, but sanitze will "
6815                                               "proceed.");
6816                                         warnx("will exit when sanitize is "
6817                                               "complete");
6818                                 }
6819                                 sleep(1);
6820                         } else {
6821                                 warnx("Unexpected SCSI error during sanitize");
6822                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6823                                                 CAM_EPF_ALL, stderr);
6824                                 error = 1;
6825                                 goto scsisanitize_bailout;
6826                         }
6827
6828                 } else if (status != CAM_REQ_CMP) {
6829                         warnx("Unexpected CAM status %#x", status);
6830                         if (arglist & CAM_ARG_VERBOSE)
6831                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6832                                                 CAM_EPF_ALL, stderr);
6833                         error = 1;
6834                         goto scsisanitize_bailout;
6835                 }
6836         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6837
6838         if (quiet == 0)
6839                 fprintf(stdout, "\nSanitize Complete\n");
6840
6841 scsisanitize_bailout:
6842         if (fd >= 0)
6843                 close(fd);
6844         if (data_ptr != NULL)
6845                 free(data_ptr);
6846         cam_freeccb(ccb);
6847
6848         return (error);
6849 }
6850
6851 static int
6852 scsireportluns(struct cam_device *device, int argc, char **argv,
6853                char *combinedopt, int task_attr, int retry_count, int timeout)
6854 {
6855         union ccb *ccb;
6856         int c, countonly, lunsonly;
6857         struct scsi_report_luns_data *lundata;
6858         int alloc_len;
6859         uint8_t report_type;
6860         uint32_t list_len, i, j;
6861         int retval;
6862
6863         retval = 0;
6864         lundata = NULL;
6865         report_type = RPL_REPORT_DEFAULT;
6866         ccb = cam_getccb(device);
6867
6868         if (ccb == NULL) {
6869                 warnx("%s: error allocating ccb", __func__);
6870                 return (1);
6871         }
6872
6873         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6874
6875         countonly = 0;
6876         lunsonly = 0;
6877
6878         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6879                 switch (c) {
6880                 case 'c':
6881                         countonly++;
6882                         break;
6883                 case 'l':
6884                         lunsonly++;
6885                         break;
6886                 case 'r':
6887                         if (strcasecmp(optarg, "default") == 0)
6888                                 report_type = RPL_REPORT_DEFAULT;
6889                         else if (strcasecmp(optarg, "wellknown") == 0)
6890                                 report_type = RPL_REPORT_WELLKNOWN;
6891                         else if (strcasecmp(optarg, "all") == 0)
6892                                 report_type = RPL_REPORT_ALL;
6893                         else {
6894                                 warnx("%s: invalid report type \"%s\"",
6895                                       __func__, optarg);
6896                                 retval = 1;
6897                                 goto bailout;
6898                         }
6899                         break;
6900                 default:
6901                         break;
6902                 }
6903         }
6904
6905         if ((countonly != 0)
6906          && (lunsonly != 0)) {
6907                 warnx("%s: you can only specify one of -c or -l", __func__);
6908                 retval = 1;
6909                 goto bailout;
6910         }
6911         /*
6912          * According to SPC-4, the allocation length must be at least 16
6913          * bytes -- enough for the header and one LUN.
6914          */
6915         alloc_len = sizeof(*lundata) + 8;
6916
6917 retry:
6918
6919         lundata = malloc(alloc_len);
6920
6921         if (lundata == NULL) {
6922                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6923                 retval = 1;
6924                 goto bailout;
6925         }
6926
6927         scsi_report_luns(&ccb->csio,
6928                          /*retries*/ retry_count,
6929                          /*cbfcnp*/ NULL,
6930                          /*tag_action*/ task_attr,
6931                          /*select_report*/ report_type,
6932                          /*rpl_buf*/ lundata,
6933                          /*alloc_len*/ alloc_len,
6934                          /*sense_len*/ SSD_FULL_SIZE,
6935                          /*timeout*/ timeout ? timeout : 5000);
6936
6937         /* Disable freezing the device queue */
6938         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6939
6940         if (arglist & CAM_ARG_ERR_RECOVER)
6941                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6942
6943         if (cam_send_ccb(device, ccb) < 0) {
6944                 warn("error sending REPORT LUNS command");
6945
6946                 if (arglist & CAM_ARG_VERBOSE)
6947                         cam_error_print(device, ccb, CAM_ESF_ALL,
6948                                         CAM_EPF_ALL, stderr);
6949
6950                 retval = 1;
6951                 goto bailout;
6952         }
6953
6954         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6955                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6956                 retval = 1;
6957                 goto bailout;
6958         }
6959
6960
6961         list_len = scsi_4btoul(lundata->length);
6962
6963         /*
6964          * If we need to list the LUNs, and our allocation
6965          * length was too short, reallocate and retry.
6966          */
6967         if ((countonly == 0)
6968          && (list_len > (alloc_len - sizeof(*lundata)))) {
6969                 alloc_len = list_len + sizeof(*lundata);
6970                 free(lundata);
6971                 goto retry;
6972         }
6973
6974         if (lunsonly == 0)
6975                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6976                         ((list_len / 8) > 1) ? "s" : "");
6977
6978         if (countonly != 0)
6979                 goto bailout;
6980
6981         for (i = 0; i < (list_len / 8); i++) {
6982                 int no_more;
6983
6984                 no_more = 0;
6985                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6986                         if (j != 0)
6987                                 fprintf(stdout, ",");
6988                         switch (lundata->luns[i].lundata[j] &
6989                                 RPL_LUNDATA_ATYP_MASK) {
6990                         case RPL_LUNDATA_ATYP_PERIPH:
6991                                 if ((lundata->luns[i].lundata[j] &
6992                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6993                                         fprintf(stdout, "%d:",
6994                                                 lundata->luns[i].lundata[j] &
6995                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
6996                                 else if ((j == 0)
6997                                       && ((lundata->luns[i].lundata[j+2] &
6998                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6999                                         no_more = 1;
7000
7001                                 fprintf(stdout, "%d",
7002                                         lundata->luns[i].lundata[j+1]);
7003                                 break;
7004                         case RPL_LUNDATA_ATYP_FLAT: {
7005                                 uint8_t tmplun[2];
7006                                 tmplun[0] = lundata->luns[i].lundata[j] &
7007                                         RPL_LUNDATA_FLAT_LUN_MASK;
7008                                 tmplun[1] = lundata->luns[i].lundata[j+1];
7009
7010                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
7011                                 no_more = 1;
7012                                 break;
7013                         }
7014                         case RPL_LUNDATA_ATYP_LUN:
7015                                 fprintf(stdout, "%d:%d:%d",
7016                                         (lundata->luns[i].lundata[j+1] &
7017                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
7018                                         lundata->luns[i].lundata[j] &
7019                                         RPL_LUNDATA_LUN_TARG_MASK,
7020                                         lundata->luns[i].lundata[j+1] &
7021                                         RPL_LUNDATA_LUN_LUN_MASK);
7022                                 break;
7023                         case RPL_LUNDATA_ATYP_EXTLUN: {
7024                                 int field_len_code, eam_code;
7025
7026                                 eam_code = lundata->luns[i].lundata[j] &
7027                                         RPL_LUNDATA_EXT_EAM_MASK;
7028                                 field_len_code = (lundata->luns[i].lundata[j] &
7029                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
7030
7031                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
7032                                  && (field_len_code == 0x00)) {
7033                                         fprintf(stdout, "%d",
7034                                                 lundata->luns[i].lundata[j+1]);
7035                                 } else if ((eam_code ==
7036                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
7037                                         && (field_len_code == 0x03)) {
7038                                         uint8_t tmp_lun[8];
7039
7040                                         /*
7041                                          * This format takes up all 8 bytes.
7042                                          * If we aren't starting at offset 0,
7043                                          * that's a bug.
7044                                          */
7045                                         if (j != 0) {
7046                                                 fprintf(stdout, "Invalid "
7047                                                         "offset %d for "
7048                                                         "Extended LUN not "
7049                                                         "specified format", j);
7050                                                 no_more = 1;
7051                                                 break;
7052                                         }
7053                                         bzero(tmp_lun, sizeof(tmp_lun));
7054                                         bcopy(&lundata->luns[i].lundata[j+1],
7055                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
7056                                         fprintf(stdout, "%#jx",
7057                                                (intmax_t)scsi_8btou64(tmp_lun));
7058                                         no_more = 1;
7059                                 } else {
7060                                         fprintf(stderr, "Unknown Extended LUN"
7061                                                 "Address method %#x, length "
7062                                                 "code %#x", eam_code,
7063                                                 field_len_code);
7064                                         no_more = 1;
7065                                 }
7066                                 break;
7067                         }
7068                         default:
7069                                 fprintf(stderr, "Unknown LUN address method "
7070                                         "%#x\n", lundata->luns[i].lundata[0] &
7071                                         RPL_LUNDATA_ATYP_MASK);
7072                                 break;
7073                         }
7074                         /*
7075                          * For the flat addressing method, there are no
7076                          * other levels after it.
7077                          */
7078                         if (no_more != 0)
7079                                 break;
7080                 }
7081                 fprintf(stdout, "\n");
7082         }
7083
7084 bailout:
7085
7086         cam_freeccb(ccb);
7087
7088         free(lundata);
7089
7090         return (retval);
7091 }
7092
7093 static int
7094 scsireadcapacity(struct cam_device *device, int argc, char **argv,
7095                  char *combinedopt, int task_attr, int retry_count, int timeout)
7096 {
7097         union ccb *ccb;
7098         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
7099         struct scsi_read_capacity_data rcap;
7100         struct scsi_read_capacity_data_long rcaplong;
7101         uint64_t maxsector;
7102         uint32_t block_len;
7103         int retval;
7104         int c;
7105
7106         blocksizeonly = 0;
7107         humanize = 0;
7108         numblocks = 0;
7109         quiet = 0;
7110         sizeonly = 0;
7111         baseten = 0;
7112         retval = 0;
7113
7114         ccb = cam_getccb(device);
7115
7116         if (ccb == NULL) {
7117                 warnx("%s: error allocating ccb", __func__);
7118                 return (1);
7119         }
7120
7121         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
7122
7123         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7124                 switch (c) {
7125                 case 'b':
7126                         blocksizeonly++;
7127                         break;
7128                 case 'h':
7129                         humanize++;
7130                         baseten = 0;
7131                         break;
7132                 case 'H':
7133                         humanize++;
7134                         baseten++;
7135                         break;
7136                 case 'N':
7137                         numblocks++;
7138                         break;
7139                 case 'q':
7140                         quiet++;
7141                         break;
7142                 case 's':
7143                         sizeonly++;
7144                         break;
7145                 default:
7146                         break;
7147                 }
7148         }
7149
7150         if ((blocksizeonly != 0)
7151          && (numblocks != 0)) {
7152                 warnx("%s: you can only specify one of -b or -N", __func__);
7153                 retval = 1;
7154                 goto bailout;
7155         }
7156
7157         if ((blocksizeonly != 0)
7158          && (sizeonly != 0)) {
7159                 warnx("%s: you can only specify one of -b or -s", __func__);
7160                 retval = 1;
7161                 goto bailout;
7162         }
7163
7164         if ((humanize != 0)
7165          && (quiet != 0)) {
7166                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
7167                 retval = 1;
7168                 goto bailout;
7169         }
7170
7171         if ((humanize != 0)
7172          && (blocksizeonly != 0)) {
7173                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
7174                 retval = 1;
7175                 goto bailout;
7176         }
7177
7178         scsi_read_capacity(&ccb->csio,
7179                            /*retries*/ retry_count,
7180                            /*cbfcnp*/ NULL,
7181                            /*tag_action*/ task_attr,
7182                            &rcap,
7183                            SSD_FULL_SIZE,
7184                            /*timeout*/ timeout ? timeout : 5000);
7185
7186         /* Disable freezing the device queue */
7187         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7188
7189         if (arglist & CAM_ARG_ERR_RECOVER)
7190                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7191
7192         if (cam_send_ccb(device, ccb) < 0) {
7193                 warn("error sending READ CAPACITY command");
7194
7195                 if (arglist & CAM_ARG_VERBOSE)
7196                         cam_error_print(device, ccb, CAM_ESF_ALL,
7197                                         CAM_EPF_ALL, stderr);
7198
7199                 retval = 1;
7200                 goto bailout;
7201         }
7202
7203         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7204                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7205                 retval = 1;
7206                 goto bailout;
7207         }
7208
7209         maxsector = scsi_4btoul(rcap.addr);
7210         block_len = scsi_4btoul(rcap.length);
7211
7212         /*
7213          * A last block of 2^32-1 means that the true capacity is over 2TB,
7214          * and we need to issue the long READ CAPACITY to get the real
7215          * capacity.  Otherwise, we're all set.
7216          */
7217         if (maxsector != 0xffffffff)
7218                 goto do_print;
7219
7220         scsi_read_capacity_16(&ccb->csio,
7221                               /*retries*/ retry_count,
7222                               /*cbfcnp*/ NULL,
7223                               /*tag_action*/ task_attr,
7224                               /*lba*/ 0,
7225                               /*reladdr*/ 0,
7226                               /*pmi*/ 0,
7227                               /*rcap_buf*/ (uint8_t *)&rcaplong,
7228                               /*rcap_buf_len*/ sizeof(rcaplong),
7229                               /*sense_len*/ SSD_FULL_SIZE,
7230                               /*timeout*/ timeout ? timeout : 5000);
7231
7232         /* Disable freezing the device queue */
7233         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7234
7235         if (arglist & CAM_ARG_ERR_RECOVER)
7236                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7237
7238         if (cam_send_ccb(device, ccb) < 0) {
7239                 warn("error sending READ CAPACITY (16) command");
7240
7241                 if (arglist & CAM_ARG_VERBOSE)
7242                         cam_error_print(device, ccb, CAM_ESF_ALL,
7243                                         CAM_EPF_ALL, stderr);
7244
7245                 retval = 1;
7246                 goto bailout;
7247         }
7248
7249         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7250                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7251                 retval = 1;
7252                 goto bailout;
7253         }
7254
7255         maxsector = scsi_8btou64(rcaplong.addr);
7256         block_len = scsi_4btoul(rcaplong.length);
7257
7258 do_print:
7259         if (blocksizeonly == 0) {
7260                 /*
7261                  * Humanize implies !quiet, and also implies numblocks.
7262                  */
7263                 if (humanize != 0) {
7264                         char tmpstr[6];
7265                         int64_t tmpbytes;
7266                         int ret;
7267
7268                         tmpbytes = (maxsector + 1) * block_len;
7269                         ret = humanize_number(tmpstr, sizeof(tmpstr),
7270                                               tmpbytes, "", HN_AUTOSCALE,
7271                                               HN_B | HN_DECIMAL |
7272                                               ((baseten != 0) ?
7273                                               HN_DIVISOR_1000 : 0));
7274                         if (ret == -1) {
7275                                 warnx("%s: humanize_number failed!", __func__);
7276                                 retval = 1;
7277                                 goto bailout;
7278                         }
7279                         fprintf(stdout, "Device Size: %s%s", tmpstr,
7280                                 (sizeonly == 0) ?  ", " : "\n");
7281                 } else if (numblocks != 0) {
7282                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7283                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
7284                                 (sizeonly == 0) ? ", " : "\n");
7285                 } else {
7286                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7287                                 "Last Block: " : "", (uintmax_t)maxsector,
7288                                 (sizeonly == 0) ? ", " : "\n");
7289                 }
7290         }
7291         if (sizeonly == 0)
7292                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
7293                         "Block Length: " : "", block_len, (quiet == 0) ?
7294                         " bytes" : "");
7295 bailout:
7296         cam_freeccb(ccb);
7297
7298         return (retval);
7299 }
7300
7301 static int
7302 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
7303        int retry_count, int timeout)
7304 {
7305         int c, error = 0;
7306         union ccb *ccb;
7307         uint8_t *smp_request = NULL, *smp_response = NULL;
7308         int request_size = 0, response_size = 0;
7309         int fd_request = 0, fd_response = 0;
7310         char *datastr = NULL;
7311         struct get_hook hook;
7312         int retval;
7313         int flags = 0;
7314
7315         /*
7316          * Note that at the moment we don't support sending SMP CCBs to
7317          * devices that aren't probed by CAM.
7318          */
7319         ccb = cam_getccb(device);
7320         if (ccb == NULL) {
7321                 warnx("%s: error allocating CCB", __func__);
7322                 return (1);
7323         }
7324
7325         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7326
7327         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7328                 switch (c) {
7329                 case 'R':
7330                         arglist |= CAM_ARG_CMD_IN;
7331                         response_size = strtol(optarg, NULL, 0);
7332                         if (response_size <= 0) {
7333                                 warnx("invalid number of response bytes %d",
7334                                       response_size);
7335                                 error = 1;
7336                                 goto smpcmd_bailout;
7337                         }
7338                         hook.argc = argc - optind;
7339                         hook.argv = argv + optind;
7340                         hook.got = 0;
7341                         optind++;
7342                         datastr = cget(&hook, NULL);
7343                         /*
7344                          * If the user supplied "-" instead of a format, he
7345                          * wants the data to be written to stdout.
7346                          */
7347                         if ((datastr != NULL)
7348                          && (datastr[0] == '-'))
7349                                 fd_response = 1;
7350
7351                         smp_response = (u_int8_t *)malloc(response_size);
7352                         if (smp_response == NULL) {
7353                                 warn("can't malloc memory for SMP response");
7354                                 error = 1;
7355                                 goto smpcmd_bailout;
7356                         }
7357                         break;
7358                 case 'r':
7359                         arglist |= CAM_ARG_CMD_OUT;
7360                         request_size = strtol(optarg, NULL, 0);
7361                         if (request_size <= 0) {
7362                                 warnx("invalid number of request bytes %d",
7363                                       request_size);
7364                                 error = 1;
7365                                 goto smpcmd_bailout;
7366                         }
7367                         hook.argc = argc - optind;
7368                         hook.argv = argv + optind;
7369                         hook.got = 0;
7370                         datastr = cget(&hook, NULL);
7371                         smp_request = (u_int8_t *)malloc(request_size);
7372                         if (smp_request == NULL) {
7373                                 warn("can't malloc memory for SMP request");
7374                                 error = 1;
7375                                 goto smpcmd_bailout;
7376                         }
7377                         bzero(smp_request, request_size);
7378                         /*
7379                          * If the user supplied "-" instead of a format, he
7380                          * wants the data to be read from stdin.
7381                          */
7382                         if ((datastr != NULL)
7383                          && (datastr[0] == '-'))
7384                                 fd_request = 1;
7385                         else
7386                                 buff_encode_visit(smp_request, request_size,
7387                                                   datastr,
7388                                                   iget, &hook);
7389                         optind += hook.got;
7390                         break;
7391                 default:
7392                         break;
7393                 }
7394         }
7395
7396         /*
7397          * If fd_data is set, and we're writing to the device, we need to
7398          * read the data the user wants written from stdin.
7399          */
7400         if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
7401                 ssize_t amt_read;
7402                 int amt_to_read = request_size;
7403                 u_int8_t *buf_ptr = smp_request;
7404
7405                 for (amt_read = 0; amt_to_read > 0;
7406                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
7407                         if (amt_read == -1) {
7408                                 warn("error reading data from stdin");
7409                                 error = 1;
7410                                 goto smpcmd_bailout;
7411                         }
7412                         amt_to_read -= amt_read;
7413                         buf_ptr += amt_read;
7414                 }
7415         }
7416
7417         if (((arglist & CAM_ARG_CMD_IN) == 0)
7418          || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
7419                 warnx("%s: need both the request (-r) and response (-R) "
7420                       "arguments", __func__);
7421                 error = 1;
7422                 goto smpcmd_bailout;
7423         }
7424
7425         flags |= CAM_DEV_QFRZDIS;
7426
7427         cam_fill_smpio(&ccb->smpio,
7428                        /*retries*/ retry_count,
7429                        /*cbfcnp*/ NULL,
7430                        /*flags*/ flags,
7431                        /*smp_request*/ smp_request,
7432                        /*smp_request_len*/ request_size,
7433                        /*smp_response*/ smp_response,
7434                        /*smp_response_len*/ response_size,
7435                        /*timeout*/ timeout ? timeout : 5000);
7436
7437         ccb->smpio.flags = SMP_FLAG_NONE;
7438
7439         if (((retval = cam_send_ccb(device, ccb)) < 0)
7440          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7441                 const char warnstr[] = "error sending command";
7442
7443                 if (retval < 0)
7444                         warn(warnstr);
7445                 else
7446                         warnx(warnstr);
7447
7448                 if (arglist & CAM_ARG_VERBOSE) {
7449                         cam_error_print(device, ccb, CAM_ESF_ALL,
7450                                         CAM_EPF_ALL, stderr);
7451                 }
7452         }
7453
7454         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
7455          && (response_size > 0)) {
7456                 if (fd_response == 0) {
7457                         buff_decode_visit(smp_response, response_size,
7458                                           datastr, arg_put, NULL);
7459                         fprintf(stdout, "\n");
7460                 } else {
7461                         ssize_t amt_written;
7462                         int amt_to_write = response_size;
7463                         u_int8_t *buf_ptr = smp_response;
7464
7465                         for (amt_written = 0; (amt_to_write > 0) &&
7466                              (amt_written = write(STDOUT_FILENO, buf_ptr,
7467                                                   amt_to_write)) > 0;){
7468                                 amt_to_write -= amt_written;
7469                                 buf_ptr += amt_written;
7470                         }
7471                         if (amt_written == -1) {
7472                                 warn("error writing data to stdout");
7473                                 error = 1;
7474                                 goto smpcmd_bailout;
7475                         } else if ((amt_written == 0)
7476                                 && (amt_to_write > 0)) {
7477                                 warnx("only wrote %u bytes out of %u",
7478                                       response_size - amt_to_write,
7479                                       response_size);
7480                         }
7481                 }
7482         }
7483 smpcmd_bailout:
7484         if (ccb != NULL)
7485                 cam_freeccb(ccb);
7486
7487         if (smp_request != NULL)
7488                 free(smp_request);
7489
7490         if (smp_response != NULL)
7491                 free(smp_response);
7492
7493         return (error);
7494 }
7495
7496 static int
7497 mmcsdcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
7498        int retry_count, int timeout)
7499 {
7500         int c, error = 0;
7501         union ccb *ccb;
7502         int32_t mmc_opcode = 0, mmc_arg = 0;
7503         int32_t mmc_flags = -1;
7504         int retval;
7505         int is_write = 0;
7506         int is_bw_4 = 0, is_bw_1 = 0;
7507         int is_highspeed = 0, is_stdspeed = 0;
7508         int is_info_request = 0;
7509         int flags = 0;
7510         uint8_t mmc_data_byte = 0;
7511
7512         /* For IO_RW_EXTENDED command */
7513         uint8_t *mmc_data = NULL;
7514         struct mmc_data mmc_d;
7515         int mmc_data_len = 0;
7516
7517         /*
7518          * Note that at the moment we don't support sending SMP CCBs to
7519          * devices that aren't probed by CAM.
7520          */
7521         ccb = cam_getccb(device);
7522         if (ccb == NULL) {
7523                 warnx("%s: error allocating CCB", __func__);
7524                 return (1);
7525         }
7526
7527         bzero(&(&ccb->ccb_h)[1],
7528               sizeof(union ccb) - sizeof(struct ccb_hdr));
7529
7530         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7531                 switch (c) {
7532                 case '4':
7533                         is_bw_4 = 1;
7534                         break;
7535                 case '1':
7536                         is_bw_1 = 1;
7537                         break;
7538                 case 'S':
7539                         if (!strcmp(optarg, "high"))
7540                                 is_highspeed = 1;
7541                         else
7542                                 is_stdspeed = 1;
7543                         break;
7544                 case 'I':
7545                         is_info_request = 1;
7546                         break;
7547                 case 'c':
7548                         mmc_opcode = strtol(optarg, NULL, 0);
7549                         if (mmc_opcode < 0) {
7550                                 warnx("invalid MMC opcode %d",
7551                                       mmc_opcode);
7552                                 error = 1;
7553                                 goto mmccmd_bailout;
7554                         }
7555                         break;
7556                 case 'a':
7557                         mmc_arg = strtol(optarg, NULL, 0);
7558                         if (mmc_arg < 0) {
7559                                 warnx("invalid MMC arg %d",
7560                                       mmc_arg);
7561                                 error = 1;
7562                                 goto mmccmd_bailout;
7563                         }
7564                         break;
7565                 case 'f':
7566                         mmc_flags = strtol(optarg, NULL, 0);
7567                         if (mmc_flags < 0) {
7568                                 warnx("invalid MMC flags %d",
7569                                       mmc_flags);
7570                                 error = 1;
7571                                 goto mmccmd_bailout;
7572                         }
7573                         break;
7574                 case 'l':
7575                         mmc_data_len = strtol(optarg, NULL, 0);
7576                         if (mmc_data_len <= 0) {
7577                                 warnx("invalid MMC data len %d",
7578                                       mmc_data_len);
7579                                 error = 1;
7580                                 goto mmccmd_bailout;
7581                         }
7582                         break;
7583                 case 'W':
7584                         is_write = 1;
7585                         break;
7586                 case 'b':
7587                         mmc_data_byte = strtol(optarg, NULL, 0);
7588                         break;
7589                 default:
7590                         break;
7591                 }
7592         }
7593         flags |= CAM_DEV_QFRZDIS; /* masks are broken?! */
7594
7595         /* If flags are left default, supply the right flags */
7596         if (mmc_flags < 0)
7597                 switch (mmc_opcode) {
7598                 case MMC_GO_IDLE_STATE:
7599                         mmc_flags = MMC_RSP_NONE | MMC_CMD_BC;
7600                         break;
7601                 case IO_SEND_OP_COND:
7602                         mmc_flags = MMC_RSP_R4;
7603                         break;
7604                 case SD_SEND_RELATIVE_ADDR:
7605                         mmc_flags = MMC_RSP_R6 | MMC_CMD_BCR;
7606                         break;
7607                 case MMC_SELECT_CARD:
7608                         mmc_flags = MMC_RSP_R1B | MMC_CMD_AC;
7609                         mmc_arg = mmc_arg << 16;
7610                         break;
7611                 case SD_IO_RW_DIRECT:
7612                         mmc_flags = MMC_RSP_R5 | MMC_CMD_AC;
7613                         mmc_arg = SD_IO_RW_ADR(mmc_arg);
7614                         if (is_write)
7615                                 mmc_arg |= SD_IO_RW_WR | SD_IO_RW_RAW | SD_IO_RW_DAT(mmc_data_byte);
7616                         break;
7617                 case SD_IO_RW_EXTENDED:
7618                         mmc_flags = MMC_RSP_R5 | MMC_CMD_ADTC;
7619                         mmc_arg = SD_IO_RW_ADR(mmc_arg);
7620                         int len_arg = mmc_data_len;
7621                         if (mmc_data_len == 512)
7622                                 len_arg = 0;
7623
7624                         // Byte mode
7625                         mmc_arg |= SD_IOE_RW_LEN(len_arg) | SD_IO_RW_INCR;
7626                         // Block mode
7627 //                        mmc_arg |= SD_IOE_RW_BLK | SD_IOE_RW_LEN(len_arg) | SD_IO_RW_INCR;
7628                         break;
7629                 default:
7630                         mmc_flags = MMC_RSP_R1;
7631                         break;
7632                 }
7633
7634         // Switch bus width instead of sending IO command
7635         if (is_bw_4 || is_bw_1) {
7636                 struct ccb_trans_settings_mmc *cts;
7637                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
7638                 ccb->ccb_h.flags = 0;
7639                 cts = &ccb->cts.proto_specific.mmc;
7640                 cts->ios.bus_width = is_bw_4 == 1 ? bus_width_4 : bus_width_1;
7641                 cts->ios_valid = MMC_BW;
7642                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7643                     || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7644                         warn("Error sending command");
7645                 } else {
7646                         printf("Parameters set OK\n");
7647                 }
7648                 cam_freeccb(ccb);
7649                 return (retval);
7650         }
7651
7652         // Switch bus speed instead of sending IO command
7653         if (is_stdspeed || is_highspeed) {
7654                 struct ccb_trans_settings_mmc *cts;
7655                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
7656                 ccb->ccb_h.flags = 0;
7657                 cts = &ccb->cts.proto_specific.mmc;
7658                 cts->ios.timing = is_highspeed == 1 ? bus_timing_hs : bus_timing_normal;
7659                 cts->ios_valid = MMC_BT;
7660                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7661                     || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7662                         warn("Error sending command");
7663                 } else {
7664                         printf("Speed set OK (HS: %d)\n", is_highspeed);
7665                 }
7666                 cam_freeccb(ccb);
7667                 return (retval);
7668         }
7669
7670         // Get information about controller and its settings
7671         if (is_info_request) {
7672                 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
7673                 ccb->ccb_h.flags = 0;
7674                 struct ccb_trans_settings_mmc *cts;
7675                 cts = &ccb->cts.proto_specific.mmc;
7676                 if (((retval = cam_send_ccb(device, ccb)) < 0)
7677                     || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7678                         warn("Error sending command");
7679                         return (retval);
7680                 }
7681                 printf("Host controller information\n");
7682                 printf("Host OCR: 0x%x\n", cts->host_ocr);
7683                 printf("Min frequency: %u KHz\n", cts->host_f_min / 1000);
7684                 printf("Max frequency: %u MHz\n", cts->host_f_max / 1000000);
7685                 printf("Supported bus width: ");
7686                 if (cts->host_caps & MMC_CAP_4_BIT_DATA)
7687                         printf(" 4 bit\n");
7688                 if (cts->host_caps & MMC_CAP_8_BIT_DATA)
7689                         printf(" 8 bit\n");
7690                 printf("\nCurrent settings:\n");
7691                 printf("Bus width: ");
7692                 switch (cts->ios.bus_width) {
7693                 case bus_width_1:
7694                         printf("1 bit\n");
7695                         break;
7696                 case bus_width_4:
7697                         printf("4 bit\n");
7698                         break;
7699                 case bus_width_8:
7700                         printf("8 bit\n");
7701                         break;
7702                 }
7703                 printf("Freq: %d.%03d MHz%s\n",
7704                        cts->ios.clock / 1000000,
7705                        (cts->ios.clock / 1000) % 1000,
7706                        cts->ios.timing == bus_timing_hs ? "(high-speed timing)" : "");
7707                 return (0);
7708         }
7709
7710         printf("CMD %d arg %d flags %02x\n", mmc_opcode, mmc_arg, mmc_flags);
7711
7712         if (mmc_data_len > 0) {
7713                 flags |= CAM_DIR_IN;
7714                 mmc_data = malloc(mmc_data_len);
7715                 memset(mmc_data, 0, mmc_data_len);
7716                 mmc_d.len = mmc_data_len;
7717                 mmc_d.data = mmc_data;
7718                 mmc_d.flags = MMC_DATA_READ;
7719         } else flags |= CAM_DIR_NONE;
7720
7721         cam_fill_mmcio(&ccb->mmcio,
7722                        /*retries*/ retry_count,
7723                        /*cbfcnp*/ NULL,
7724                        /*flags*/ flags,
7725                        /*mmc_opcode*/ mmc_opcode,
7726                        /*mmc_arg*/ mmc_arg,
7727                        /*mmc_flags*/ mmc_flags,
7728                        /*mmc_data*/ mmc_data_len > 0 ? &mmc_d : NULL,
7729                        /*timeout*/ timeout ? timeout : 5000);
7730
7731         if (((retval = cam_send_ccb(device, ccb)) < 0)
7732          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7733                 const char warnstr[] = "error sending command";
7734
7735                 if (retval < 0)
7736                         warn(warnstr);
7737                 else
7738                         warnx(warnstr);
7739
7740                 if (arglist & CAM_ARG_VERBOSE) {
7741                         cam_error_print(device, ccb, CAM_ESF_ALL,
7742                                         CAM_EPF_ALL, stderr);
7743                 }
7744         }
7745
7746         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)) {
7747                 printf("MMCIO: error %d, %08x %08x %08x %08x\n",
7748                        ccb->mmcio.cmd.error, ccb->mmcio.cmd.resp[0],
7749                        ccb->mmcio.cmd.resp[1],
7750                        ccb->mmcio.cmd.resp[2],
7751                        ccb->mmcio.cmd.resp[3]);
7752
7753                 switch (mmc_opcode) {
7754                 case SD_IO_RW_DIRECT:
7755                         printf("IO_RW_DIRECT: resp byte %02x, cur state %d\n",
7756                                SD_R5_DATA(ccb->mmcio.cmd.resp),
7757                                (ccb->mmcio.cmd.resp[0] >> 12) & 0x3);
7758                         break;
7759                 case SD_IO_RW_EXTENDED:
7760                         printf("IO_RW_EXTENDED: read %d bytes w/o error:\n", mmc_data_len);
7761                         hexdump(mmc_data, mmc_data_len, NULL, 0);
7762                         break;
7763                 case SD_SEND_RELATIVE_ADDR:
7764                         printf("SEND_RELATIVE_ADDR: published RCA %02x\n", ccb->mmcio.cmd.resp[0] >> 16);
7765                         break;
7766                 default:
7767                         printf("No command-specific decoder for CMD %d\n", mmc_opcode);
7768                 }
7769         }
7770 mmccmd_bailout:
7771         if (ccb != NULL)
7772                 cam_freeccb(ccb);
7773
7774         if (mmc_data_len > 0 && mmc_data != NULL)
7775                 free(mmc_data);
7776
7777         return (error);
7778 }
7779
7780 static int
7781 smpreportgeneral(struct cam_device *device, int argc, char **argv,
7782                  char *combinedopt, int retry_count, int timeout)
7783 {
7784         union ccb *ccb;
7785         struct smp_report_general_request *request = NULL;
7786         struct smp_report_general_response *response = NULL;
7787         struct sbuf *sb = NULL;
7788         int error = 0;
7789         int c, long_response = 0;
7790         int retval;
7791
7792         /*
7793          * Note that at the moment we don't support sending SMP CCBs to
7794          * devices that aren't probed by CAM.
7795          */
7796         ccb = cam_getccb(device);
7797         if (ccb == NULL) {
7798                 warnx("%s: error allocating CCB", __func__);
7799                 return (1);
7800         }
7801
7802         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7803
7804         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7805                 switch (c) {
7806                 case 'l':
7807                         long_response = 1;
7808                         break;
7809                 default:
7810                         break;
7811                 }
7812         }
7813         request = malloc(sizeof(*request));
7814         if (request == NULL) {
7815                 warn("%s: unable to allocate %zd bytes", __func__,
7816                      sizeof(*request));
7817                 error = 1;
7818                 goto bailout;
7819         }
7820
7821         response = malloc(sizeof(*response));
7822         if (response == NULL) {
7823                 warn("%s: unable to allocate %zd bytes", __func__,
7824                      sizeof(*response));
7825                 error = 1;
7826                 goto bailout;
7827         }
7828
7829 try_long:
7830         smp_report_general(&ccb->smpio,
7831                            retry_count,
7832                            /*cbfcnp*/ NULL,
7833                            request,
7834                            /*request_len*/ sizeof(*request),
7835                            (uint8_t *)response,
7836                            /*response_len*/ sizeof(*response),
7837                            /*long_response*/ long_response,
7838                            timeout);
7839
7840         if (((retval = cam_send_ccb(device, ccb)) < 0)
7841          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7842                 const char warnstr[] = "error sending command";
7843
7844                 if (retval < 0)
7845                         warn(warnstr);
7846                 else
7847                         warnx(warnstr);
7848
7849                 if (arglist & CAM_ARG_VERBOSE) {
7850                         cam_error_print(device, ccb, CAM_ESF_ALL,
7851                                         CAM_EPF_ALL, stderr);
7852                 }
7853                 error = 1;
7854                 goto bailout;
7855         }
7856
7857         /*
7858          * If the device supports the long response bit, try again and see
7859          * if we can get all of the data.
7860          */
7861         if ((response->long_response & SMP_RG_LONG_RESPONSE)
7862          && (long_response == 0)) {
7863                 ccb->ccb_h.status = CAM_REQ_INPROG;
7864                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7865                 long_response = 1;
7866                 goto try_long;
7867         }
7868
7869         /*
7870          * XXX KDM detect and decode SMP errors here.
7871          */
7872         sb = sbuf_new_auto();
7873         if (sb == NULL) {
7874                 warnx("%s: error allocating sbuf", __func__);
7875                 goto bailout;
7876         }
7877
7878         smp_report_general_sbuf(response, sizeof(*response), sb);
7879
7880         if (sbuf_finish(sb) != 0) {
7881                 warnx("%s: sbuf_finish", __func__);
7882                 goto bailout;
7883         }
7884
7885         printf("%s", sbuf_data(sb));
7886
7887 bailout:
7888         if (ccb != NULL)
7889                 cam_freeccb(ccb);
7890
7891         if (request != NULL)
7892                 free(request);
7893
7894         if (response != NULL)
7895                 free(response);
7896
7897         if (sb != NULL)
7898                 sbuf_delete(sb);
7899
7900         return (error);
7901 }
7902
7903 static struct camcontrol_opts phy_ops[] = {
7904         {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7905         {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7906         {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7907         {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7908         {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7909         {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7910         {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7911         {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7912         {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7913         {NULL, 0, 0, NULL}
7914 };
7915
7916 static int
7917 smpphycontrol(struct cam_device *device, int argc, char **argv,
7918               char *combinedopt, int retry_count, int timeout)
7919 {
7920         union ccb *ccb;
7921         struct smp_phy_control_request *request = NULL;
7922         struct smp_phy_control_response *response = NULL;
7923         int long_response = 0;
7924         int retval = 0;
7925         int phy = -1;
7926         uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7927         int phy_op_set = 0;
7928         uint64_t attached_dev_name = 0;
7929         int dev_name_set = 0;
7930         uint32_t min_plr = 0, max_plr = 0;
7931         uint32_t pp_timeout_val = 0;
7932         int slumber_partial = 0;
7933         int set_pp_timeout_val = 0;
7934         int c;
7935
7936         /*
7937          * Note that at the moment we don't support sending SMP CCBs to
7938          * devices that aren't probed by CAM.
7939          */
7940         ccb = cam_getccb(device);
7941         if (ccb == NULL) {
7942                 warnx("%s: error allocating CCB", __func__);
7943                 return (1);
7944         }
7945
7946         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7947
7948         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7949                 switch (c) {
7950                 case 'a':
7951                 case 'A':
7952                 case 's':
7953                 case 'S': {
7954                         int enable = -1;
7955
7956                         if (strcasecmp(optarg, "enable") == 0)
7957                                 enable = 1;
7958                         else if (strcasecmp(optarg, "disable") == 0)
7959                                 enable = 2;
7960                         else {
7961                                 warnx("%s: Invalid argument %s", __func__,
7962                                       optarg);
7963                                 retval = 1;
7964                                 goto bailout;
7965                         }
7966                         switch (c) {
7967                         case 's':
7968                                 slumber_partial |= enable <<
7969                                                    SMP_PC_SAS_SLUMBER_SHIFT;
7970                                 break;
7971                         case 'S':
7972                                 slumber_partial |= enable <<
7973                                                    SMP_PC_SAS_PARTIAL_SHIFT;
7974                                 break;
7975                         case 'a':
7976                                 slumber_partial |= enable <<
7977                                                    SMP_PC_SATA_SLUMBER_SHIFT;
7978                                 break;
7979                         case 'A':
7980                                 slumber_partial |= enable <<
7981                                                    SMP_PC_SATA_PARTIAL_SHIFT;
7982                                 break;
7983                         default:
7984                                 warnx("%s: programmer error", __func__);
7985                                 retval = 1;
7986                                 goto bailout;
7987                                 break; /*NOTREACHED*/
7988                         }
7989                         break;
7990                 }
7991                 case 'd':
7992                         attached_dev_name = (uintmax_t)strtoumax(optarg,
7993                                                                  NULL,0);
7994                         dev_name_set = 1;
7995                         break;
7996                 case 'l':
7997                         long_response = 1;
7998                         break;
7999                 case 'm':
8000                         /*
8001                          * We don't do extensive checking here, so this
8002                          * will continue to work when new speeds come out.
8003                          */
8004                         min_plr = strtoul(optarg, NULL, 0);
8005                         if ((min_plr == 0)
8006                          || (min_plr > 0xf)) {
8007                                 warnx("%s: invalid link rate %x",
8008                                       __func__, min_plr);
8009                                 retval = 1;
8010                                 goto bailout;
8011                         }
8012                         break;
8013                 case 'M':
8014                         /*
8015                          * We don't do extensive checking here, so this
8016                          * will continue to work when new speeds come out.
8017                          */
8018                         max_plr = strtoul(optarg, NULL, 0);
8019                         if ((max_plr == 0)
8020                          || (max_plr > 0xf)) {
8021                                 warnx("%s: invalid link rate %x",
8022                                       __func__, max_plr);
8023                                 retval = 1;
8024                                 goto bailout;
8025                         }
8026                         break;
8027                 case 'o': {
8028                         camcontrol_optret optreturn;
8029                         cam_argmask argnums;
8030                         const char *subopt;
8031
8032                         if (phy_op_set != 0) {
8033                                 warnx("%s: only one phy operation argument "
8034                                       "(-o) allowed", __func__);
8035                                 retval = 1;
8036                                 goto bailout;
8037                         }
8038
8039                         phy_op_set = 1;
8040
8041                         /*
8042                          * Allow the user to specify the phy operation
8043                          * numerically, as well as with a name.  This will
8044                          * future-proof it a bit, so options that are added
8045                          * in future specs can be used.
8046                          */
8047                         if (isdigit(optarg[0])) {
8048                                 phy_operation = strtoul(optarg, NULL, 0);
8049                                 if ((phy_operation == 0)
8050                                  || (phy_operation > 0xff)) {
8051                                         warnx("%s: invalid phy operation %#x",
8052                                               __func__, phy_operation);
8053                                         retval = 1;
8054                                         goto bailout;
8055                                 }
8056                                 break;
8057                         }
8058                         optreturn = getoption(phy_ops, optarg, &phy_operation,
8059                                               &argnums, &subopt);
8060
8061                         if (optreturn == CC_OR_AMBIGUOUS) {
8062                                 warnx("%s: ambiguous option %s", __func__,
8063                                       optarg);
8064                                 usage(0);
8065                                 retval = 1;
8066                                 goto bailout;
8067                         } else if (optreturn == CC_OR_NOT_FOUND) {
8068                                 warnx("%s: option %s not found", __func__,
8069                                       optarg);
8070                                 usage(0);
8071                                 retval = 1;
8072                                 goto bailout;
8073                         }
8074                         break;
8075                 }
8076                 case 'p':
8077                         phy = atoi(optarg);
8078                         break;
8079                 case 'T':
8080                         pp_timeout_val = strtoul(optarg, NULL, 0);
8081                         if (pp_timeout_val > 15) {
8082                                 warnx("%s: invalid partial pathway timeout "
8083                                       "value %u, need a value less than 16",
8084                                       __func__, pp_timeout_val);
8085                                 retval = 1;
8086                                 goto bailout;
8087                         }
8088                         set_pp_timeout_val = 1;
8089                         break;
8090                 default:
8091                         break;
8092                 }
8093         }
8094
8095         if (phy == -1) {
8096                 warnx("%s: a PHY (-p phy) argument is required",__func__);
8097                 retval = 1;
8098                 goto bailout;
8099         }
8100
8101         if (((dev_name_set != 0)
8102           && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
8103          || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
8104           && (dev_name_set == 0))) {
8105                 warnx("%s: -d name and -o setdevname arguments both "
8106                       "required to set device name", __func__);
8107                 retval = 1;
8108                 goto bailout;
8109         }
8110
8111         request = malloc(sizeof(*request));
8112         if (request == NULL) {
8113                 warn("%s: unable to allocate %zd bytes", __func__,
8114                      sizeof(*request));
8115                 retval = 1;
8116                 goto bailout;
8117         }
8118
8119         response = malloc(sizeof(*response));
8120         if (response == NULL) {
8121                 warn("%s: unable to allocate %zd bytes", __func__,
8122                      sizeof(*response));
8123                 retval = 1;
8124                 goto bailout;
8125         }
8126
8127         smp_phy_control(&ccb->smpio,
8128                         retry_count,
8129                         /*cbfcnp*/ NULL,
8130                         request,
8131                         sizeof(*request),
8132                         (uint8_t *)response,
8133                         sizeof(*response),
8134                         long_response,
8135                         /*expected_exp_change_count*/ 0,
8136                         phy,
8137                         phy_operation,
8138                         (set_pp_timeout_val != 0) ? 1 : 0,
8139                         attached_dev_name,
8140                         min_plr,
8141                         max_plr,
8142                         slumber_partial,
8143                         pp_timeout_val,
8144                         timeout);
8145
8146         if (((retval = cam_send_ccb(device, ccb)) < 0)
8147          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8148                 const char warnstr[] = "error sending command";
8149
8150                 if (retval < 0)
8151                         warn(warnstr);
8152                 else
8153                         warnx(warnstr);
8154
8155                 if (arglist & CAM_ARG_VERBOSE) {
8156                         /*
8157                          * Use CAM_EPF_NORMAL so we only get one line of
8158                          * SMP command decoding.
8159                          */
8160                         cam_error_print(device, ccb, CAM_ESF_ALL,
8161                                         CAM_EPF_NORMAL, stderr);
8162                 }
8163                 retval = 1;
8164                 goto bailout;
8165         }
8166
8167         /* XXX KDM print out something here for success? */
8168 bailout:
8169         if (ccb != NULL)
8170                 cam_freeccb(ccb);
8171
8172         if (request != NULL)
8173                 free(request);
8174
8175         if (response != NULL)
8176                 free(response);
8177
8178         return (retval);
8179 }
8180
8181 static int
8182 smpmaninfo(struct cam_device *device, int argc, char **argv,
8183            char *combinedopt, int retry_count, int timeout)
8184 {
8185         union ccb *ccb;
8186         struct smp_report_manuf_info_request request;
8187         struct smp_report_manuf_info_response response;
8188         struct sbuf *sb = NULL;
8189         int long_response = 0;
8190         int retval = 0;
8191         int c;
8192
8193         /*
8194          * Note that at the moment we don't support sending SMP CCBs to
8195          * devices that aren't probed by CAM.
8196          */
8197         ccb = cam_getccb(device);
8198         if (ccb == NULL) {
8199                 warnx("%s: error allocating CCB", __func__);
8200                 return (1);
8201         }
8202
8203         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8204
8205         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8206                 switch (c) {
8207                 case 'l':
8208                         long_response = 1;
8209                         break;
8210                 default:
8211                         break;
8212                 }
8213         }
8214         bzero(&request, sizeof(request));
8215         bzero(&response, sizeof(response));
8216
8217         smp_report_manuf_info(&ccb->smpio,
8218                               retry_count,
8219                               /*cbfcnp*/ NULL,
8220                               &request,
8221                               sizeof(request),
8222                               (uint8_t *)&response,
8223                               sizeof(response),
8224                               long_response,
8225                               timeout);
8226
8227         if (((retval = cam_send_ccb(device, ccb)) < 0)
8228          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8229                 const char warnstr[] = "error sending command";
8230
8231                 if (retval < 0)
8232                         warn(warnstr);
8233                 else
8234                         warnx(warnstr);
8235
8236                 if (arglist & CAM_ARG_VERBOSE) {
8237                         cam_error_print(device, ccb, CAM_ESF_ALL,
8238                                         CAM_EPF_ALL, stderr);
8239                 }
8240                 retval = 1;
8241                 goto bailout;
8242         }
8243
8244         sb = sbuf_new_auto();
8245         if (sb == NULL) {
8246                 warnx("%s: error allocating sbuf", __func__);
8247                 goto bailout;
8248         }
8249
8250         smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
8251
8252         if (sbuf_finish(sb) != 0) {
8253                 warnx("%s: sbuf_finish", __func__);
8254                 goto bailout;
8255         }
8256
8257         printf("%s", sbuf_data(sb));
8258
8259 bailout:
8260
8261         if (ccb != NULL)
8262                 cam_freeccb(ccb);
8263
8264         if (sb != NULL)
8265                 sbuf_delete(sb);
8266
8267         return (retval);
8268 }
8269
8270 static int
8271 getdevid(struct cam_devitem *item)
8272 {
8273         int retval = 0;
8274         union ccb *ccb = NULL;
8275
8276         struct cam_device *dev;
8277
8278         dev = cam_open_btl(item->dev_match.path_id,
8279                            item->dev_match.target_id,
8280                            item->dev_match.target_lun, O_RDWR, NULL);
8281
8282         if (dev == NULL) {
8283                 warnx("%s", cam_errbuf);
8284                 retval = 1;
8285                 goto bailout;
8286         }
8287
8288         item->device_id_len = 0;
8289
8290         ccb = cam_getccb(dev);
8291         if (ccb == NULL) {
8292                 warnx("%s: error allocating CCB", __func__);
8293                 retval = 1;
8294                 goto bailout;
8295         }
8296
8297         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai);
8298
8299         /*
8300          * On the first try, we just probe for the size of the data, and
8301          * then allocate that much memory and try again.
8302          */
8303 retry:
8304         ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
8305         ccb->ccb_h.flags = CAM_DIR_IN;
8306         ccb->cdai.flags = CDAI_FLAG_NONE;
8307         ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
8308         ccb->cdai.bufsiz = item->device_id_len;
8309         if (item->device_id_len != 0)
8310                 ccb->cdai.buf = (uint8_t *)item->device_id;
8311
8312         if (cam_send_ccb(dev, ccb) < 0) {
8313                 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
8314                 retval = 1;
8315                 goto bailout;
8316         }
8317
8318         if (ccb->ccb_h.status != CAM_REQ_CMP) {
8319                 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
8320                 retval = 1;
8321                 goto bailout;
8322         }
8323
8324         if (item->device_id_len == 0) {
8325                 /*
8326                  * This is our first time through.  Allocate the buffer,
8327                  * and then go back to get the data.
8328                  */
8329                 if (ccb->cdai.provsiz == 0) {
8330                         warnx("%s: invalid .provsiz field returned with "
8331                              "XPT_GDEV_ADVINFO CCB", __func__);
8332                         retval = 1;
8333                         goto bailout;
8334                 }
8335                 item->device_id_len = ccb->cdai.provsiz;
8336                 item->device_id = malloc(item->device_id_len);
8337                 if (item->device_id == NULL) {
8338                         warn("%s: unable to allocate %d bytes", __func__,
8339                              item->device_id_len);
8340                         retval = 1;
8341                         goto bailout;
8342                 }
8343                 ccb->ccb_h.status = CAM_REQ_INPROG;
8344                 goto retry;
8345         }
8346
8347 bailout:
8348         if (dev != NULL)
8349                 cam_close_device(dev);
8350
8351         if (ccb != NULL)
8352                 cam_freeccb(ccb);
8353
8354         return (retval);
8355 }
8356
8357 /*
8358  * XXX KDM merge this code with getdevtree()?
8359  */
8360 static int
8361 buildbusdevlist(struct cam_devlist *devlist)
8362 {
8363         union ccb ccb;
8364         int bufsize, fd = -1;
8365         struct dev_match_pattern *patterns;
8366         struct cam_devitem *item = NULL;
8367         int skip_device = 0;
8368         int retval = 0;
8369
8370         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
8371                 warn("couldn't open %s", XPT_DEVICE);
8372                 return (1);
8373         }
8374
8375         bzero(&ccb, sizeof(union ccb));
8376
8377         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
8378         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
8379         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
8380
8381         ccb.ccb_h.func_code = XPT_DEV_MATCH;
8382         bufsize = sizeof(struct dev_match_result) * 100;
8383         ccb.cdm.match_buf_len = bufsize;
8384         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
8385         if (ccb.cdm.matches == NULL) {
8386                 warnx("can't malloc memory for matches");
8387                 close(fd);
8388                 return (1);
8389         }
8390         ccb.cdm.num_matches = 0;
8391         ccb.cdm.num_patterns = 2;
8392         ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
8393                 ccb.cdm.num_patterns;
8394
8395         patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
8396         if (patterns == NULL) {
8397                 warnx("can't malloc memory for patterns");
8398                 retval = 1;
8399                 goto bailout;
8400         }
8401
8402         ccb.cdm.patterns = patterns;
8403         bzero(patterns, ccb.cdm.pattern_buf_len);
8404
8405         patterns[0].type = DEV_MATCH_DEVICE;
8406         patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
8407         patterns[0].pattern.device_pattern.path_id = devlist->path_id;
8408         patterns[1].type = DEV_MATCH_PERIPH;
8409         patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
8410         patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
8411
8412         /*
8413          * We do the ioctl multiple times if necessary, in case there are
8414          * more than 100 nodes in the EDT.
8415          */
8416         do {
8417                 unsigned int i;
8418
8419                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
8420                         warn("error sending CAMIOCOMMAND ioctl");
8421                         retval = 1;
8422                         goto bailout;
8423                 }
8424
8425                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
8426                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
8427                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
8428                         warnx("got CAM error %#x, CDM error %d\n",
8429                               ccb.ccb_h.status, ccb.cdm.status);
8430                         retval = 1;
8431                         goto bailout;
8432                 }
8433
8434                 for (i = 0; i < ccb.cdm.num_matches; i++) {
8435                         switch (ccb.cdm.matches[i].type) {
8436                         case DEV_MATCH_DEVICE: {
8437                                 struct device_match_result *dev_result;
8438
8439                                 dev_result =
8440                                      &ccb.cdm.matches[i].result.device_result;
8441
8442                                 if (dev_result->flags &
8443                                     DEV_RESULT_UNCONFIGURED) {
8444                                         skip_device = 1;
8445                                         break;
8446                                 } else
8447                                         skip_device = 0;
8448
8449                                 item = malloc(sizeof(*item));
8450                                 if (item == NULL) {
8451                                         warn("%s: unable to allocate %zd bytes",
8452                                              __func__, sizeof(*item));
8453                                         retval = 1;
8454                                         goto bailout;
8455                                 }
8456                                 bzero(item, sizeof(*item));
8457                                 bcopy(dev_result, &item->dev_match,
8458                                       sizeof(*dev_result));
8459                                 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
8460                                                    links);
8461
8462                                 if (getdevid(item) != 0) {
8463                                         retval = 1;
8464                                         goto bailout;
8465                                 }
8466                                 break;
8467                         }
8468                         case DEV_MATCH_PERIPH: {
8469                                 struct periph_match_result *periph_result;
8470
8471                                 periph_result =
8472                                       &ccb.cdm.matches[i].result.periph_result;
8473
8474                                 if (skip_device != 0)
8475                                         break;
8476                                 item->num_periphs++;
8477                                 item->periph_matches = realloc(
8478                                         item->periph_matches,
8479                                         item->num_periphs *
8480                                         sizeof(struct periph_match_result));
8481                                 if (item->periph_matches == NULL) {
8482                                         warn("%s: error allocating periph "
8483                                              "list", __func__);
8484                                         retval = 1;
8485                                         goto bailout;
8486                                 }
8487                                 bcopy(periph_result, &item->periph_matches[
8488                                       item->num_periphs - 1],
8489                                       sizeof(*periph_result));
8490                                 break;
8491                         }
8492                         default:
8493                                 fprintf(stderr, "%s: unexpected match "
8494                                         "type %d\n", __func__,
8495                                         ccb.cdm.matches[i].type);
8496                                 retval = 1;
8497                                 goto bailout;
8498                                 break; /*NOTREACHED*/
8499                         }
8500                 }
8501         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
8502                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
8503 bailout:
8504
8505         if (fd != -1)
8506                 close(fd);
8507
8508         free(patterns);
8509
8510         free(ccb.cdm.matches);
8511
8512         if (retval != 0)
8513                 freebusdevlist(devlist);
8514
8515         return (retval);
8516 }
8517
8518 static void
8519 freebusdevlist(struct cam_devlist *devlist)
8520 {
8521         struct cam_devitem *item, *item2;
8522
8523         STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
8524                 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
8525                               links);
8526                 free(item->device_id);
8527                 free(item->periph_matches);
8528                 free(item);
8529         }
8530 }
8531
8532 static struct cam_devitem *
8533 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
8534 {
8535         struct cam_devitem *item;
8536
8537         STAILQ_FOREACH(item, &devlist->dev_queue, links) {
8538                 struct scsi_vpd_id_descriptor *idd;
8539
8540                 /*
8541                  * XXX KDM look for LUN IDs as well?
8542                  */
8543                 idd = scsi_get_devid(item->device_id,
8544                                            item->device_id_len,
8545                                            scsi_devid_is_sas_target);
8546                 if (idd == NULL)
8547                         continue;
8548
8549                 if (scsi_8btou64(idd->identifier) == sasaddr)
8550                         return (item);
8551         }
8552
8553         return (NULL);
8554 }
8555
8556 static int
8557 smpphylist(struct cam_device *device, int argc, char **argv,
8558            char *combinedopt, int retry_count, int timeout)
8559 {
8560         struct smp_report_general_request *rgrequest = NULL;
8561         struct smp_report_general_response *rgresponse = NULL;
8562         struct smp_discover_request *disrequest = NULL;
8563         struct smp_discover_response *disresponse = NULL;
8564         struct cam_devlist devlist;
8565         union ccb *ccb;
8566         int long_response = 0;
8567         int num_phys = 0;
8568         int quiet = 0;
8569         int retval;
8570         int i, c;
8571
8572         /*
8573          * Note that at the moment we don't support sending SMP CCBs to
8574          * devices that aren't probed by CAM.
8575          */
8576         ccb = cam_getccb(device);
8577         if (ccb == NULL) {
8578                 warnx("%s: error allocating CCB", __func__);
8579                 return (1);
8580         }
8581
8582         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8583         STAILQ_INIT(&devlist.dev_queue);
8584
8585         rgrequest = malloc(sizeof(*rgrequest));
8586         if (rgrequest == NULL) {
8587                 warn("%s: unable to allocate %zd bytes", __func__,
8588                      sizeof(*rgrequest));
8589                 retval = 1;
8590                 goto bailout;
8591         }
8592
8593         rgresponse = malloc(sizeof(*rgresponse));
8594         if (rgresponse == NULL) {
8595                 warn("%s: unable to allocate %zd bytes", __func__,
8596                      sizeof(*rgresponse));
8597                 retval = 1;
8598                 goto bailout;
8599         }
8600
8601         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8602                 switch (c) {
8603                 case 'l':
8604                         long_response = 1;
8605                         break;
8606                 case 'q':
8607                         quiet = 1;
8608                         break;
8609                 default:
8610                         break;
8611                 }
8612         }
8613
8614         smp_report_general(&ccb->smpio,
8615                            retry_count,
8616                            /*cbfcnp*/ NULL,
8617                            rgrequest,
8618                            /*request_len*/ sizeof(*rgrequest),
8619                            (uint8_t *)rgresponse,
8620                            /*response_len*/ sizeof(*rgresponse),
8621                            /*long_response*/ long_response,
8622                            timeout);
8623
8624         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8625
8626         if (((retval = cam_send_ccb(device, ccb)) < 0)
8627          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8628                 const char warnstr[] = "error sending command";
8629
8630                 if (retval < 0)
8631                         warn(warnstr);
8632                 else
8633                         warnx(warnstr);
8634
8635                 if (arglist & CAM_ARG_VERBOSE) {
8636                         cam_error_print(device, ccb, CAM_ESF_ALL,
8637                                         CAM_EPF_ALL, stderr);
8638                 }
8639                 retval = 1;
8640                 goto bailout;
8641         }
8642
8643         num_phys = rgresponse->num_phys;
8644
8645         if (num_phys == 0) {
8646                 if (quiet == 0)
8647                         fprintf(stdout, "%s: No Phys reported\n", __func__);
8648                 retval = 1;
8649                 goto bailout;
8650         }
8651
8652         devlist.path_id = device->path_id;
8653
8654         retval = buildbusdevlist(&devlist);
8655         if (retval != 0)
8656                 goto bailout;
8657
8658         if (quiet == 0) {
8659                 fprintf(stdout, "%d PHYs:\n", num_phys);
8660                 fprintf(stdout, "PHY  Attached SAS Address\n");
8661         }
8662
8663         disrequest = malloc(sizeof(*disrequest));
8664         if (disrequest == NULL) {
8665                 warn("%s: unable to allocate %zd bytes", __func__,
8666                      sizeof(*disrequest));
8667                 retval = 1;
8668                 goto bailout;
8669         }
8670
8671         disresponse = malloc(sizeof(*disresponse));
8672         if (disresponse == NULL) {
8673                 warn("%s: unable to allocate %zd bytes", __func__,
8674                      sizeof(*disresponse));
8675                 retval = 1;
8676                 goto bailout;
8677         }
8678
8679         for (i = 0; i < num_phys; i++) {
8680                 struct cam_devitem *item;
8681                 struct device_match_result *dev_match;
8682                 char vendor[16], product[48], revision[16];
8683                 char tmpstr[256];
8684                 int j;
8685
8686                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8687
8688                 ccb->ccb_h.status = CAM_REQ_INPROG;
8689                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8690
8691                 smp_discover(&ccb->smpio,
8692                              retry_count,
8693                              /*cbfcnp*/ NULL,
8694                              disrequest,
8695                              sizeof(*disrequest),
8696                              (uint8_t *)disresponse,
8697                              sizeof(*disresponse),
8698                              long_response,
8699                              /*ignore_zone_group*/ 0,
8700                              /*phy*/ i,
8701                              timeout);
8702
8703                 if (((retval = cam_send_ccb(device, ccb)) < 0)
8704                  || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
8705                   && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
8706                         const char warnstr[] = "error sending command";
8707
8708                         if (retval < 0)
8709                                 warn(warnstr);
8710                         else
8711                                 warnx(warnstr);
8712
8713                         if (arglist & CAM_ARG_VERBOSE) {
8714                                 cam_error_print(device, ccb, CAM_ESF_ALL,
8715                                                 CAM_EPF_ALL, stderr);
8716                         }
8717                         retval = 1;
8718                         goto bailout;
8719                 }
8720
8721                 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
8722                         if (quiet == 0)
8723                                 fprintf(stdout, "%3d  <vacant>\n", i);
8724                         continue;
8725                 }
8726
8727                 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
8728                         item = NULL;
8729                 } else {
8730                         item = findsasdevice(&devlist,
8731                             scsi_8btou64(disresponse->attached_sas_address));
8732                 }
8733
8734                 if ((quiet == 0)
8735                  || (item != NULL)) {
8736                         fprintf(stdout, "%3d  0x%016jx", i,
8737                                 (uintmax_t)scsi_8btou64(
8738                                 disresponse->attached_sas_address));
8739                         if (item == NULL) {
8740                                 fprintf(stdout, "\n");
8741                                 continue;
8742                         }
8743                 } else if (quiet != 0)
8744                         continue;
8745
8746                 dev_match = &item->dev_match;
8747
8748                 if (dev_match->protocol == PROTO_SCSI) {
8749                         cam_strvis(vendor, dev_match->inq_data.vendor,
8750                                    sizeof(dev_match->inq_data.vendor),
8751                                    sizeof(vendor));
8752                         cam_strvis(product, dev_match->inq_data.product,
8753                                    sizeof(dev_match->inq_data.product),
8754                                    sizeof(product));
8755                         cam_strvis(revision, dev_match->inq_data.revision,
8756                                    sizeof(dev_match->inq_data.revision),
8757                                    sizeof(revision));
8758                         sprintf(tmpstr, "<%s %s %s>", vendor, product,
8759                                 revision);
8760                 } else if ((dev_match->protocol == PROTO_ATA)
8761                         || (dev_match->protocol == PROTO_SATAPM)) {
8762                         cam_strvis(product, dev_match->ident_data.model,
8763                                    sizeof(dev_match->ident_data.model),
8764                                    sizeof(product));
8765                         cam_strvis(revision, dev_match->ident_data.revision,
8766                                    sizeof(dev_match->ident_data.revision),
8767                                    sizeof(revision));
8768                         sprintf(tmpstr, "<%s %s>", product, revision);
8769                 } else {
8770                         sprintf(tmpstr, "<>");
8771                 }
8772                 fprintf(stdout, "   %-33s ", tmpstr);
8773
8774                 /*
8775                  * If we have 0 periphs, that's a bug...
8776                  */
8777                 if (item->num_periphs == 0) {
8778                         fprintf(stdout, "\n");
8779                         continue;
8780                 }
8781
8782                 fprintf(stdout, "(");
8783                 for (j = 0; j < item->num_periphs; j++) {
8784                         if (j > 0)
8785                                 fprintf(stdout, ",");
8786
8787                         fprintf(stdout, "%s%d",
8788                                 item->periph_matches[j].periph_name,
8789                                 item->periph_matches[j].unit_number);
8790
8791                 }
8792                 fprintf(stdout, ")\n");
8793         }
8794 bailout:
8795         if (ccb != NULL)
8796                 cam_freeccb(ccb);
8797
8798         free(rgrequest);
8799
8800         free(rgresponse);
8801
8802         free(disrequest);
8803
8804         free(disresponse);
8805
8806         freebusdevlist(&devlist);
8807
8808         return (retval);
8809 }
8810
8811 static int
8812 atapm(struct cam_device *device, int argc, char **argv,
8813                  char *combinedopt, int retry_count, int timeout)
8814 {
8815         union ccb *ccb;
8816         int retval = 0;
8817         int t = -1;
8818         int c;
8819         u_char cmd, sc;
8820
8821         ccb = cam_getccb(device);
8822
8823         if (ccb == NULL) {
8824                 warnx("%s: error allocating ccb", __func__);
8825                 return (1);
8826         }
8827
8828         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8829                 switch (c) {
8830                 case 't':
8831                         t = atoi(optarg);
8832                         break;
8833                 default:
8834                         break;
8835                 }
8836         }
8837         if (strcmp(argv[1], "idle") == 0) {
8838                 if (t == -1)
8839                         cmd = ATA_IDLE_IMMEDIATE;
8840                 else
8841                         cmd = ATA_IDLE_CMD;
8842         } else if (strcmp(argv[1], "standby") == 0) {
8843                 if (t == -1)
8844                         cmd = ATA_STANDBY_IMMEDIATE;
8845                 else
8846                         cmd = ATA_STANDBY_CMD;
8847         } else {
8848                 cmd = ATA_SLEEP;
8849                 t = -1;
8850         }
8851
8852         if (t < 0)
8853                 sc = 0;
8854         else if (t <= (240 * 5))
8855                 sc = (t + 4) / 5;
8856         else if (t <= (252 * 5))
8857                 /* special encoding for 21 minutes */
8858                 sc = 252;
8859         else if (t <= (11 * 30 * 60))
8860                 sc = (t - 1) / (30 * 60) + 241;
8861         else
8862                 sc = 253;
8863
8864         retval = ata_do_28bit_cmd(device,
8865             ccb,
8866             /*retries*/retry_count,
8867             /*flags*/CAM_DIR_NONE,
8868             /*protocol*/AP_PROTO_NON_DATA,
8869             /*tag_action*/MSG_SIMPLE_Q_TAG,
8870             /*command*/cmd,
8871             /*features*/0,
8872             /*lba*/0,
8873             /*sector_count*/sc,
8874             /*data_ptr*/NULL,
8875             /*dxfer_len*/0,
8876             /*timeout*/timeout ? timeout : 30 * 1000,
8877             /*quiet*/1);
8878
8879         cam_freeccb(ccb);
8880         return (retval);
8881 }
8882
8883 static int
8884 ataaxm(struct cam_device *device, int argc, char **argv,
8885                  char *combinedopt, int retry_count, int timeout)
8886 {
8887         union ccb *ccb;
8888         int retval = 0;
8889         int l = -1;
8890         int c;
8891         u_char cmd, sc;
8892
8893         ccb = cam_getccb(device);
8894
8895         if (ccb == NULL) {
8896                 warnx("%s: error allocating ccb", __func__);
8897                 return (1);
8898         }
8899
8900         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8901                 switch (c) {
8902                 case 'l':
8903                         l = atoi(optarg);
8904                         break;
8905                 default:
8906                         break;
8907                 }
8908         }
8909         sc = 0;
8910         if (strcmp(argv[1], "apm") == 0) {
8911                 if (l == -1)
8912                         cmd = 0x85;
8913                 else {
8914                         cmd = 0x05;
8915                         sc = l;
8916                 }
8917         } else /* aam */ {
8918                 if (l == -1)
8919                         cmd = 0xC2;
8920                 else {
8921                         cmd = 0x42;
8922                         sc = l;
8923                 }
8924         }
8925
8926         retval = ata_do_28bit_cmd(device,
8927             ccb,
8928             /*retries*/retry_count,
8929             /*flags*/CAM_DIR_NONE,
8930             /*protocol*/AP_PROTO_NON_DATA,
8931             /*tag_action*/MSG_SIMPLE_Q_TAG,
8932             /*command*/ATA_SETFEATURES,
8933             /*features*/cmd,
8934             /*lba*/0,
8935             /*sector_count*/sc,
8936             /*data_ptr*/NULL,
8937             /*dxfer_len*/0,
8938             /*timeout*/timeout ? timeout : 30 * 1000,
8939             /*quiet*/1);
8940
8941         cam_freeccb(ccb);
8942         return (retval);
8943 }
8944
8945 int
8946 scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8947                int show_sa_errors, int sa_set, int service_action,
8948                int timeout_desc, int task_attr, int retry_count, int timeout,
8949                int verbosemode, uint32_t *fill_len, uint8_t **data_ptr)
8950 {
8951         union ccb *ccb = NULL;
8952         uint8_t *buf = NULL;
8953         uint32_t alloc_len = 0, num_opcodes;
8954         uint32_t valid_len = 0;
8955         uint32_t avail_len = 0;
8956         struct scsi_report_supported_opcodes_all *all_hdr;
8957         struct scsi_report_supported_opcodes_one *one;
8958         int options = 0;
8959         int retval = 0;
8960
8961         /*
8962          * Make it clear that we haven't yet allocated or filled anything.
8963          */
8964         *fill_len = 0;
8965         *data_ptr = NULL;
8966
8967         ccb = cam_getccb(device);
8968         if (ccb == NULL) {
8969                 warnx("couldn't allocate CCB");
8970                 retval = 1;
8971                 goto bailout;
8972         }
8973
8974         /* cam_getccb cleans up the header, caller has to zero the payload */
8975         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8976
8977         if (opcode_set != 0) {
8978                 options |= RSO_OPTIONS_OC;
8979                 num_opcodes = 1;
8980                 alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8981         } else {
8982                 num_opcodes = 256;
8983                 alloc_len = sizeof(*all_hdr) + (num_opcodes *
8984                     sizeof(struct scsi_report_supported_opcodes_descr));
8985         }
8986
8987         if (timeout_desc != 0) {
8988                 options |= RSO_RCTD;
8989                 alloc_len += num_opcodes *
8990                     sizeof(struct scsi_report_supported_opcodes_timeout);
8991         }
8992
8993         if (sa_set != 0) {
8994                 options |= RSO_OPTIONS_OC_SA;
8995                 if (show_sa_errors != 0)
8996                         options &= ~RSO_OPTIONS_OC;
8997         }
8998
8999 retry_alloc:
9000         if (buf != NULL) {
9001                 free(buf);
9002                 buf = NULL;
9003         }
9004
9005         buf = malloc(alloc_len);
9006         if (buf == NULL) {
9007                 warn("Unable to allocate %u bytes", alloc_len);
9008                 retval = 1;
9009                 goto bailout;
9010         }
9011         bzero(buf, alloc_len);
9012
9013         scsi_report_supported_opcodes(&ccb->csio,
9014                                       /*retries*/ retry_count,
9015                                       /*cbfcnp*/ NULL,
9016                                       /*tag_action*/ task_attr,
9017                                       /*options*/ options,
9018                                       /*req_opcode*/ opcode,
9019                                       /*req_service_action*/ service_action,
9020                                       /*data_ptr*/ buf,
9021                                       /*dxfer_len*/ alloc_len,
9022                                       /*sense_len*/ SSD_FULL_SIZE,
9023                                       /*timeout*/ timeout ? timeout : 10000);
9024
9025         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
9026
9027         if (retry_count != 0)
9028                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
9029
9030         if (cam_send_ccb(device, ccb) < 0) {
9031                 perror("error sending REPORT SUPPORTED OPERATION CODES");
9032                 retval = 1;
9033                 goto bailout;
9034         }
9035
9036         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
9037                 if (verbosemode != 0)
9038                         cam_error_print(device, ccb, CAM_ESF_ALL,
9039                                         CAM_EPF_ALL, stderr);
9040                 retval = 1;
9041                 goto bailout;
9042         }
9043
9044         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
9045
9046         if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
9047          && (valid_len >= sizeof(*all_hdr))) {
9048                 all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
9049                 avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
9050         } else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
9051                 && (valid_len >= sizeof(*one))) {
9052                 uint32_t cdb_length;
9053
9054                 one = (struct scsi_report_supported_opcodes_one *)buf;
9055                 cdb_length = scsi_2btoul(one->cdb_length);
9056                 avail_len = sizeof(*one) + cdb_length;
9057                 if (one->support & RSO_ONE_CTDP) {
9058                         struct scsi_report_supported_opcodes_timeout *td;
9059
9060                         td = (struct scsi_report_supported_opcodes_timeout *)
9061                             &buf[avail_len];
9062                         if (valid_len >= (avail_len + sizeof(td->length))) {
9063                                 avail_len += scsi_2btoul(td->length) +
9064                                     sizeof(td->length);
9065                         } else {
9066                                 avail_len += sizeof(*td);
9067                         }
9068                 }
9069         }
9070
9071         /*
9072          * avail_len could be zero if we didn't get enough data back from
9073          * thet target to determine
9074          */
9075         if ((avail_len != 0)
9076          && (avail_len > valid_len)) {
9077                 alloc_len = avail_len;
9078                 goto retry_alloc;
9079         }
9080
9081         *fill_len = valid_len;
9082         *data_ptr = buf;
9083 bailout:
9084         if (retval != 0)
9085                 free(buf);
9086
9087         cam_freeccb(ccb);
9088
9089         return (retval);
9090 }
9091
9092 static int
9093 scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
9094                    int req_sa, uint8_t *buf, uint32_t valid_len)
9095 {
9096         struct scsi_report_supported_opcodes_one *one;
9097         struct scsi_report_supported_opcodes_timeout *td;
9098         uint32_t cdb_len = 0, td_len = 0;
9099         const char *op_desc = NULL;
9100         unsigned int i;
9101         int retval = 0;
9102
9103         one = (struct scsi_report_supported_opcodes_one *)buf;
9104
9105         /*
9106          * If we don't have the full single opcode descriptor, no point in
9107          * continuing.
9108          */
9109         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
9110             cdb_length)) {
9111                 warnx("Only %u bytes returned, not enough to verify support",
9112                       valid_len);
9113                 retval = 1;
9114                 goto bailout;
9115         }
9116
9117         op_desc = scsi_op_desc(req_opcode, &device->inq_data);
9118
9119         printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
9120                req_opcode);
9121         if (sa_set != 0)
9122                 printf(", SA 0x%x", req_sa);
9123         printf(": ");
9124
9125         switch (one->support & RSO_ONE_SUP_MASK) {
9126         case RSO_ONE_SUP_UNAVAIL:
9127                 printf("No command support information currently available\n");
9128                 break;
9129         case RSO_ONE_SUP_NOT_SUP:
9130                 printf("Command not supported\n");
9131                 retval = 1;
9132                 goto bailout;
9133                 break; /*NOTREACHED*/
9134         case RSO_ONE_SUP_AVAIL:
9135                 printf("Command is supported, complies with a SCSI standard\n");
9136                 break;
9137         case RSO_ONE_SUP_VENDOR:
9138                 printf("Command is supported, vendor-specific "
9139                        "implementation\n");
9140                 break;
9141         default:
9142                 printf("Unknown command support flags 0x%#x\n",
9143                        one->support & RSO_ONE_SUP_MASK);
9144                 break;
9145         }
9146
9147         /*
9148          * If we don't have the CDB length, it isn't exactly an error, the
9149          * command probably isn't supported.
9150          */
9151         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
9152             cdb_usage))
9153                 goto bailout;
9154
9155         cdb_len = scsi_2btoul(one->cdb_length);
9156
9157         /*
9158          * If our valid data doesn't include the full reported length,
9159          * return.  The caller should have detected this and adjusted his
9160          * allocation length to get all of the available data.
9161          */
9162         if (valid_len < sizeof(*one) + cdb_len) {
9163                 retval = 1;
9164                 goto bailout;
9165         }
9166
9167         /*
9168          * If all we have is the opcode, there is no point in printing out
9169          * the usage bitmap.
9170          */
9171         if (cdb_len <= 1) {
9172                 retval = 1;
9173                 goto bailout;
9174         }
9175
9176         printf("CDB usage bitmap:");
9177         for (i = 0; i < cdb_len; i++) {
9178                 printf(" %02x", one->cdb_usage[i]);
9179         }
9180         printf("\n");
9181
9182         /*
9183          * If we don't have a timeout descriptor, we're done.
9184          */
9185         if ((one->support & RSO_ONE_CTDP) == 0)
9186                 goto bailout;
9187
9188         /*
9189          * If we don't have enough valid length to include the timeout
9190          * descriptor length, we're done.
9191          */
9192         if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
9193                 goto bailout;
9194
9195         td = (struct scsi_report_supported_opcodes_timeout *)
9196             &buf[sizeof(*one) + cdb_len];
9197         td_len = scsi_2btoul(td->length);
9198         td_len += sizeof(td->length);
9199
9200         /*
9201          * If we don't have the full timeout descriptor, we're done.
9202          */
9203         if (td_len < sizeof(*td))
9204                 goto bailout;
9205
9206         /*
9207          * If we don't have enough valid length to contain the full timeout
9208          * descriptor, we're done.
9209          */
9210         if (valid_len < (sizeof(*one) + cdb_len + td_len))
9211                 goto bailout;
9212
9213         printf("Timeout information:\n");
9214         printf("Command-specific:    0x%02x\n", td->cmd_specific);
9215         printf("Nominal timeout:     %u seconds\n",
9216                scsi_4btoul(td->nominal_time));
9217         printf("Recommended timeout: %u seconds\n",
9218                scsi_4btoul(td->recommended_time));
9219
9220 bailout:
9221         return (retval);
9222 }
9223
9224 static int
9225 scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
9226                  uint32_t valid_len)
9227 {
9228         struct scsi_report_supported_opcodes_all *hdr;
9229         struct scsi_report_supported_opcodes_descr *desc;
9230         uint32_t avail_len = 0, used_len = 0;
9231         uint8_t *cur_ptr;
9232         int retval = 0;
9233
9234         if (valid_len < sizeof(*hdr)) {
9235                 warnx("%s: not enough returned data (%u bytes) opcode list",
9236                       __func__, valid_len);
9237                 retval = 1;
9238                 goto bailout;
9239         }
9240         hdr = (struct scsi_report_supported_opcodes_all *)buf;
9241         avail_len = scsi_4btoul(hdr->length);
9242         avail_len += sizeof(hdr->length);
9243         /*
9244          * Take the lesser of the amount of data the drive claims is
9245          * available, and the amount of data the HBA says was returned.
9246          */
9247         avail_len = MIN(avail_len, valid_len);
9248
9249         used_len = sizeof(hdr->length);
9250
9251         printf("%-6s %4s %8s ",
9252                "Opcode", "SA", "CDB len" );
9253
9254         if (td_req != 0)
9255                 printf("%5s %6s %6s ", "CS", "Nom", "Rec");
9256         printf(" Description\n");
9257
9258         while ((avail_len - used_len) > sizeof(*desc)) {
9259                 struct scsi_report_supported_opcodes_timeout *td;
9260                 uint32_t td_len;
9261                 const char *op_desc = NULL;
9262
9263                 cur_ptr = &buf[used_len];
9264                 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
9265
9266                 op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
9267                 if (op_desc == NULL)
9268                         op_desc = "UNKNOWN";
9269
9270                 printf("0x%02x   %#4x %8u ", desc->opcode,
9271                        scsi_2btoul(desc->service_action),
9272                        scsi_2btoul(desc->cdb_length));
9273
9274                 used_len += sizeof(*desc);
9275
9276                 if ((desc->flags & RSO_CTDP) == 0) {
9277                         printf(" %s\n", op_desc);
9278                         continue;
9279                 }
9280
9281                 /*
9282                  * If we don't have enough space to fit a timeout
9283                  * descriptor, then we're done.
9284                  */
9285                 if (avail_len - used_len < sizeof(*td)) {
9286                         used_len = avail_len;
9287                         printf(" %s\n", op_desc);
9288                         continue;
9289                 }
9290                 cur_ptr = &buf[used_len];
9291                 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
9292                 td_len = scsi_2btoul(td->length);
9293                 td_len += sizeof(td->length);
9294
9295                 used_len += td_len;
9296                 /*
9297                  * If the given timeout descriptor length is less than what
9298                  * we understand, skip it.
9299                  */
9300                 if (td_len < sizeof(*td)) {
9301                         printf(" %s\n", op_desc);
9302                         continue;
9303                 }
9304
9305                 printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
9306                        scsi_4btoul(td->nominal_time),
9307                        scsi_4btoul(td->recommended_time), op_desc);
9308         }
9309 bailout:
9310         return (retval);
9311 }
9312
9313 static int
9314 scsiopcodes(struct cam_device *device, int argc, char **argv,
9315             char *combinedopt, int task_attr, int retry_count, int timeout,
9316             int verbosemode)
9317 {
9318         int c;
9319         uint32_t opcode = 0, service_action = 0;
9320         int td_set = 0, opcode_set = 0, sa_set = 0;
9321         int show_sa_errors = 1;
9322         uint32_t valid_len = 0;
9323         uint8_t *buf = NULL;
9324         char *endptr;
9325         int retval = 0;
9326
9327         while ((c = getopt(argc, argv, combinedopt)) != -1) {
9328                 switch (c) {
9329                 case 'N':
9330                         show_sa_errors = 0;
9331                         break;
9332                 case 'o':
9333                         opcode = strtoul(optarg, &endptr, 0);
9334                         if (*endptr != '\0') {
9335                                 warnx("Invalid opcode \"%s\", must be a number",
9336                                       optarg);
9337                                 retval = 1;
9338                                 goto bailout;
9339                         }
9340                         if (opcode > 0xff) {
9341                                 warnx("Invalid opcode 0x%#x, must be between"
9342                                       "0 and 0xff inclusive", opcode);
9343                                 retval = 1;
9344                                 goto bailout;
9345                         }
9346                         opcode_set = 1;
9347                         break;
9348                 case 's':
9349                         service_action = strtoul(optarg, &endptr, 0);
9350                         if (*endptr != '\0') {
9351                                 warnx("Invalid service action \"%s\", must "
9352                                       "be a number", optarg);
9353                                 retval = 1;
9354                                 goto bailout;
9355                         }
9356                         if (service_action > 0xffff) {
9357                                 warnx("Invalid service action 0x%#x, must "
9358                                       "be between 0 and 0xffff inclusive",
9359                                       service_action);
9360                                 retval = 1;
9361                         }
9362                         sa_set = 1;
9363                         break;
9364                 case 'T':
9365                         td_set = 1;
9366                         break;
9367                 default:
9368                         break;
9369                 }
9370         }
9371
9372         if ((sa_set != 0)
9373          && (opcode_set == 0)) {
9374                 warnx("You must specify an opcode with -o if a service "
9375                       "action is given");
9376                 retval = 1;
9377                 goto bailout;
9378         }
9379         retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
9380                                 sa_set, service_action, td_set, task_attr,
9381                                 retry_count, timeout, verbosemode, &valid_len,
9382                                 &buf);
9383         if (retval != 0)
9384                 goto bailout;
9385
9386         if ((opcode_set != 0)
9387          || (sa_set != 0)) {
9388                 retval = scsiprintoneopcode(device, opcode, sa_set,
9389                                             service_action, buf, valid_len);
9390         } else {
9391                 retval = scsiprintopcodes(device, td_set, buf, valid_len);
9392         }
9393
9394 bailout:
9395         free(buf);
9396
9397         return (retval);
9398 }
9399
9400 #endif /* MINIMALISTIC */
9401
9402 static int
9403 scsireprobe(struct cam_device *device)
9404 {
9405         union ccb *ccb;
9406         int retval = 0;
9407
9408         ccb = cam_getccb(device);
9409
9410         if (ccb == NULL) {
9411                 warnx("%s: error allocating ccb", __func__);
9412                 return (1);
9413         }
9414
9415         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
9416
9417         ccb->ccb_h.func_code = XPT_REPROBE_LUN;
9418
9419         if (cam_send_ccb(device, ccb) < 0) {
9420                 warn("error sending XPT_REPROBE_LUN CCB");
9421                 retval = 1;
9422                 goto bailout;
9423         }
9424
9425         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
9426                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
9427                 retval = 1;
9428                 goto bailout;
9429         }
9430
9431 bailout:
9432         cam_freeccb(ccb);
9433
9434         return (retval);
9435 }
9436
9437 void
9438 usage(int printlong)
9439 {
9440
9441         fprintf(printlong ? stdout : stderr,
9442 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
9443 "        camcontrol devlist    [-b] [-v]\n"
9444 #ifndef MINIMALISTIC
9445 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
9446 "        camcontrol tur        [dev_id][generic args]\n"
9447 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
9448 "        camcontrol identify   [dev_id][generic args] [-v]\n"
9449 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
9450 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
9451 "                              [-q] [-s]\n"
9452 "        camcontrol start      [dev_id][generic args]\n"
9453 "        camcontrol stop       [dev_id][generic args]\n"
9454 "        camcontrol load       [dev_id][generic args]\n"
9455 "        camcontrol eject      [dev_id][generic args]\n"
9456 "        camcontrol reprobe    [dev_id][generic args]\n"
9457 #endif /* MINIMALISTIC */
9458 "        camcontrol rescan     <all | bus[:target:lun] | dev_id>\n"
9459 "        camcontrol reset      <all | bus[:target:lun] | dev_id>\n"
9460 #ifndef MINIMALISTIC
9461 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
9462 "                              [-q][-s][-S offset][-X]\n"
9463 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
9464 "                              [-P pagectl][-e | -b][-d]\n"
9465 "        camcontrol cmd        [dev_id][generic args]\n"
9466 "                              <-a cmd [args] | -c cmd [args]>\n"
9467 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
9468 "        camcontrol smpcmd     [dev_id][generic args]\n"
9469 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
9470 "        camcontrol smprg      [dev_id][generic args][-l]\n"
9471 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
9472 "                              [-o operation][-d name][-m rate][-M rate]\n"
9473 "                              [-T pp_timeout][-a enable|disable]\n"
9474 "                              [-A enable|disable][-s enable|disable]\n"
9475 "                              [-S enable|disable]\n"
9476 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
9477 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
9478 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
9479 "                              <all|bus[:target[:lun]]|off>\n"
9480 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
9481 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
9482 "                              [-D <enable|disable>][-M mode][-O offset]\n"
9483 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
9484 "                              [-U][-W bus_width]\n"
9485 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
9486 "        camcontrol sanitize   [dev_id][generic args]\n"
9487 "                              [-a overwrite|block|crypto|exitfailure]\n"
9488 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
9489 "                              [-y]\n"
9490 "        camcontrol idle       [dev_id][generic args][-t time]\n"
9491 "        camcontrol standby    [dev_id][generic args][-t time]\n"
9492 "        camcontrol sleep      [dev_id][generic args]\n"
9493 "        camcontrol apm        [dev_id][generic args][-l level]\n"
9494 "        camcontrol aam        [dev_id][generic args][-l level]\n"
9495 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
9496 "                              [-s][-y]\n"
9497 "        camcontrol security   [dev_id][generic args]\n"
9498 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
9499 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
9500 "                              [-U <user|master>] [-y]\n"
9501 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
9502 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
9503 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
9504 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
9505 "                              [-s scope][-S][-T type][-U]\n"
9506 "        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
9507 "                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
9508 "                              [-p part][-s start][-T type][-V vol]\n"
9509 "        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
9510 "                              [-N][-T]\n"
9511 "        camcontrol zone       [dev_id][generic args]<-c cmd> [-a] [-l LBA]\n"
9512 "                              [-o rep_opts] [-P print_opts]\n"
9513 "        camcontrol epc        [dev_id][generic_args]<-c cmd> [-d] [-D] [-e]\n"
9514 "                              [-H] [-p power_cond] [-P] [-r rst_src] [-s]\n"
9515 "                              [-S power_src] [-T timer]\n"
9516 "        camcontrol timestamp  [dev_id][generic_args] <-r [-f format|-m|-U]>|\n"
9517 "                              <-s <-f format -T time | -U >>\n"
9518 "                              \n"
9519 #endif /* MINIMALISTIC */
9520 "        camcontrol help\n");
9521         if (!printlong)
9522                 return;
9523 #ifndef MINIMALISTIC
9524         fprintf(stdout,
9525 "Specify one of the following options:\n"
9526 "devlist     list all CAM devices\n"
9527 "periphlist  list all CAM peripheral drivers attached to a device\n"
9528 "tur         send a test unit ready to the named device\n"
9529 "inquiry     send a SCSI inquiry command to the named device\n"
9530 "identify    send a ATA identify command to the named device\n"
9531 "reportluns  send a SCSI report luns command to the device\n"
9532 "readcap     send a SCSI read capacity command to the device\n"
9533 "start       send a Start Unit command to the device\n"
9534 "stop        send a Stop Unit command to the device\n"
9535 "load        send a Start Unit command to the device with the load bit set\n"
9536 "eject       send a Stop Unit command to the device with the eject bit set\n"
9537 "reprobe     update capacity information of the given device\n"
9538 "rescan      rescan all buses, the given bus, bus:target:lun or device\n"
9539 "reset       reset all buses, the given bus, bus:target:lun or device\n"
9540 "defects     read the defect list of the specified device\n"
9541 "modepage    display or edit (-e) the given mode page\n"
9542 "cmd         send the given SCSI command, may need -i or -o as well\n"
9543 "smpcmd      send the given SMP command, requires -o and -i\n"
9544 "smprg       send the SMP Report General command\n"
9545 "smppc       send the SMP PHY Control command, requires -p\n"
9546 "smpphylist  display phys attached to a SAS expander\n"
9547 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
9548 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
9549 "tags        report or set the number of transaction slots for a device\n"
9550 "negotiate   report or set device negotiation parameters\n"
9551 "format      send the SCSI FORMAT UNIT command to the named device\n"
9552 "sanitize    send the SCSI SANITIZE command to the named device\n"
9553 "idle        send the ATA IDLE command to the named device\n"
9554 "standby     send the ATA STANDBY command to the named device\n"
9555 "sleep       send the ATA SLEEP command to the named device\n"
9556 "fwdownload  program firmware of the named device with the given image\n"
9557 "security    report or send ATA security commands to the named device\n"
9558 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
9559 "attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
9560 "opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
9561 "zone        manage Zoned Block (Shingled) devices\n"
9562 "epc         send ATA Extended Power Conditions commands\n"
9563 "timestamp   report or set the device's timestamp\n"
9564 "help        this message\n"
9565 "Device Identifiers:\n"
9566 "bus:target        specify the bus and target, lun defaults to 0\n"
9567 "bus:target:lun    specify the bus, target and lun\n"
9568 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
9569 "Generic arguments:\n"
9570 "-v                be verbose, print out sense information\n"
9571 "-t timeout        command timeout in seconds, overrides default timeout\n"
9572 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
9573 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
9574 "-E                have the kernel attempt to perform SCSI error recovery\n"
9575 "-C count          specify the SCSI command retry count (needs -E to work)\n"
9576 "-Q task_attr      specify ordered, simple or head tag type for SCSI cmds\n"
9577 "modepage arguments:\n"
9578 "-l                list all available mode pages\n"
9579 "-m page           specify the mode page to view or edit\n"
9580 "-e                edit the specified mode page\n"
9581 "-b                force view to binary mode\n"
9582 "-d                disable block descriptors for mode sense\n"
9583 "-P pgctl          page control field 0-3\n"
9584 "defects arguments:\n"
9585 "-f format         specify defect list format (block, bfi or phys)\n"
9586 "-G                get the grown defect list\n"
9587 "-P                get the permanent defect list\n"
9588 "inquiry arguments:\n"
9589 "-D                get the standard inquiry data\n"
9590 "-S                get the serial number\n"
9591 "-R                get the transfer rate, etc.\n"
9592 "reportluns arguments:\n"
9593 "-c                only report a count of available LUNs\n"
9594 "-l                only print out luns, and not a count\n"
9595 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
9596 "readcap arguments\n"
9597 "-b                only report the blocksize\n"
9598 "-h                human readable device size, base 2\n"
9599 "-H                human readable device size, base 10\n"
9600 "-N                print the number of blocks instead of last block\n"
9601 "-q                quiet, print numbers only\n"
9602 "-s                only report the last block/device size\n"
9603 "cmd arguments:\n"
9604 "-c cdb [args]     specify the SCSI CDB\n"
9605 "-i len fmt        specify input data and input data format\n"
9606 "-o len fmt [args] specify output data and output data fmt\n"
9607 "smpcmd arguments:\n"
9608 "-r len fmt [args] specify the SMP command to be sent\n"
9609 "-R len fmt [args] specify SMP response format\n"
9610 "smprg arguments:\n"
9611 "-l                specify the long response format\n"
9612 "smppc arguments:\n"
9613 "-p phy            specify the PHY to operate on\n"
9614 "-l                specify the long request/response format\n"
9615 "-o operation      specify the phy control operation\n"
9616 "-d name           set the attached device name\n"
9617 "-m rate           set the minimum physical link rate\n"
9618 "-M rate           set the maximum physical link rate\n"
9619 "-T pp_timeout     set the partial pathway timeout value\n"
9620 "-a enable|disable enable or disable SATA slumber\n"
9621 "-A enable|disable enable or disable SATA partial phy power\n"
9622 "-s enable|disable enable or disable SAS slumber\n"
9623 "-S enable|disable enable or disable SAS partial phy power\n"
9624 "smpphylist arguments:\n"
9625 "-l                specify the long response format\n"
9626 "-q                only print phys with attached devices\n"
9627 "smpmaninfo arguments:\n"
9628 "-l                specify the long response format\n"
9629 "debug arguments:\n"
9630 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
9631 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
9632 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
9633 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
9634 "tags arguments:\n"
9635 "-N tags           specify the number of tags to use for this device\n"
9636 "-q                be quiet, don't report the number of tags\n"
9637 "-v                report a number of tag-related parameters\n"
9638 "negotiate arguments:\n"
9639 "-a                send a test unit ready after negotiation\n"
9640 "-c                report/set current negotiation settings\n"
9641 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
9642 "-M mode           set ATA mode\n"
9643 "-O offset         set command delay offset\n"
9644 "-q                be quiet, don't report anything\n"
9645 "-R syncrate       synchronization rate in MHz\n"
9646 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
9647 "-U                report/set user negotiation settings\n"
9648 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
9649 "-v                also print a Path Inquiry CCB for the controller\n"
9650 "format arguments:\n"
9651 "-q                be quiet, don't print status messages\n"
9652 "-r                run in report only mode\n"
9653 "-w                don't send immediate format command\n"
9654 "-y                don't ask any questions\n"
9655 "sanitize arguments:\n"
9656 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
9657 "-c passes         overwrite passes to perform (1 to 31)\n"
9658 "-I                invert overwrite pattern after each pass\n"
9659 "-P pattern        path to overwrite pattern file\n"
9660 "-q                be quiet, don't print status messages\n"
9661 "-r                run in report only mode\n"
9662 "-U                run operation in unrestricted completion exit mode\n"
9663 "-w                don't send immediate sanitize command\n"
9664 "-y                don't ask any questions\n"
9665 "idle/standby arguments:\n"
9666 "-t <arg>          number of seconds before respective state.\n"
9667 "fwdownload arguments:\n"
9668 "-f fw_image       path to firmware image file\n"
9669 "-q                don't print informational messages, only errors\n"
9670 "-s                run in simulation mode\n"
9671 "-v                print info for every firmware segment sent to device\n"
9672 "-y                don't ask any questions\n"
9673 "security arguments:\n"
9674 "-d pwd            disable security using the given password for the selected\n"
9675 "                  user\n"
9676 "-e pwd            erase the device using the given pwd for the selected user\n"
9677 "-f                freeze the security configuration of the specified device\n"
9678 "-h pwd            enhanced erase the device using the given pwd for the\n"
9679 "                  selected user\n"
9680 "-k pwd            unlock the device using the given pwd for the selected\n"
9681 "                  user\n"
9682 "-l <high|maximum> specifies which security level to set: high or maximum\n"
9683 "-q                be quiet, do not print any status messages\n"
9684 "-s pwd            password the device (enable security) using the given\n"
9685 "                  pwd for the selected user\n"
9686 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
9687 "-U <user|master>  specifies which user to set: user or master\n"
9688 "-y                don't ask any questions\n"
9689 "hpa arguments:\n"
9690 "-f                freeze the HPA configuration of the device\n"
9691 "-l                lock the HPA configuration of the device\n"
9692 "-P                make the HPA max sectors persist\n"
9693 "-p pwd            Set the HPA configuration password required for unlock\n"
9694 "                  calls\n"
9695 "-q                be quiet, do not print any status messages\n"
9696 "-s sectors        configures the maximum user accessible sectors of the\n"
9697 "                  device\n"
9698 "-U pwd            unlock the HPA configuration of the device\n"
9699 "-y                don't ask any questions\n"
9700 "persist arguments:\n"
9701 "-i action         specify read_keys, read_reservation, report_cap, or\n"
9702 "                  read_full_status\n"
9703 "-o action         specify register, register_ignore, reserve, release,\n"
9704 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
9705 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
9706 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
9707 "-k key            specify the Reservation Key\n"
9708 "-K sa_key         specify the Service Action Reservation Key\n"
9709 "-p                set the Activate Persist Through Power Loss bit\n"
9710 "-R rtp            specify the Relative Target Port\n"
9711 "-s scope          specify the scope: lun, extent, element or a number\n"
9712 "-S                specify Transport ID for register, requires -I\n"
9713 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
9714 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
9715 "-U                unregister the current initiator for register_move\n"
9716 "attrib arguments:\n"
9717 "-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
9718 "                  supp_attr\n"
9719 "-w attr           specify an attribute to write, one -w argument per attr\n"
9720 "-a attr_num       only display this attribute number\n"
9721 "-c                get cached attributes\n"
9722 "-e elem_addr      request attributes for the given element in a changer\n"
9723 "-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
9724 "                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
9725 "                  field_none, field_desc, field_num, field_size, field_rw\n"
9726 "-p partition      request attributes for the given partition\n"
9727 "-s start_attr     request attributes starting at the given number\n"
9728 "-T elem_type      specify the element type (used with -e)\n"
9729 "-V logical_vol    specify the logical volume ID\n"
9730 "opcodes arguments:\n"
9731 "-o opcode         specify the individual opcode to list\n"
9732 "-s service_action specify the service action for the opcode\n"
9733 "-N                do not return SCSI error for unsupported SA\n"
9734 "-T                request nominal and recommended timeout values\n"
9735 "zone arguments:\n"
9736 "-c cmd            required: rz, open, close, finish, or rwp\n"
9737 "-a                apply the action to all zones\n"
9738 "-l LBA            specify the zone starting LBA\n"
9739 "-o rep_opts       report zones options: all, empty, imp_open, exp_open,\n"
9740 "                  closed, full, ro, offline, reset, nonseq, nonwp\n"
9741 "-P print_opt      report zones printing:  normal, summary, script\n"
9742 "epc arguments:\n"
9743 "-c cmd            required: restore, goto, timer, state, enable, disable,\n"
9744 "                  source, status, list\n"
9745 "-d                disable power mode (timer, state)\n"
9746 "-D                delayed entry (goto)\n"
9747 "-e                enable power mode (timer, state)\n"
9748 "-H                hold power mode (goto)\n"
9749 "-p power_cond     Idle_a, Idle_b, Idle_c, Standby_y, Standby_z (timer,\n"
9750 "                  state, goto)\n"
9751 "-P                only display power mode (status)\n"
9752 "-r rst_src        restore settings from: default, saved (restore)\n"
9753 "-s                save mode (timer, state, restore)\n"
9754 "-S power_src      set power source: battery, nonbattery (source)\n"
9755 "-T timer          set timer, seconds, .1 sec resolution (timer)\n"
9756 "timestamp arguments:\n"
9757 "-r                report the timestamp of the device\n"
9758 "-f format         report the timestamp of the device with the given\n"
9759 "                  strftime(3) format string\n"
9760 "-m                report the timestamp of the device as milliseconds since\n"
9761 "                  January 1st, 1970\n"
9762 "-U                report the time with UTC instead of the local time zone\n"
9763 "-s                set the timestamp of the device\n"
9764 "-f format         the format of the time string passed into strptime(3)\n"
9765 "-T time           the time value passed into strptime(3)\n"
9766 "-U                set the timestamp of the device to UTC time\n"
9767 );
9768 #endif /* MINIMALISTIC */
9769 }
9770
9771 int
9772 main(int argc, char **argv)
9773 {
9774         int c;
9775         char *device = NULL;
9776         int unit = 0;
9777         struct cam_device *cam_dev = NULL;
9778         int timeout = 0, retry_count = 1;
9779         camcontrol_optret optreturn;
9780         char *tstr;
9781         const char *mainopt = "C:En:Q:t:u:v";
9782         const char *subopt = NULL;
9783         char combinedopt[256];
9784         int error = 0, optstart = 2;
9785         int task_attr = MSG_SIMPLE_Q_TAG;
9786         int devopen = 1;
9787 #ifndef MINIMALISTIC
9788         path_id_t bus;
9789         target_id_t target;
9790         lun_id_t lun;
9791 #endif /* MINIMALISTIC */
9792
9793         cmdlist = CAM_CMD_NONE;
9794         arglist = CAM_ARG_NONE;
9795
9796         if (argc < 2) {
9797                 usage(0);
9798                 exit(1);
9799         }
9800
9801         /*
9802          * Get the base option.
9803          */
9804         optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
9805
9806         if (optreturn == CC_OR_AMBIGUOUS) {
9807                 warnx("ambiguous option %s", argv[1]);
9808                 usage(0);
9809                 exit(1);
9810         } else if (optreturn == CC_OR_NOT_FOUND) {
9811                 warnx("option %s not found", argv[1]);
9812                 usage(0);
9813                 exit(1);
9814         }
9815
9816         /*
9817          * Ahh, getopt(3) is a pain.
9818          *
9819          * This is a gross hack.  There really aren't many other good
9820          * options (excuse the pun) for parsing options in a situation like
9821          * this.  getopt is kinda braindead, so you end up having to run
9822          * through the options twice, and give each invocation of getopt
9823          * the option string for the other invocation.
9824          *
9825          * You would think that you could just have two groups of options.
9826          * The first group would get parsed by the first invocation of
9827          * getopt, and the second group would get parsed by the second
9828          * invocation of getopt.  It doesn't quite work out that way.  When
9829          * the first invocation of getopt finishes, it leaves optind pointing
9830          * to the argument _after_ the first argument in the second group.
9831          * So when the second invocation of getopt comes around, it doesn't
9832          * recognize the first argument it gets and then bails out.
9833          *
9834          * A nice alternative would be to have a flag for getopt that says
9835          * "just keep parsing arguments even when you encounter an unknown
9836          * argument", but there isn't one.  So there's no real clean way to
9837          * easily parse two sets of arguments without having one invocation
9838          * of getopt know about the other.
9839          *
9840          * Without this hack, the first invocation of getopt would work as
9841          * long as the generic arguments are first, but the second invocation
9842          * (in the subfunction) would fail in one of two ways.  In the case
9843          * where you don't set optreset, it would fail because optind may be
9844          * pointing to the argument after the one it should be pointing at.
9845          * In the case where you do set optreset, and reset optind, it would
9846          * fail because getopt would run into the first set of options, which
9847          * it doesn't understand.
9848          *
9849          * All of this would "sort of" work if you could somehow figure out
9850          * whether optind had been incremented one option too far.  The
9851          * mechanics of that, however, are more daunting than just giving
9852          * both invocations all of the expect options for either invocation.
9853          *
9854          * Needless to say, I wouldn't mind if someone invented a better
9855          * (non-GPL!) command line parsing interface than getopt.  I
9856          * wouldn't mind if someone added more knobs to getopt to make it
9857          * work better.  Who knows, I may talk myself into doing it someday,
9858          * if the standards weenies let me.  As it is, it just leads to
9859          * hackery like this and causes people to avoid it in some cases.
9860          *
9861          * KDM, September 8th, 1998
9862          */
9863         if (subopt != NULL)
9864                 sprintf(combinedopt, "%s%s", mainopt, subopt);
9865         else
9866                 sprintf(combinedopt, "%s", mainopt);
9867
9868         /*
9869          * For these options we do not parse optional device arguments and
9870          * we do not open a passthrough device.
9871          */
9872         if ((cmdlist == CAM_CMD_RESCAN)
9873          || (cmdlist == CAM_CMD_RESET)
9874          || (cmdlist == CAM_CMD_DEVTREE)
9875          || (cmdlist == CAM_CMD_USAGE)
9876          || (cmdlist == CAM_CMD_DEBUG))
9877                 devopen = 0;
9878
9879 #ifndef MINIMALISTIC
9880         if ((devopen == 1)
9881          && (argc > 2 && argv[2][0] != '-')) {
9882                 char name[30];
9883                 int rv;
9884
9885                 if (isdigit(argv[2][0])) {
9886                         /* device specified as bus:target[:lun] */
9887                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9888                         if (rv < 2)
9889                                 errx(1, "numeric device specification must "
9890                                      "be either bus:target, or "
9891                                      "bus:target:lun");
9892                         /* default to 0 if lun was not specified */
9893                         if ((arglist & CAM_ARG_LUN) == 0) {
9894                                 lun = 0;
9895                                 arglist |= CAM_ARG_LUN;
9896                         }
9897                         optstart++;
9898                 } else {
9899                         if (cam_get_device(argv[2], name, sizeof name, &unit)
9900                             == -1)
9901                                 errx(1, "%s", cam_errbuf);
9902                         device = strdup(name);
9903                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9904                         optstart++;
9905                 }
9906         }
9907 #endif /* MINIMALISTIC */
9908         /*
9909          * Start getopt processing at argv[2/3], since we've already
9910          * accepted argv[1..2] as the command name, and as a possible
9911          * device name.
9912          */
9913         optind = optstart;
9914
9915         /*
9916          * Now we run through the argument list looking for generic
9917          * options, and ignoring options that possibly belong to
9918          * subfunctions.
9919          */
9920         while ((c = getopt(argc, argv, combinedopt))!= -1){
9921                 switch(c) {
9922                         case 'C':
9923                                 retry_count = strtol(optarg, NULL, 0);
9924                                 if (retry_count < 0)
9925                                         errx(1, "retry count %d is < 0",
9926                                              retry_count);
9927                                 arglist |= CAM_ARG_RETRIES;
9928                                 break;
9929                         case 'E':
9930                                 arglist |= CAM_ARG_ERR_RECOVER;
9931                                 break;
9932                         case 'n':
9933                                 arglist |= CAM_ARG_DEVICE;
9934                                 tstr = optarg;
9935                                 while (isspace(*tstr) && (*tstr != '\0'))
9936                                         tstr++;
9937                                 device = (char *)strdup(tstr);
9938                                 break;
9939                         case 'Q': {
9940                                 char *endptr;
9941                                 int table_entry = 0;
9942
9943                                 tstr = optarg;
9944                                 while (isspace(*tstr) && (*tstr != '\0'))
9945                                         tstr++;
9946                                 if (isdigit(*tstr)) {
9947                                         task_attr = strtol(tstr, &endptr, 0);
9948                                         if (*endptr != '\0') {
9949                                                 errx(1, "Invalid queue option "
9950                                                     "%s", tstr);
9951                                         }
9952                                 } else {
9953                                         size_t table_size;
9954                                         scsi_nv_status status;
9955
9956                                         table_size = sizeof(task_attrs) /
9957                                                      sizeof(task_attrs[0]);
9958                                         status = scsi_get_nv(task_attrs,
9959                                             table_size, tstr, &table_entry,
9960                                             SCSI_NV_FLAG_IG_CASE);
9961                                         if (status == SCSI_NV_FOUND)
9962                                                 task_attr = task_attrs[
9963                                                     table_entry].value;
9964                                         else {
9965                                                 errx(1, "%s option %s",
9966                                                   (status == SCSI_NV_AMBIGUOUS)?
9967                                                     "ambiguous" : "invalid",
9968                                                     tstr);
9969                                         }
9970                                 }
9971                                 break;
9972                         }
9973                         case 't':
9974                                 timeout = strtol(optarg, NULL, 0);
9975                                 if (timeout < 0)
9976                                         errx(1, "invalid timeout %d", timeout);
9977                                 /* Convert the timeout from seconds to ms */
9978                                 timeout *= 1000;
9979                                 arglist |= CAM_ARG_TIMEOUT;
9980                                 break;
9981                         case 'u':
9982                                 arglist |= CAM_ARG_UNIT;
9983                                 unit = strtol(optarg, NULL, 0);
9984                                 break;
9985                         case 'v':
9986                                 arglist |= CAM_ARG_VERBOSE;
9987                                 break;
9988                         default:
9989                                 break;
9990                 }
9991         }
9992
9993 #ifndef MINIMALISTIC
9994         /*
9995          * For most commands we'll want to open the passthrough device
9996          * associated with the specified device.  In the case of the rescan
9997          * commands, we don't use a passthrough device at all, just the
9998          * transport layer device.
9999          */
10000         if (devopen == 1) {
10001                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
10002                  && (((arglist & CAM_ARG_DEVICE) == 0)
10003                   || ((arglist & CAM_ARG_UNIT) == 0))) {
10004                         errx(1, "subcommand \"%s\" requires a valid device "
10005                              "identifier", argv[1]);
10006                 }
10007
10008                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
10009                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
10010                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
10011                      == NULL)
10012                         errx(1,"%s", cam_errbuf);
10013         }
10014 #endif /* MINIMALISTIC */
10015
10016         /*
10017          * Reset optind to 2, and reset getopt, so these routines can parse
10018          * the arguments again.
10019          */
10020         optind = optstart;
10021         optreset = 1;
10022
10023         switch(cmdlist) {
10024 #ifndef MINIMALISTIC
10025         case CAM_CMD_DEVLIST:
10026                 error = getdevlist(cam_dev);
10027                 break;
10028         case CAM_CMD_HPA:
10029                 error = atahpa(cam_dev, retry_count, timeout,
10030                                argc, argv, combinedopt);
10031                 break;
10032 #endif /* MINIMALISTIC */
10033         case CAM_CMD_DEVTREE:
10034                 error = getdevtree(argc, argv, combinedopt);
10035                 break;
10036 #ifndef MINIMALISTIC
10037         case CAM_CMD_TUR:
10038                 error = testunitready(cam_dev, task_attr, retry_count,
10039                     timeout, 0);
10040                 break;
10041         case CAM_CMD_INQUIRY:
10042                 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
10043                                       task_attr, retry_count, timeout);
10044                 break;
10045         case CAM_CMD_IDENTIFY:
10046                 error = ataidentify(cam_dev, retry_count, timeout);
10047                 break;
10048         case CAM_CMD_STARTSTOP:
10049                 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
10050                                   arglist & CAM_ARG_EJECT, task_attr,
10051                                   retry_count, timeout);
10052                 break;
10053 #endif /* MINIMALISTIC */
10054         case CAM_CMD_RESCAN:
10055                 error = dorescan_or_reset(argc, argv, 1);
10056                 break;
10057         case CAM_CMD_RESET:
10058                 error = dorescan_or_reset(argc, argv, 0);
10059                 break;
10060 #ifndef MINIMALISTIC
10061         case CAM_CMD_READ_DEFECTS:
10062                 error = readdefects(cam_dev, argc, argv, combinedopt,
10063                                     task_attr, retry_count, timeout);
10064                 break;
10065         case CAM_CMD_MODE_PAGE:
10066                 modepage(cam_dev, argc, argv, combinedopt,
10067                          task_attr, retry_count, timeout);
10068                 break;
10069         case CAM_CMD_SCSI_CMD:
10070                 error = scsicmd(cam_dev, argc, argv, combinedopt,
10071                                 task_attr, retry_count, timeout);
10072                 break;
10073         case CAM_CMD_MMCSD_CMD:
10074                 error = mmcsdcmd(cam_dev, argc, argv, combinedopt,
10075                                         retry_count, timeout);
10076                 break;
10077         case CAM_CMD_SMP_CMD:
10078                 error = smpcmd(cam_dev, argc, argv, combinedopt,
10079                                retry_count, timeout);
10080                 break;
10081         case CAM_CMD_SMP_RG:
10082                 error = smpreportgeneral(cam_dev, argc, argv,
10083                                          combinedopt, retry_count,
10084                                          timeout);
10085                 break;
10086         case CAM_CMD_SMP_PC:
10087                 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
10088                                       retry_count, timeout);
10089                 break;
10090         case CAM_CMD_SMP_PHYLIST:
10091                 error = smpphylist(cam_dev, argc, argv, combinedopt,
10092                                    retry_count, timeout);
10093                 break;
10094         case CAM_CMD_SMP_MANINFO:
10095                 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
10096                                    retry_count, timeout);
10097                 break;
10098         case CAM_CMD_DEBUG:
10099                 error = camdebug(argc, argv, combinedopt);
10100                 break;
10101         case CAM_CMD_TAG:
10102                 error = tagcontrol(cam_dev, argc, argv, combinedopt);
10103                 break;
10104         case CAM_CMD_RATE:
10105                 error = ratecontrol(cam_dev, task_attr, retry_count,
10106                                     timeout, argc, argv, combinedopt);
10107                 break;
10108         case CAM_CMD_FORMAT:
10109                 error = scsiformat(cam_dev, argc, argv,
10110                                    combinedopt, task_attr, retry_count,
10111                                    timeout);
10112                 break;
10113         case CAM_CMD_REPORTLUNS:
10114                 error = scsireportluns(cam_dev, argc, argv,
10115                                        combinedopt, task_attr,
10116                                        retry_count, timeout);
10117                 break;
10118         case CAM_CMD_READCAP:
10119                 error = scsireadcapacity(cam_dev, argc, argv,
10120                                          combinedopt, task_attr,
10121                                          retry_count, timeout);
10122                 break;
10123         case CAM_CMD_IDLE:
10124         case CAM_CMD_STANDBY:
10125         case CAM_CMD_SLEEP:
10126                 error = atapm(cam_dev, argc, argv,
10127                               combinedopt, retry_count, timeout);
10128                 break;
10129         case CAM_CMD_APM:
10130         case CAM_CMD_AAM:
10131                 error = ataaxm(cam_dev, argc, argv,
10132                               combinedopt, retry_count, timeout);
10133                 break;
10134         case CAM_CMD_SECURITY:
10135                 error = atasecurity(cam_dev, retry_count, timeout,
10136                                     argc, argv, combinedopt);
10137                 break;
10138         case CAM_CMD_DOWNLOAD_FW:
10139                 error = fwdownload(cam_dev, argc, argv, combinedopt,
10140                     arglist & CAM_ARG_VERBOSE, task_attr, retry_count,
10141                     timeout);
10142                 break;
10143         case CAM_CMD_SANITIZE:
10144                 error = scsisanitize(cam_dev, argc, argv,
10145                                      combinedopt, task_attr,
10146                                      retry_count, timeout);
10147                 break;
10148         case CAM_CMD_PERSIST:
10149                 error = scsipersist(cam_dev, argc, argv, combinedopt,
10150                     task_attr, retry_count, timeout,
10151                     arglist & CAM_ARG_VERBOSE,
10152                     arglist & CAM_ARG_ERR_RECOVER);
10153                 break;
10154         case CAM_CMD_ATTRIB:
10155                 error = scsiattrib(cam_dev, argc, argv, combinedopt,
10156                     task_attr, retry_count, timeout,
10157                     arglist & CAM_ARG_VERBOSE,
10158                     arglist & CAM_ARG_ERR_RECOVER);
10159                 break;
10160         case CAM_CMD_OPCODES:
10161                 error = scsiopcodes(cam_dev, argc, argv, combinedopt,
10162                     task_attr, retry_count, timeout,
10163                     arglist & CAM_ARG_VERBOSE);
10164                 break;
10165         case CAM_CMD_REPROBE:
10166                 error = scsireprobe(cam_dev);
10167                 break;
10168         case CAM_CMD_ZONE:
10169                 error = zone(cam_dev, argc, argv, combinedopt,
10170                     task_attr, retry_count, timeout,
10171                     arglist & CAM_ARG_VERBOSE);
10172                 break;
10173         case CAM_CMD_EPC:
10174                 error = epc(cam_dev, argc, argv, combinedopt,
10175                     retry_count, timeout, arglist & CAM_ARG_VERBOSE);
10176                 break;
10177         case CAM_CMD_TIMESTAMP:
10178                 error = timestamp(cam_dev, argc, argv, combinedopt,
10179                     task_attr, retry_count, timeout,
10180                     arglist & CAM_ARG_VERBOSE);
10181                 break;
10182 #endif /* MINIMALISTIC */
10183         case CAM_CMD_USAGE:
10184                 usage(1);
10185                 break;
10186         default:
10187                 usage(0);
10188                 error = 1;
10189                 break;
10190         }
10191
10192         if (cam_dev != NULL)
10193                 cam_close_device(cam_dev);
10194
10195         exit(error);
10196 }