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