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