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