]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/camcontrol/camcontrol.c
Copy needed include files from EDK2. This is a minimal set gleened
[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 {
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         }
3141
3142         if ((arglist & CAM_ARG_BUS)
3143             && (arglist & CAM_ARG_TARGET)
3144             && (arglist & CAM_ARG_LUN))
3145                 error = scanlun_or_reset_dev(bus, target, lun, rescan);
3146         else
3147                 error = rescan_or_reset_bus(bus, rescan);
3148
3149         return(error);
3150 }
3151
3152 static int
3153 rescan_or_reset_bus(path_id_t bus, int rescan)
3154 {
3155         union ccb *ccb = NULL, *matchccb = NULL;
3156         int fd = -1, retval;
3157         int bufsize;
3158
3159         retval = 0;
3160
3161         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3162                 warnx("error opening transport layer device %s", XPT_DEVICE);
3163                 warn("%s", XPT_DEVICE);
3164                 return(1);
3165         }
3166
3167         ccb = malloc(sizeof(*ccb));
3168         if (ccb == NULL) {
3169                 warn("failed to allocate CCB");
3170                 retval = 1;
3171                 goto bailout;
3172         }
3173         bzero(ccb, sizeof(*ccb));
3174
3175         if (bus != CAM_BUS_WILDCARD) {
3176                 ccb->ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3177                 ccb->ccb_h.path_id = bus;
3178                 ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
3179                 ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
3180                 ccb->crcn.flags = CAM_FLAG_NONE;
3181
3182                 /* run this at a low priority */
3183                 ccb->ccb_h.pinfo.priority = 5;
3184
3185                 if (ioctl(fd, CAMIOCOMMAND, ccb) == -1) {
3186                         warn("CAMIOCOMMAND ioctl failed");
3187                         retval = 1;
3188                         goto bailout;
3189                 }
3190
3191                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3192                         fprintf(stdout, "%s of bus %d was successful\n",
3193                             rescan ? "Re-scan" : "Reset", bus);
3194                 } else {
3195                         fprintf(stdout, "%s of bus %d returned error %#x\n",
3196                                 rescan ? "Re-scan" : "Reset", bus,
3197                                 ccb->ccb_h.status & CAM_STATUS_MASK);
3198                         retval = 1;
3199                 }
3200
3201                 goto bailout;
3202         }
3203
3204
3205         /*
3206          * The right way to handle this is to modify the xpt so that it can
3207          * handle a wildcarded bus in a rescan or reset CCB.  At the moment
3208          * that isn't implemented, so instead we enumerate the buses and
3209          * send the rescan or reset to those buses in the case where the
3210          * given bus is -1 (wildcard).  We don't send a rescan or reset
3211          * to the xpt bus; sending a rescan to the xpt bus is effectively a
3212          * no-op, sending a rescan to the xpt bus would result in a status of
3213          * CAM_REQ_INVALID.
3214          */
3215         matchccb = malloc(sizeof(*matchccb));
3216         if (matchccb == NULL) {
3217                 warn("failed to allocate CCB");
3218                 retval = 1;
3219                 goto bailout;
3220         }
3221         bzero(matchccb, sizeof(*matchccb));
3222         matchccb->ccb_h.func_code = XPT_DEV_MATCH;
3223         matchccb->ccb_h.path_id = CAM_BUS_WILDCARD;
3224         bufsize = sizeof(struct dev_match_result) * 20;
3225         matchccb->cdm.match_buf_len = bufsize;
3226         matchccb->cdm.matches=(struct dev_match_result *)malloc(bufsize);
3227         if (matchccb->cdm.matches == NULL) {
3228                 warnx("can't malloc memory for matches");
3229                 retval = 1;
3230                 goto bailout;
3231         }
3232         matchccb->cdm.num_matches = 0;
3233
3234         matchccb->cdm.num_patterns = 1;
3235         matchccb->cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3236
3237         matchccb->cdm.patterns = (struct dev_match_pattern *)malloc(
3238                 matchccb->cdm.pattern_buf_len);
3239         if (matchccb->cdm.patterns == NULL) {
3240                 warnx("can't malloc memory for patterns");
3241                 retval = 1;
3242                 goto bailout;
3243         }
3244         matchccb->cdm.patterns[0].type = DEV_MATCH_BUS;
3245         matchccb->cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3246
3247         do {
3248                 unsigned int i;
3249
3250                 if (ioctl(fd, CAMIOCOMMAND, matchccb) == -1) {
3251                         warn("CAMIOCOMMAND ioctl failed");
3252                         retval = 1;
3253                         goto bailout;
3254                 }
3255
3256                 if ((matchccb->ccb_h.status != CAM_REQ_CMP)
3257                  || ((matchccb->cdm.status != CAM_DEV_MATCH_LAST)
3258                    && (matchccb->cdm.status != CAM_DEV_MATCH_MORE))) {
3259                         warnx("got CAM error %#x, CDM error %d\n",
3260                               matchccb->ccb_h.status, matchccb->cdm.status);
3261                         retval = 1;
3262                         goto bailout;
3263                 }
3264
3265                 for (i = 0; i < matchccb->cdm.num_matches; i++) {
3266                         struct bus_match_result *bus_result;
3267
3268                         /* This shouldn't happen. */
3269                         if (matchccb->cdm.matches[i].type != DEV_MATCH_BUS)
3270                                 continue;
3271
3272                         bus_result =&matchccb->cdm.matches[i].result.bus_result;
3273
3274                         /*
3275                          * We don't want to rescan or reset the xpt bus.
3276                          * See above.
3277                          */
3278                         if (bus_result->path_id == CAM_XPT_PATH_ID)
3279                                 continue;
3280
3281                         ccb->ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3282                                                        XPT_RESET_BUS;
3283                         ccb->ccb_h.path_id = bus_result->path_id;
3284                         ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
3285                         ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
3286                         ccb->crcn.flags = CAM_FLAG_NONE;
3287
3288                         /* run this at a low priority */
3289                         ccb->ccb_h.pinfo.priority = 5;
3290
3291                         if (ioctl(fd, CAMIOCOMMAND, ccb) == -1) {
3292                                 warn("CAMIOCOMMAND ioctl failed");
3293                                 retval = 1;
3294                                 goto bailout;
3295                         }
3296
3297                         if ((ccb->ccb_h.status & CAM_STATUS_MASK)==CAM_REQ_CMP){
3298                                 fprintf(stdout, "%s of bus %d was successful\n",
3299                                         rescan? "Re-scan" : "Reset",
3300                                         bus_result->path_id);
3301                         } else {
3302                                 /*
3303                                  * Don't bail out just yet, maybe the other
3304                                  * rescan or reset commands will complete
3305                                  * successfully.
3306                                  */
3307                                 fprintf(stderr, "%s of bus %d returned error "
3308                                         "%#x\n", rescan? "Re-scan" : "Reset",
3309                                         bus_result->path_id,
3310                                         ccb->ccb_h.status & CAM_STATUS_MASK);
3311                                 retval = 1;
3312                         }
3313                 }
3314         } while ((matchccb->ccb_h.status == CAM_REQ_CMP)
3315                  && (matchccb->cdm.status == CAM_DEV_MATCH_MORE));
3316
3317 bailout:
3318
3319         if (fd != -1)
3320                 close(fd);
3321
3322         if (matchccb != NULL) {
3323                 free(matchccb->cdm.patterns);
3324                 free(matchccb->cdm.matches);
3325                 free(matchccb);
3326         }
3327         free(ccb);
3328
3329         return(retval);
3330 }
3331
3332 static int
3333 scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3334 {
3335         union ccb ccb;
3336         struct cam_device *device;
3337         int fd;
3338
3339         device = NULL;
3340
3341         if (bus == CAM_BUS_WILDCARD) {
3342                 warnx("invalid bus number %d", bus);
3343                 return(1);
3344         }
3345
3346         if (target == CAM_TARGET_WILDCARD) {
3347                 warnx("invalid target number %d", target);
3348                 return(1);
3349         }
3350
3351         if (lun == CAM_LUN_WILDCARD) {
3352                 warnx("invalid lun number %jx", (uintmax_t)lun);
3353                 return(1);
3354         }
3355
3356         fd = -1;
3357
3358         bzero(&ccb, sizeof(union ccb));
3359
3360         if (scan) {
3361                 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3362                         warnx("error opening transport layer device %s\n",
3363                             XPT_DEVICE);
3364                         warn("%s", XPT_DEVICE);
3365                         return(1);
3366                 }
3367         } else {
3368                 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3369                 if (device == NULL) {
3370                         warnx("%s", cam_errbuf);
3371                         return(1);
3372                 }
3373         }
3374
3375         ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3376         ccb.ccb_h.path_id = bus;
3377         ccb.ccb_h.target_id = target;
3378         ccb.ccb_h.target_lun = lun;
3379         ccb.ccb_h.timeout = 5000;
3380         ccb.crcn.flags = CAM_FLAG_NONE;
3381
3382         /* run this at a low priority */
3383         ccb.ccb_h.pinfo.priority = 5;
3384
3385         if (scan) {
3386                 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3387                         warn("CAMIOCOMMAND ioctl failed");
3388                         close(fd);
3389                         return(1);
3390                 }
3391         } else {
3392                 if (cam_send_ccb(device, &ccb) < 0) {
3393                         warn("error sending XPT_RESET_DEV CCB");
3394                         cam_close_device(device);
3395                         return(1);
3396                 }
3397         }
3398
3399         if (scan)
3400                 close(fd);
3401         else
3402                 cam_close_device(device);
3403
3404         /*
3405          * An error code of CAM_BDR_SENT is normal for a BDR request.
3406          */
3407         if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3408          || ((!scan)
3409           && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3410                 fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3411                     scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3412                 return(0);
3413         } else {
3414                 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3415                     scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3416                     ccb.ccb_h.status & CAM_STATUS_MASK);
3417                 return(1);
3418         }
3419 }
3420
3421 #ifndef MINIMALISTIC
3422
3423 static struct scsi_nv defect_list_type_map[] = {
3424         { "block", SRDD10_BLOCK_FORMAT },
3425         { "extbfi", SRDD10_EXT_BFI_FORMAT },
3426         { "extphys", SRDD10_EXT_PHYS_FORMAT },
3427         { "longblock", SRDD10_LONG_BLOCK_FORMAT },
3428         { "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3429         { "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3430 };
3431
3432 static int
3433 readdefects(struct cam_device *device, int argc, char **argv,
3434             char *combinedopt, int task_attr, int retry_count, int timeout)
3435 {
3436         union ccb *ccb = NULL;
3437         struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3438         struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3439         size_t hdr_size = 0, entry_size = 0;
3440         int use_12byte = 0;
3441         int hex_format = 0;
3442         u_int8_t *defect_list = NULL;
3443         u_int8_t list_format = 0;
3444         int list_type_set = 0;
3445         u_int32_t dlist_length = 0;
3446         u_int32_t returned_length = 0, valid_len = 0;
3447         u_int32_t num_returned = 0, num_valid = 0;
3448         u_int32_t max_possible_size = 0, hdr_max = 0;
3449         u_int32_t starting_offset = 0;
3450         u_int8_t returned_format, returned_type;
3451         unsigned int i;
3452         int summary = 0, quiet = 0;
3453         int c, error = 0;
3454         int lists_specified = 0;
3455         int get_length = 1, first_pass = 1;
3456         int mads = 0;
3457
3458         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3459                 switch(c){
3460                 case 'f':
3461                 {
3462                         scsi_nv_status status;
3463                         int entry_num = 0;
3464
3465                         status = scsi_get_nv(defect_list_type_map,
3466                             sizeof(defect_list_type_map) /
3467                             sizeof(defect_list_type_map[0]), optarg,
3468                             &entry_num, SCSI_NV_FLAG_IG_CASE);
3469
3470                         if (status == SCSI_NV_FOUND) {
3471                                 list_format = defect_list_type_map[
3472                                     entry_num].value;
3473                                 list_type_set = 1;
3474                         } else {
3475                                 warnx("%s: %s %s option %s", __func__,
3476                                     (status == SCSI_NV_AMBIGUOUS) ?
3477                                     "ambiguous" : "invalid", "defect list type",
3478                                     optarg);
3479                                 error = 1;
3480                                 goto defect_bailout;
3481                         }
3482                         break;
3483                 }
3484                 case 'G':
3485                         arglist |= CAM_ARG_GLIST;
3486                         break;
3487                 case 'P':
3488                         arglist |= CAM_ARG_PLIST;
3489                         break;
3490                 case 'q':
3491                         quiet = 1;
3492                         break;
3493                 case 's':
3494                         summary = 1;
3495                         break;
3496                 case 'S': {
3497                         char *endptr;
3498
3499                         starting_offset = strtoul(optarg, &endptr, 0);
3500                         if (*endptr != '\0') {
3501                                 error = 1;
3502                                 warnx("invalid starting offset %s", optarg);
3503                                 goto defect_bailout;
3504                         }
3505                         break;
3506                 }
3507                 case 'X':
3508                         hex_format = 1;
3509                         break;
3510                 default:
3511                         break;
3512                 }
3513         }
3514
3515         if (list_type_set == 0) {
3516                 error = 1;
3517                 warnx("no defect list format specified");
3518                 goto defect_bailout;
3519         }
3520
3521         if (arglist & CAM_ARG_PLIST) {
3522                 list_format |= SRDD10_PLIST;
3523                 lists_specified++;
3524         }
3525
3526         if (arglist & CAM_ARG_GLIST) {
3527                 list_format |= SRDD10_GLIST;
3528                 lists_specified++;
3529         }
3530
3531         /*
3532          * This implies a summary, and was the previous behavior.
3533          */
3534         if (lists_specified == 0)
3535                 summary = 1;
3536
3537         ccb = cam_getccb(device);
3538
3539 retry_12byte:
3540
3541         /*
3542          * We start off asking for just the header to determine how much
3543          * defect data is available.  Some Hitachi drives return an error
3544          * if you ask for more data than the drive has.  Once we know the
3545          * length, we retry the command with the returned length.
3546          */
3547         if (use_12byte == 0)
3548                 dlist_length = sizeof(*hdr10);
3549         else
3550                 dlist_length = sizeof(*hdr12);
3551
3552 retry:
3553         if (defect_list != NULL) {
3554                 free(defect_list);
3555                 defect_list = NULL;
3556         }
3557         defect_list = malloc(dlist_length);
3558         if (defect_list == NULL) {
3559                 warnx("can't malloc memory for defect list");
3560                 error = 1;
3561                 goto defect_bailout;
3562         }
3563
3564 next_batch:
3565         bzero(defect_list, dlist_length);
3566
3567         /*
3568          * cam_getccb() zeros the CCB header only.  So we need to zero the
3569          * payload portion of the ccb.
3570          */
3571         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
3572
3573         scsi_read_defects(&ccb->csio,
3574                           /*retries*/ retry_count,
3575                           /*cbfcnp*/ NULL,
3576                           /*tag_action*/ task_attr,
3577                           /*list_format*/ list_format,
3578                           /*addr_desc_index*/ starting_offset,
3579                           /*data_ptr*/ defect_list,
3580                           /*dxfer_len*/ dlist_length,
3581                           /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3582                           /*sense_len*/ SSD_FULL_SIZE,
3583                           /*timeout*/ timeout ? timeout : 5000);
3584
3585         /* Disable freezing the device queue */
3586         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3587
3588         if (cam_send_ccb(device, ccb) < 0) {
3589                 perror("error reading defect list");
3590
3591                 if (arglist & CAM_ARG_VERBOSE) {
3592                         cam_error_print(device, ccb, CAM_ESF_ALL,
3593                                         CAM_EPF_ALL, stderr);
3594                 }
3595
3596                 error = 1;
3597                 goto defect_bailout;
3598         }
3599
3600         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3601
3602         if (use_12byte == 0) {
3603                 hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3604                 hdr_size = sizeof(*hdr10);
3605                 hdr_max = SRDDH10_MAX_LENGTH;
3606
3607                 if (valid_len >= hdr_size) {
3608                         returned_length = scsi_2btoul(hdr10->length);
3609                         returned_format = hdr10->format;
3610                 } else {
3611                         returned_length = 0;
3612                         returned_format = 0;
3613                 }
3614         } else {
3615                 hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3616                 hdr_size = sizeof(*hdr12);
3617                 hdr_max = SRDDH12_MAX_LENGTH;
3618
3619                 if (valid_len >= hdr_size) {
3620                         returned_length = scsi_4btoul(hdr12->length);
3621                         returned_format = hdr12->format;
3622                 } else {
3623                         returned_length = 0;
3624                         returned_format = 0;
3625                 }
3626         }
3627
3628         returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3629         switch (returned_type) {
3630         case SRDD10_BLOCK_FORMAT:
3631                 entry_size = sizeof(struct scsi_defect_desc_block);
3632                 break;
3633         case SRDD10_LONG_BLOCK_FORMAT:
3634                 entry_size = sizeof(struct scsi_defect_desc_long_block);
3635                 break;
3636         case SRDD10_EXT_PHYS_FORMAT:
3637         case SRDD10_PHYSICAL_SECTOR_FORMAT:
3638                 entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3639                 break;
3640         case SRDD10_EXT_BFI_FORMAT:
3641         case SRDD10_BYTES_FROM_INDEX_FORMAT:
3642                 entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3643                 break;
3644         default:
3645                 warnx("Unknown defect format 0x%x\n", returned_type);
3646                 error = 1;
3647                 goto defect_bailout;
3648                 break;
3649         } 
3650
3651         max_possible_size = (hdr_max / entry_size) * entry_size;
3652         num_returned = returned_length / entry_size;
3653         num_valid = min(returned_length, valid_len - hdr_size);
3654         num_valid /= entry_size;
3655
3656         if (get_length != 0) {
3657                 get_length = 0;
3658
3659                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3660                      CAM_SCSI_STATUS_ERROR) {
3661                         struct scsi_sense_data *sense;
3662                         int error_code, sense_key, asc, ascq;
3663
3664                         sense = &ccb->csio.sense_data;
3665                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
3666                             ccb->csio.sense_resid, &error_code, &sense_key,
3667                             &asc, &ascq, /*show_errors*/ 1);
3668
3669                         /*
3670                          * If the drive is reporting that it just doesn't
3671                          * support the defect list format, go ahead and use
3672                          * the length it reported.  Otherwise, the length
3673                          * may not be valid, so use the maximum.
3674                          */
3675                         if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3676                          && (asc == 0x1c) && (ascq == 0x00)
3677                          && (returned_length > 0)) {
3678                                 if ((use_12byte == 0)
3679                                  && (returned_length >= max_possible_size)) {
3680                                         get_length = 1;
3681                                         use_12byte = 1;
3682                                         goto retry_12byte;
3683                                 }
3684                                 dlist_length = returned_length + hdr_size;
3685                         } else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3686                                 && (asc == 0x1f) && (ascq == 0x00)
3687                                 && (returned_length > 0)) {
3688                                 /* Partial defect list transfer */
3689                                 /*
3690                                  * Hitachi drives return this error
3691                                  * along with a partial defect list if they
3692                                  * have more defects than the 10 byte
3693                                  * command can support.  Retry with the 12
3694                                  * byte command.
3695                                  */
3696                                 if (use_12byte == 0) {
3697                                         get_length = 1;
3698                                         use_12byte = 1;
3699                                         goto retry_12byte;
3700                                 }
3701                                 dlist_length = returned_length + hdr_size;
3702                         } else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3703                                 && (asc == 0x24) && (ascq == 0x00)) {
3704                                 /* Invalid field in CDB */
3705                                 /*
3706                                  * SBC-3 says that if the drive has more
3707                                  * defects than can be reported with the
3708                                  * 10 byte command, it should return this
3709                                  * error and no data.  Retry with the 12
3710                                  * byte command.
3711                                  */
3712                                 if (use_12byte == 0) {
3713                                         get_length = 1;
3714                                         use_12byte = 1;
3715                                         goto retry_12byte;
3716                                 }
3717                                 dlist_length = returned_length + hdr_size;
3718                         } else {
3719                                 /*
3720                                  * If we got a SCSI error and no valid length,
3721                                  * just use the 10 byte maximum.  The 12
3722                                  * byte maximum is too large.
3723                                  */
3724                                 if (returned_length == 0)
3725                                         dlist_length = SRDD10_MAX_LENGTH;
3726                                 else {
3727                                         if ((use_12byte == 0)
3728                                          && (returned_length >=
3729                                              max_possible_size)) {
3730                                                 get_length = 1;
3731                                                 use_12byte = 1;
3732                                                 goto retry_12byte;
3733                                         }
3734                                         dlist_length = returned_length +
3735                                             hdr_size;
3736                                 }
3737                         }
3738                 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3739                             CAM_REQ_CMP){
3740                         error = 1;
3741                         warnx("Error reading defect header");
3742                         if (arglist & CAM_ARG_VERBOSE)
3743                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3744                                                 CAM_EPF_ALL, stderr);
3745                         goto defect_bailout;
3746                 } else {
3747                         if ((use_12byte == 0)
3748                          && (returned_length >= max_possible_size)) {
3749                                 get_length = 1;
3750                                 use_12byte = 1;
3751                                 goto retry_12byte;
3752                         }
3753                         dlist_length = returned_length + hdr_size;
3754                 }
3755                 if (summary != 0) {
3756                         fprintf(stdout, "%u", num_returned);
3757                         if (quiet == 0) {
3758                                 fprintf(stdout, " defect%s",
3759                                         (num_returned != 1) ? "s" : "");
3760                         }
3761                         fprintf(stdout, "\n");
3762
3763                         goto defect_bailout;
3764                 }
3765
3766                 /*
3767                  * We always limit the list length to the 10-byte maximum
3768                  * length (0xffff).  The reason is that some controllers
3769                  * can't handle larger I/Os, and we can transfer the entire
3770                  * 10 byte list in one shot.  For drives that support the 12
3771                  * byte read defects command, we'll step through the list
3772                  * by specifying a starting offset.  For drives that don't
3773                  * support the 12 byte command's starting offset, we'll
3774                  * just display the first 64K.
3775                  */
3776                 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3777
3778                 goto retry;
3779         }
3780
3781
3782         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3783          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3784          && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3785                 struct scsi_sense_data *sense;
3786                 int error_code, sense_key, asc, ascq;
3787
3788                 sense = &ccb->csio.sense_data;
3789                 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3790                     ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3791                     &ascq, /*show_errors*/ 1);
3792
3793                 /*
3794                  * According to the SCSI spec, if the disk doesn't support
3795                  * the requested format, it will generally return a sense
3796                  * key of RECOVERED ERROR, and an additional sense code
3797                  * of "DEFECT LIST NOT FOUND".  HGST drives also return
3798                  * Primary/Grown defect list not found errors.  So just
3799                  * check for an ASC of 0x1c.
3800                  */
3801                 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3802                  && (asc == 0x1c)) {
3803                         const char *format_str;
3804
3805                         format_str = scsi_nv_to_str(defect_list_type_map,
3806                             sizeof(defect_list_type_map) /
3807                             sizeof(defect_list_type_map[0]),
3808                             list_format & SRDD10_DLIST_FORMAT_MASK);
3809                         warnx("requested defect format %s not available",
3810                             format_str ? format_str : "unknown");
3811
3812                         format_str = scsi_nv_to_str(defect_list_type_map,
3813                             sizeof(defect_list_type_map) /
3814                             sizeof(defect_list_type_map[0]), returned_type);
3815                         if (format_str != NULL) {
3816                                 warnx("Device returned %s format",
3817                                     format_str);
3818                         } else {
3819                                 error = 1;
3820                                 warnx("Device returned unknown defect"
3821                                      " data format %#x", returned_type);
3822                                 goto defect_bailout;
3823                         }
3824                 } else {
3825                         error = 1;
3826                         warnx("Error returned from read defect data command");
3827                         if (arglist & CAM_ARG_VERBOSE)
3828                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3829                                                 CAM_EPF_ALL, stderr);
3830                         goto defect_bailout;
3831                 }
3832         } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3833                 error = 1;
3834                 warnx("Error returned from read defect data command");
3835                 if (arglist & CAM_ARG_VERBOSE)
3836                         cam_error_print(device, ccb, CAM_ESF_ALL,
3837                                         CAM_EPF_ALL, stderr);
3838                 goto defect_bailout;
3839         }
3840
3841         if (first_pass != 0) {
3842                 fprintf(stderr, "Got %d defect", num_returned);
3843
3844                 if ((lists_specified == 0) || (num_returned == 0)) {
3845                         fprintf(stderr, "s.\n");
3846                         goto defect_bailout;
3847                 } else if (num_returned == 1)
3848                         fprintf(stderr, ":\n");
3849                 else
3850                         fprintf(stderr, "s:\n");
3851
3852                 first_pass = 0;
3853         }
3854
3855         /*
3856          * XXX KDM  I should probably clean up the printout format for the
3857          * disk defects.
3858          */
3859         switch (returned_type) {
3860         case SRDD10_PHYSICAL_SECTOR_FORMAT:
3861         case SRDD10_EXT_PHYS_FORMAT:
3862         {
3863                 struct scsi_defect_desc_phys_sector *dlist;
3864
3865                 dlist = (struct scsi_defect_desc_phys_sector *)
3866                         (defect_list + hdr_size);
3867
3868                 for (i = 0; i < num_valid; i++) {
3869                         uint32_t sector;
3870
3871                         sector = scsi_4btoul(dlist[i].sector);
3872                         if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
3873                                 mads = (sector & SDD_EXT_PHYS_MADS) ?
3874                                        0 : 1;
3875                                 sector &= ~SDD_EXT_PHYS_FLAG_MASK;
3876                         }
3877                         if (hex_format == 0)
3878                                 fprintf(stdout, "%d:%d:%d%s",
3879                                         scsi_3btoul(dlist[i].cylinder),
3880                                         dlist[i].head,
3881                                         scsi_4btoul(dlist[i].sector),
3882                                         mads ? " - " : "\n");
3883                         else
3884                                 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3885                                         scsi_3btoul(dlist[i].cylinder),
3886                                         dlist[i].head,
3887                                         scsi_4btoul(dlist[i].sector),
3888                                         mads ? " - " : "\n");
3889                         mads = 0;
3890                 }
3891                 if (num_valid < num_returned) {
3892                         starting_offset += num_valid;
3893                         goto next_batch;
3894                 }
3895                 break;
3896         }
3897         case SRDD10_BYTES_FROM_INDEX_FORMAT:
3898         case SRDD10_EXT_BFI_FORMAT:
3899         {
3900                 struct scsi_defect_desc_bytes_from_index *dlist;
3901
3902                 dlist = (struct scsi_defect_desc_bytes_from_index *)
3903                         (defect_list + hdr_size);
3904
3905                 for (i = 0; i < num_valid; i++) {
3906                         uint32_t bfi;
3907
3908                         bfi = scsi_4btoul(dlist[i].bytes_from_index);
3909                         if (returned_type == SRDD10_EXT_BFI_FORMAT) {
3910                                 mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
3911                                 bfi &= ~SDD_EXT_BFI_FLAG_MASK;
3912                         }
3913                         if (hex_format == 0)
3914                                 fprintf(stdout, "%d:%d:%d%s",
3915                                         scsi_3btoul(dlist[i].cylinder),
3916                                         dlist[i].head,
3917                                         scsi_4btoul(dlist[i].bytes_from_index),
3918                                         mads ? " - " : "\n");
3919                         else
3920                                 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3921                                         scsi_3btoul(dlist[i].cylinder),
3922                                         dlist[i].head,
3923                                         scsi_4btoul(dlist[i].bytes_from_index),
3924                                         mads ? " - " : "\n");
3925
3926                         mads = 0;
3927                 }
3928                 if (num_valid < num_returned) {
3929                         starting_offset += num_valid;
3930                         goto next_batch;
3931                 }
3932                 break;
3933         }
3934         case SRDDH10_BLOCK_FORMAT:
3935         {
3936                 struct scsi_defect_desc_block *dlist;
3937
3938                 dlist = (struct scsi_defect_desc_block *)
3939                         (defect_list + hdr_size);
3940
3941                 for (i = 0; i < num_valid; i++) {
3942                         if (hex_format == 0)
3943                                 fprintf(stdout, "%u\n",
3944                                         scsi_4btoul(dlist[i].address));
3945                         else
3946                                 fprintf(stdout, "0x%x\n",
3947                                         scsi_4btoul(dlist[i].address));
3948                 }
3949
3950                 if (num_valid < num_returned) {
3951                         starting_offset += num_valid;
3952                         goto next_batch;
3953                 }
3954
3955                 break;
3956         }
3957         case SRDD10_LONG_BLOCK_FORMAT:
3958         {
3959                 struct scsi_defect_desc_long_block *dlist;
3960
3961                 dlist = (struct scsi_defect_desc_long_block *)
3962                         (defect_list + hdr_size);
3963
3964                 for (i = 0; i < num_valid; i++) {
3965                         if (hex_format == 0)
3966                                 fprintf(stdout, "%ju\n",
3967                                         (uintmax_t)scsi_8btou64(
3968                                         dlist[i].address));
3969                         else
3970                                 fprintf(stdout, "0x%jx\n",
3971                                         (uintmax_t)scsi_8btou64(
3972                                         dlist[i].address));
3973                 }
3974
3975                 if (num_valid < num_returned) {
3976                         starting_offset += num_valid;
3977                         goto next_batch;
3978                 }
3979                 break;
3980         }
3981         default:
3982                 fprintf(stderr, "Unknown defect format 0x%x\n",
3983                         returned_type);
3984                 error = 1;
3985                 break;
3986         }
3987 defect_bailout:
3988
3989         if (defect_list != NULL)
3990                 free(defect_list);
3991
3992         if (ccb != NULL)
3993                 cam_freeccb(ccb);
3994
3995         return(error);
3996 }
3997 #endif /* MINIMALISTIC */
3998
3999 #if 0
4000 void
4001 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
4002 {
4003         union ccb *ccb;
4004
4005         ccb = cam_getccb(device);
4006
4007         cam_freeccb(ccb);
4008 }
4009 #endif
4010
4011 #ifndef MINIMALISTIC
4012 void
4013 mode_sense(struct cam_device *device, int dbd, int pc, int page, int subpage,
4014            int task_attr, int retry_count, int timeout, u_int8_t *data,
4015            int datalen)
4016 {
4017         union ccb *ccb;
4018         int retval;
4019
4020         ccb = cam_getccb(device);
4021
4022         if (ccb == NULL)
4023                 errx(1, "mode_sense: couldn't allocate CCB");
4024
4025         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
4026
4027         scsi_mode_sense_subpage(&ccb->csio,
4028                         /* retries */ retry_count,
4029                         /* cbfcnp */ NULL,
4030                         /* tag_action */ task_attr,
4031                         /* dbd */ dbd,
4032                         /* pc */ pc << 6,
4033                         /* page */ page,
4034                         /* subpage */ subpage,
4035                         /* param_buf */ data,
4036                         /* param_len */ datalen,
4037                         /* minimum_cmd_size */ 0,
4038                         /* sense_len */ SSD_FULL_SIZE,
4039                         /* timeout */ timeout ? timeout : 5000);
4040
4041         if (arglist & CAM_ARG_ERR_RECOVER)
4042                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4043
4044         /* Disable freezing the device queue */
4045         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4046
4047         if (((retval = cam_send_ccb(device, ccb)) < 0)
4048          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4049                 if (arglist & CAM_ARG_VERBOSE) {
4050                         cam_error_print(device, ccb, CAM_ESF_ALL,
4051                                         CAM_EPF_ALL, stderr);
4052                 }
4053                 cam_freeccb(ccb);
4054                 cam_close_device(device);
4055                 if (retval < 0)
4056                         err(1, "error sending mode sense command");
4057                 else
4058                         errx(1, "error sending mode sense command");
4059         }
4060
4061         cam_freeccb(ccb);
4062 }
4063
4064 void
4065 mode_select(struct cam_device *device, int save_pages, int task_attr,
4066             int retry_count, int timeout, u_int8_t *data, int datalen)
4067 {
4068         union ccb *ccb;
4069         int retval;
4070
4071         ccb = cam_getccb(device);
4072
4073         if (ccb == NULL)
4074                 errx(1, "mode_select: couldn't allocate CCB");
4075
4076         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
4077
4078         scsi_mode_select(&ccb->csio,
4079                          /* retries */ retry_count,
4080                          /* cbfcnp */ NULL,
4081                          /* tag_action */ task_attr,
4082                          /* scsi_page_fmt */ 1,
4083                          /* save_pages */ save_pages,
4084                          /* param_buf */ data,
4085                          /* param_len */ datalen,
4086                          /* sense_len */ SSD_FULL_SIZE,
4087                          /* timeout */ timeout ? timeout : 5000);
4088
4089         if (arglist & CAM_ARG_ERR_RECOVER)
4090                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4091
4092         /* Disable freezing the device queue */
4093         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4094
4095         if (((retval = cam_send_ccb(device, ccb)) < 0)
4096          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4097                 if (arglist & CAM_ARG_VERBOSE) {
4098                         cam_error_print(device, ccb, CAM_ESF_ALL,
4099                                         CAM_EPF_ALL, stderr);
4100                 }
4101                 cam_freeccb(ccb);
4102                 cam_close_device(device);
4103
4104                 if (retval < 0)
4105                         err(1, "error sending mode select command");
4106                 else
4107                         errx(1, "error sending mode select command");
4108
4109         }
4110
4111         cam_freeccb(ccb);
4112 }
4113
4114 void
4115 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4116          int task_attr, int retry_count, int timeout)
4117 {
4118         char *str_subpage;
4119         int c, page = -1, subpage = -1, pc = 0;
4120         int binary = 0, dbd = 0, edit = 0, list = 0;
4121
4122         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4123                 switch(c) {
4124                 case 'b':
4125                         binary = 1;
4126                         break;
4127                 case 'd':
4128                         dbd = 1;
4129                         break;
4130                 case 'e':
4131                         edit = 1;
4132                         break;
4133                 case 'l':
4134                         list++;
4135                         break;
4136                 case 'm':
4137                         str_subpage = optarg;
4138                         strsep(&str_subpage, ",");
4139                         page = strtol(optarg, NULL, 0);
4140                         if (str_subpage)
4141                             subpage = strtol(str_subpage, NULL, 0);
4142                         else
4143                             subpage = 0;
4144                         if (page < 0)
4145                                 errx(1, "invalid mode page %d", page);
4146                         if (subpage < 0)
4147                                 errx(1, "invalid mode subpage %d", subpage);
4148                         break;
4149                 case 'P':
4150                         pc = strtol(optarg, NULL, 0);
4151                         if ((pc < 0) || (pc > 3))
4152                                 errx(1, "invalid page control field %d", pc);
4153                         break;
4154                 default:
4155                         break;
4156                 }
4157         }
4158
4159         if (page == -1 && list == 0)
4160                 errx(1, "you must specify a mode page!");
4161
4162         if (list != 0) {
4163                 mode_list(device, dbd, pc, list > 1, task_attr, retry_count,
4164                           timeout);
4165         } else {
4166                 mode_edit(device, dbd, pc, page, subpage, edit, binary,
4167                     task_attr, retry_count, timeout);
4168         }
4169 }
4170
4171 static int
4172 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4173         int task_attr, int retry_count, int timeout)
4174 {
4175         union ccb *ccb;
4176         u_int32_t flags = CAM_DIR_NONE;
4177         u_int8_t *data_ptr = NULL;
4178         u_int8_t cdb[20];
4179         u_int8_t atacmd[12];
4180         struct get_hook hook;
4181         int c, data_bytes = 0, valid_bytes;
4182         int cdb_len = 0;
4183         int atacmd_len = 0;
4184         int dmacmd = 0;
4185         int fpdmacmd = 0;
4186         int need_res = 0;
4187         char *datastr = NULL, *tstr, *resstr = NULL;
4188         int error = 0;
4189         int fd_data = 0, fd_res = 0;
4190         int retval;
4191
4192         ccb = cam_getccb(device);
4193
4194         if (ccb == NULL) {
4195                 warnx("scsicmd: error allocating ccb");
4196                 return(1);
4197         }
4198
4199         CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
4200
4201         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4202                 switch(c) {
4203                 case 'a':
4204                         tstr = optarg;
4205                         while (isspace(*tstr) && (*tstr != '\0'))
4206                                 tstr++;
4207                         hook.argc = argc - optind;
4208                         hook.argv = argv + optind;
4209                         hook.got = 0;
4210                         atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4211                                                     iget, &hook);
4212                         /*
4213                          * Increment optind by the number of arguments the
4214                          * encoding routine processed.  After each call to
4215                          * getopt(3), optind points to the argument that
4216                          * getopt should process _next_.  In this case,
4217                          * that means it points to the first command string
4218                          * argument, if there is one.  Once we increment
4219                          * this, it should point to either the next command
4220                          * line argument, or it should be past the end of
4221                          * the list.
4222                          */
4223                         optind += hook.got;
4224                         break;
4225                 case 'c':
4226                         tstr = optarg;
4227                         while (isspace(*tstr) && (*tstr != '\0'))
4228                                 tstr++;
4229                         hook.argc = argc - optind;
4230                         hook.argv = argv + optind;
4231                         hook.got = 0;
4232                         cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4233                                                     iget, &hook);
4234                         /*
4235                          * Increment optind by the number of arguments the
4236                          * encoding routine processed.  After each call to
4237                          * getopt(3), optind points to the argument that
4238                          * getopt should process _next_.  In this case,
4239                          * that means it points to the first command string
4240                          * argument, if there is one.  Once we increment
4241                          * this, it should point to either the next command
4242                          * line argument, or it should be past the end of
4243                          * the list.
4244                          */
4245                         optind += hook.got;
4246                         break;
4247                 case 'd':
4248                         dmacmd = 1;
4249                         break;
4250                 case 'f':
4251                         fpdmacmd = 1;
4252                         break;
4253                 case 'i':
4254                         if (arglist & CAM_ARG_CMD_OUT) {
4255                                 warnx("command must either be "
4256                                       "read or write, not both");
4257                                 error = 1;
4258                                 goto scsicmd_bailout;
4259                         }
4260                         arglist |= CAM_ARG_CMD_IN;
4261                         flags = CAM_DIR_IN;
4262                         data_bytes = strtol(optarg, NULL, 0);
4263                         if (data_bytes <= 0) {
4264                                 warnx("invalid number of input bytes %d",
4265                                       data_bytes);
4266                                 error = 1;
4267                                 goto scsicmd_bailout;
4268                         }
4269                         hook.argc = argc - optind;
4270                         hook.argv = argv + optind;
4271                         hook.got = 0;
4272                         optind++;
4273                         datastr = cget(&hook, NULL);
4274                         /*
4275                          * If the user supplied "-" instead of a format, he
4276                          * wants the data to be written to stdout.
4277                          */
4278                         if ((datastr != NULL)
4279                          && (datastr[0] == '-'))
4280                                 fd_data = 1;
4281
4282                         data_ptr = (u_int8_t *)malloc(data_bytes);
4283                         if (data_ptr == NULL) {
4284                                 warnx("can't malloc memory for data_ptr");
4285                                 error = 1;
4286                                 goto scsicmd_bailout;
4287                         }
4288                         break;
4289                 case 'o':
4290                         if (arglist & CAM_ARG_CMD_IN) {
4291                                 warnx("command must either be "
4292                                       "read or write, not both");
4293                                 error = 1;
4294                                 goto scsicmd_bailout;
4295                         }
4296                         arglist |= CAM_ARG_CMD_OUT;
4297                         flags = CAM_DIR_OUT;
4298                         data_bytes = strtol(optarg, NULL, 0);
4299                         if (data_bytes <= 0) {
4300                                 warnx("invalid number of output bytes %d",
4301                                       data_bytes);
4302                                 error = 1;
4303                                 goto scsicmd_bailout;
4304                         }
4305                         hook.argc = argc - optind;
4306                         hook.argv = argv + optind;
4307                         hook.got = 0;
4308                         datastr = cget(&hook, NULL);
4309                         data_ptr = (u_int8_t *)malloc(data_bytes);
4310                         if (data_ptr == NULL) {
4311                                 warnx("can't malloc memory for data_ptr");
4312                                 error = 1;
4313                                 goto scsicmd_bailout;
4314                         }
4315                         bzero(data_ptr, data_bytes);
4316                         /*
4317                          * If the user supplied "-" instead of a format, he
4318                          * wants the data to be read from stdin.
4319                          */
4320                         if ((datastr != NULL)
4321                          && (datastr[0] == '-'))
4322                                 fd_data = 1;
4323                         else
4324                                 buff_encode_visit(data_ptr, data_bytes, datastr,
4325                                                   iget, &hook);
4326                         optind += hook.got;
4327                         break;
4328                 case 'r':
4329                         need_res = 1;
4330                         hook.argc = argc - optind;
4331                         hook.argv = argv + optind;
4332                         hook.got = 0;
4333                         resstr = cget(&hook, NULL);
4334                         if ((resstr != NULL) && (resstr[0] == '-'))
4335                                 fd_res = 1;
4336                         optind += hook.got;
4337                         break;
4338                 default:
4339                         break;
4340                 }
4341         }
4342
4343         /*
4344          * If fd_data is set, and we're writing to the device, we need to
4345          * read the data the user wants written from stdin.
4346          */
4347         if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4348                 ssize_t amt_read;
4349                 int amt_to_read = data_bytes;
4350                 u_int8_t *buf_ptr = data_ptr;
4351
4352                 for (amt_read = 0; amt_to_read > 0;
4353                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4354                         if (amt_read == -1) {
4355                                 warn("error reading data from stdin");
4356                                 error = 1;
4357                                 goto scsicmd_bailout;
4358                         }
4359                         amt_to_read -= amt_read;
4360                         buf_ptr += amt_read;
4361                 }
4362         }
4363
4364         if (arglist & CAM_ARG_ERR_RECOVER)
4365                 flags |= CAM_PASS_ERR_RECOVER;
4366
4367         /* Disable freezing the device queue */
4368         flags |= CAM_DEV_QFRZDIS;
4369
4370         if (cdb_len) {
4371                 /*
4372                  * This is taken from the SCSI-3 draft spec.
4373                  * (T10/1157D revision 0.3)
4374                  * The top 3 bits of an opcode are the group code.
4375                  * The next 5 bits are the command code.
4376                  * Group 0:  six byte commands
4377                  * Group 1:  ten byte commands
4378                  * Group 2:  ten byte commands
4379                  * Group 3:  reserved
4380                  * Group 4:  sixteen byte commands
4381                  * Group 5:  twelve byte commands
4382                  * Group 6:  vendor specific
4383                  * Group 7:  vendor specific
4384                  */
4385                 switch((cdb[0] >> 5) & 0x7) {
4386                         case 0:
4387                                 cdb_len = 6;
4388                                 break;
4389                         case 1:
4390                         case 2:
4391                                 cdb_len = 10;
4392                                 break;
4393                         case 3:
4394                         case 6:
4395                         case 7:
4396                                 /* computed by buff_encode_visit */
4397                                 break;
4398                         case 4:
4399                                 cdb_len = 16;
4400                                 break;
4401                         case 5:
4402                                 cdb_len = 12;
4403                                 break;
4404                 }
4405
4406                 /*
4407                  * We should probably use csio_build_visit or something like that
4408                  * here, but it's easier to encode arguments as you go.  The
4409                  * alternative would be skipping the CDB argument and then encoding
4410                  * it here, since we've got the data buffer argument by now.
4411                  */
4412                 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4413
4414                 cam_fill_csio(&ccb->csio,
4415                       /*retries*/ retry_count,
4416                       /*cbfcnp*/ NULL,
4417                       /*flags*/ flags,
4418                       /*tag_action*/ task_attr,
4419                       /*data_ptr*/ data_ptr,
4420                       /*dxfer_len*/ data_bytes,
4421                       /*sense_len*/ SSD_FULL_SIZE,
4422                       /*cdb_len*/ cdb_len,
4423                       /*timeout*/ timeout ? timeout : 5000);
4424         } else {
4425                 atacmd_len = 12;
4426                 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4427                 if (need_res)
4428                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4429                 if (dmacmd)
4430                         ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4431                 if (fpdmacmd)
4432                         ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4433
4434                 cam_fill_ataio(&ccb->ataio,
4435                       /*retries*/ retry_count,
4436                       /*cbfcnp*/ NULL,
4437                       /*flags*/ flags,
4438                       /*tag_action*/ 0,
4439                       /*data_ptr*/ data_ptr,
4440                       /*dxfer_len*/ data_bytes,
4441                       /*timeout*/ timeout ? timeout : 5000);
4442         }
4443
4444         if (((retval = cam_send_ccb(device, ccb)) < 0)
4445          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4446                 const char warnstr[] = "error sending command";
4447
4448                 if (retval < 0)
4449                         warn(warnstr);
4450                 else
4451                         warnx(warnstr);
4452
4453                 if (arglist & CAM_ARG_VERBOSE) {
4454                         cam_error_print(device, ccb, CAM_ESF_ALL,
4455                                         CAM_EPF_ALL, stderr);
4456                 }
4457
4458                 error = 1;
4459                 goto scsicmd_bailout;
4460         }
4461
4462         if (atacmd_len && need_res) {
4463                 if (fd_res == 0) {
4464                         buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4465                                           arg_put, NULL);
4466                         fprintf(stdout, "\n");
4467                 } else {
4468                         fprintf(stdout,
4469                             "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4470                             ccb->ataio.res.status,
4471                             ccb->ataio.res.error,
4472                             ccb->ataio.res.lba_low,
4473                             ccb->ataio.res.lba_mid,
4474                             ccb->ataio.res.lba_high,
4475                             ccb->ataio.res.device,
4476                             ccb->ataio.res.lba_low_exp,
4477                             ccb->ataio.res.lba_mid_exp,
4478                             ccb->ataio.res.lba_high_exp,
4479                             ccb->ataio.res.sector_count,
4480                             ccb->ataio.res.sector_count_exp);
4481                         fflush(stdout);
4482                 }
4483         }
4484
4485         if (cdb_len)
4486                 valid_bytes = ccb->csio.dxfer_len - ccb->csio.resid;
4487         else
4488                 valid_bytes = ccb->ataio.dxfer_len - ccb->ataio.resid;
4489         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4490          && (arglist & CAM_ARG_CMD_IN)
4491          && (valid_bytes > 0)) {
4492                 if (fd_data == 0) {
4493                         buff_decode_visit(data_ptr, valid_bytes, datastr,
4494                                           arg_put, NULL);
4495                         fprintf(stdout, "\n");
4496                 } else {
4497                         ssize_t amt_written;
4498                         int amt_to_write = valid_bytes;
4499                         u_int8_t *buf_ptr = data_ptr;
4500
4501                         for (amt_written = 0; (amt_to_write > 0) &&
4502                              (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4503                                 amt_to_write -= amt_written;
4504                                 buf_ptr += amt_written;
4505                         }
4506                         if (amt_written == -1) {
4507                                 warn("error writing data to stdout");
4508                                 error = 1;
4509                                 goto scsicmd_bailout;
4510                         } else if ((amt_written == 0)
4511                                 && (amt_to_write > 0)) {
4512                                 warnx("only wrote %u bytes out of %u",
4513                                       valid_bytes - amt_to_write, valid_bytes);
4514                         }
4515                 }
4516         }
4517
4518 scsicmd_bailout:
4519
4520         if ((data_bytes > 0) && (data_ptr != NULL))
4521                 free(data_ptr);
4522
4523         cam_freeccb(ccb);
4524
4525         return(error);
4526 }
4527
4528 static int
4529 camdebug(int argc, char **argv, char *combinedopt)
4530 {
4531         int c, fd;
4532         path_id_t bus = CAM_BUS_WILDCARD;
4533         target_id_t target = CAM_TARGET_WILDCARD;
4534         lun_id_t lun = CAM_LUN_WILDCARD;
4535         char *tstr, *tmpstr = NULL;
4536         union ccb ccb;
4537         int error = 0;
4538
4539         bzero(&ccb, sizeof(union ccb));
4540
4541         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4542                 switch(c) {
4543                 case 'I':
4544                         arglist |= CAM_ARG_DEBUG_INFO;
4545                         ccb.cdbg.flags |= CAM_DEBUG_INFO;
4546                         break;
4547                 case 'P':
4548                         arglist |= CAM_ARG_DEBUG_PERIPH;
4549                         ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4550                         break;
4551                 case 'S':
4552                         arglist |= CAM_ARG_DEBUG_SUBTRACE;
4553                         ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4554                         break;
4555                 case 'T':
4556                         arglist |= CAM_ARG_DEBUG_TRACE;
4557                         ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4558                         break;
4559                 case 'X':
4560                         arglist |= CAM_ARG_DEBUG_XPT;
4561                         ccb.cdbg.flags |= CAM_DEBUG_XPT;
4562                         break;
4563                 case 'c':
4564                         arglist |= CAM_ARG_DEBUG_CDB;
4565                         ccb.cdbg.flags |= CAM_DEBUG_CDB;
4566                         break;
4567                 case 'p':
4568                         arglist |= CAM_ARG_DEBUG_PROBE;
4569                         ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4570                         break;
4571                 default:
4572                         break;
4573                 }
4574         }
4575
4576         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4577                 warnx("error opening transport layer device %s", XPT_DEVICE);
4578                 warn("%s", XPT_DEVICE);
4579                 return(1);
4580         }
4581         argc -= optind;
4582         argv += optind;
4583
4584         if (argc <= 0) {
4585                 warnx("you must specify \"off\", \"all\" or a bus,");
4586                 warnx("bus:target, or bus:target:lun");
4587                 close(fd);
4588                 return(1);
4589         }
4590
4591         tstr = *argv;
4592
4593         while (isspace(*tstr) && (*tstr != '\0'))
4594                 tstr++;
4595
4596         if (strncmp(tstr, "off", 3) == 0) {
4597                 ccb.cdbg.flags = CAM_DEBUG_NONE;
4598                 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4599                              CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4600                              CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4601         } else if (strncmp(tstr, "all", 3) != 0) {
4602                 tmpstr = (char *)strtok(tstr, ":");
4603                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4604                         bus = strtol(tmpstr, NULL, 0);
4605                         arglist |= CAM_ARG_BUS;
4606                         tmpstr = (char *)strtok(NULL, ":");
4607                         if ((tmpstr != NULL) && (*tmpstr != '\0')){
4608                                 target = strtol(tmpstr, NULL, 0);
4609                                 arglist |= CAM_ARG_TARGET;
4610                                 tmpstr = (char *)strtok(NULL, ":");
4611                                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4612                                         lun = strtol(tmpstr, NULL, 0);
4613                                         arglist |= CAM_ARG_LUN;
4614                                 }
4615                         }
4616                 } else {
4617                         error = 1;
4618                         warnx("you must specify \"all\", \"off\", or a bus,");
4619                         warnx("bus:target, or bus:target:lun to debug");
4620                 }
4621         }
4622
4623         if (error == 0) {
4624
4625                 ccb.ccb_h.func_code = XPT_DEBUG;
4626                 ccb.ccb_h.path_id = bus;
4627                 ccb.ccb_h.target_id = target;
4628                 ccb.ccb_h.target_lun = lun;
4629
4630                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4631                         warn("CAMIOCOMMAND ioctl failed");
4632                         error = 1;
4633                 }
4634
4635                 if (error == 0) {
4636                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4637                              CAM_FUNC_NOTAVAIL) {
4638                                 warnx("CAM debugging not available");
4639                                 warnx("you need to put options CAMDEBUG in"
4640                                       " your kernel config file!");
4641                                 error = 1;
4642                         } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4643                                     CAM_REQ_CMP) {
4644                                 warnx("XPT_DEBUG CCB failed with status %#x",
4645                                       ccb.ccb_h.status);
4646                                 error = 1;
4647                         } else {
4648                                 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4649                                         fprintf(stderr,
4650                                                 "Debugging turned off\n");
4651                                 } else {
4652                                         fprintf(stderr,
4653                                                 "Debugging enabled for "
4654                                                 "%d:%d:%jx\n",
4655                                                 bus, target, (uintmax_t)lun);
4656                                 }
4657                         }
4658                 }
4659                 close(fd);
4660         }
4661
4662         return(error);
4663 }
4664
4665 static int
4666 tagcontrol(struct cam_device *device, int argc, char **argv,
4667            char *combinedopt)
4668 {
4669         int c;
4670         union ccb *ccb;
4671         int numtags = -1;
4672         int retval = 0;
4673         int quiet = 0;
4674         char pathstr[1024];
4675
4676         ccb = cam_getccb(device);
4677
4678         if (ccb == NULL) {
4679                 warnx("tagcontrol: error allocating ccb");
4680                 return(1);
4681         }
4682
4683         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4684                 switch(c) {
4685                 case 'N':
4686                         numtags = strtol(optarg, NULL, 0);
4687                         if (numtags < 0) {
4688                                 warnx("tag count %d is < 0", numtags);
4689                                 retval = 1;
4690                                 goto tagcontrol_bailout;
4691                         }
4692                         break;
4693                 case 'q':
4694                         quiet++;
4695                         break;
4696                 default:
4697                         break;
4698                 }
4699         }
4700
4701         cam_path_string(device, pathstr, sizeof(pathstr));
4702
4703         if (numtags >= 0) {
4704                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->crs);
4705                 ccb->ccb_h.func_code = XPT_REL_SIMQ;
4706                 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4707                 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4708                 ccb->crs.openings = numtags;
4709
4710
4711                 if (cam_send_ccb(device, ccb) < 0) {
4712                         perror("error sending XPT_REL_SIMQ CCB");
4713                         retval = 1;
4714                         goto tagcontrol_bailout;
4715                 }
4716
4717                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4718                         warnx("XPT_REL_SIMQ CCB failed");
4719                         cam_error_print(device, ccb, CAM_ESF_ALL,
4720                                         CAM_EPF_ALL, stderr);
4721                         retval = 1;
4722                         goto tagcontrol_bailout;
4723                 }
4724
4725
4726                 if (quiet == 0)
4727                         fprintf(stdout, "%stagged openings now %d\n",
4728                                 pathstr, ccb->crs.openings);
4729         }
4730
4731         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgds);
4732
4733         ccb->ccb_h.func_code = XPT_GDEV_STATS;
4734
4735         if (cam_send_ccb(device, ccb) < 0) {
4736                 perror("error sending XPT_GDEV_STATS CCB");
4737                 retval = 1;
4738                 goto tagcontrol_bailout;
4739         }
4740
4741         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4742                 warnx("XPT_GDEV_STATS CCB failed");
4743                 cam_error_print(device, ccb, CAM_ESF_ALL,
4744                                 CAM_EPF_ALL, stderr);
4745                 retval = 1;
4746                 goto tagcontrol_bailout;
4747         }
4748
4749         if (arglist & CAM_ARG_VERBOSE) {
4750                 fprintf(stdout, "%s", pathstr);
4751                 fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4752                 fprintf(stdout, "%s", pathstr);
4753                 fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4754                 fprintf(stdout, "%s", pathstr);
4755                 fprintf(stdout, "allocated     %d\n", ccb->cgds.allocated);
4756                 fprintf(stdout, "%s", pathstr);
4757                 fprintf(stdout, "queued        %d\n", ccb->cgds.queued);
4758                 fprintf(stdout, "%s", pathstr);
4759                 fprintf(stdout, "held          %d\n", ccb->cgds.held);
4760                 fprintf(stdout, "%s", pathstr);
4761                 fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4762                 fprintf(stdout, "%s", pathstr);
4763                 fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4764         } else {
4765                 if (quiet == 0) {
4766                         fprintf(stdout, "%s", pathstr);
4767                         fprintf(stdout, "device openings: ");
4768                 }
4769                 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4770                         ccb->cgds.dev_active);
4771         }
4772
4773 tagcontrol_bailout:
4774
4775         cam_freeccb(ccb);
4776         return(retval);
4777 }
4778
4779 static void
4780 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4781 {
4782         char pathstr[1024];
4783
4784         cam_path_string(device, pathstr, sizeof(pathstr));
4785
4786         if (cts->transport == XPORT_SPI) {
4787                 struct ccb_trans_settings_spi *spi =
4788                     &cts->xport_specific.spi;
4789
4790                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4791
4792                         fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4793                                 spi->sync_period);
4794
4795                         if (spi->sync_offset != 0) {
4796                                 u_int freq;
4797
4798                                 freq = scsi_calc_syncsrate(spi->sync_period);
4799                                 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4800                                         pathstr, freq / 1000, freq % 1000);
4801                         }
4802                 }
4803
4804                 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4805                         fprintf(stdout, "%soffset: %d\n", pathstr,
4806                             spi->sync_offset);
4807                 }
4808
4809                 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4810                         fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4811                                 (0x01 << spi->bus_width) * 8);
4812                 }
4813
4814                 if (spi->valid & CTS_SPI_VALID_DISC) {
4815                         fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4816                                 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4817                                 "enabled" : "disabled");
4818                 }
4819         }
4820         if (cts->transport == XPORT_FC) {
4821                 struct ccb_trans_settings_fc *fc =
4822                     &cts->xport_specific.fc;
4823
4824                 if (fc->valid & CTS_FC_VALID_WWNN)
4825                         fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4826                             (long long) fc->wwnn);
4827                 if (fc->valid & CTS_FC_VALID_WWPN)
4828                         fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4829                             (long long) fc->wwpn);
4830                 if (fc->valid & CTS_FC_VALID_PORT)
4831                         fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4832                 if (fc->valid & CTS_FC_VALID_SPEED)
4833                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4834                             pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4835         }
4836         if (cts->transport == XPORT_SAS) {
4837                 struct ccb_trans_settings_sas *sas =
4838                     &cts->xport_specific.sas;
4839
4840                 if (sas->valid & CTS_SAS_VALID_SPEED)
4841                         fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4842                             pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4843         }
4844         if (cts->transport == XPORT_ATA) {
4845                 struct ccb_trans_settings_pata *pata =
4846                     &cts->xport_specific.ata;
4847
4848                 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4849                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4850                                 ata_mode2string(pata->mode));
4851                 }
4852                 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4853                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4854                                 pata->atapi);
4855                 }
4856                 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4857                         fprintf(stdout, "%sPIO transaction length: %d\n",
4858                                 pathstr, pata->bytecount);
4859                 }
4860         }
4861         if (cts->transport == XPORT_SATA) {
4862                 struct ccb_trans_settings_sata *sata =
4863                     &cts->xport_specific.sata;
4864
4865                 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4866                         fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4867                                 sata->revision);
4868                 }
4869                 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4870                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
4871                                 ata_mode2string(sata->mode));
4872                 }
4873                 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4874                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4875                                 sata->atapi);
4876                 }
4877                 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4878                         fprintf(stdout, "%sPIO transaction length: %d\n",
4879                                 pathstr, sata->bytecount);
4880                 }
4881                 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4882                         fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4883                                 sata->pm_present);
4884                 }
4885                 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4886                         fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4887                                 sata->tags);
4888                 }
4889                 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4890                         fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4891                                 sata->caps);
4892                 }
4893         }
4894         if (cts->protocol == PROTO_ATA) {
4895                 struct ccb_trans_settings_ata *ata=
4896                     &cts->proto_specific.ata;
4897
4898                 if (ata->valid & CTS_ATA_VALID_TQ) {
4899                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4900                                 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4901                                 "enabled" : "disabled");
4902                 }
4903         }
4904         if (cts->protocol == PROTO_SCSI) {
4905                 struct ccb_trans_settings_scsi *scsi=
4906                     &cts->proto_specific.scsi;
4907
4908                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
4909                         fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4910                                 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4911                                 "enabled" : "disabled");
4912                 }
4913         }
4914
4915 }
4916
4917 /*
4918  * Get a path inquiry CCB for the specified device.
4919  */
4920 static int
4921 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4922 {
4923         union ccb *ccb;
4924         int retval = 0;
4925
4926         ccb = cam_getccb(device);
4927         if (ccb == NULL) {
4928                 warnx("get_cpi: couldn't allocate CCB");
4929                 return(1);
4930         }
4931         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
4932         ccb->ccb_h.func_code = XPT_PATH_INQ;
4933         if (cam_send_ccb(device, ccb) < 0) {
4934                 warn("get_cpi: error sending Path Inquiry CCB");
4935                 if (arglist & CAM_ARG_VERBOSE)
4936                         cam_error_print(device, ccb, CAM_ESF_ALL,
4937                                         CAM_EPF_ALL, stderr);
4938                 retval = 1;
4939                 goto get_cpi_bailout;
4940         }
4941         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4942                 if (arglist & CAM_ARG_VERBOSE)
4943                         cam_error_print(device, ccb, CAM_ESF_ALL,
4944                                         CAM_EPF_ALL, stderr);
4945                 retval = 1;
4946                 goto get_cpi_bailout;
4947         }
4948         bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4949
4950 get_cpi_bailout:
4951         cam_freeccb(ccb);
4952         return(retval);
4953 }
4954
4955 /*
4956  * Get a get device CCB for the specified device.
4957  */
4958 static int
4959 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4960 {
4961         union ccb *ccb;
4962         int retval = 0;
4963
4964         ccb = cam_getccb(device);
4965         if (ccb == NULL) {
4966                 warnx("get_cgd: couldn't allocate CCB");
4967                 return(1);
4968         }
4969         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgd);
4970         ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4971         if (cam_send_ccb(device, ccb) < 0) {
4972                 warn("get_cgd: error sending Path Inquiry CCB");
4973                 if (arglist & CAM_ARG_VERBOSE)
4974                         cam_error_print(device, ccb, CAM_ESF_ALL,
4975                                         CAM_EPF_ALL, stderr);
4976                 retval = 1;
4977                 goto get_cgd_bailout;
4978         }
4979         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4980                 if (arglist & CAM_ARG_VERBOSE)
4981                         cam_error_print(device, ccb, CAM_ESF_ALL,
4982                                         CAM_EPF_ALL, stderr);
4983                 retval = 1;
4984                 goto get_cgd_bailout;
4985         }
4986         bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4987
4988 get_cgd_bailout:
4989         cam_freeccb(ccb);
4990         return(retval);
4991 }
4992
4993 /*
4994  * Returns 1 if the device has the VPD page, 0 if it does not, and -1 on an
4995  * error.
4996  */
4997 int
4998 dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count,
4999                  int timeout, int verbosemode)
5000 {
5001         union ccb *ccb = NULL;
5002         struct scsi_vpd_supported_page_list sup_pages;
5003         int i;
5004         int retval = 0;
5005
5006         ccb = cam_getccb(dev);
5007         if (ccb == NULL) {
5008                 warn("Unable to allocate CCB");
5009                 retval = -1;
5010                 goto bailout;
5011         }
5012         
5013         /* cam_getccb cleans up the header, caller has to zero the payload */
5014         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5015
5016         bzero(&sup_pages, sizeof(sup_pages));
5017
5018         scsi_inquiry(&ccb->csio,
5019                      /*retries*/ retry_count,
5020                      /*cbfcnp*/ NULL,
5021                      /* tag_action */ MSG_SIMPLE_Q_TAG,
5022                      /* inq_buf */ (u_int8_t *)&sup_pages,
5023                      /* inq_len */ sizeof(sup_pages),
5024                      /* evpd */ 1,
5025                      /* page_code */ SVPD_SUPPORTED_PAGE_LIST,
5026                      /* sense_len */ SSD_FULL_SIZE,
5027                      /* timeout */ timeout ? timeout : 5000);
5028
5029         /* Disable freezing the device queue */
5030         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5031
5032         if (retry_count != 0)
5033                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5034
5035         if (cam_send_ccb(dev, ccb) < 0) {
5036                 cam_freeccb(ccb);
5037                 ccb = NULL;
5038                 retval = -1;
5039                 goto bailout;
5040         }
5041
5042         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5043                 if (verbosemode != 0)
5044                         cam_error_print(dev, ccb, CAM_ESF_ALL,
5045                                         CAM_EPF_ALL, stderr);
5046                 retval = -1;
5047                 goto bailout;
5048         }
5049
5050         for (i = 0; i < sup_pages.length; i++) {
5051                 if (sup_pages.list[i] == page_id) {
5052                         retval = 1;
5053                         goto bailout;
5054                 }
5055         }
5056 bailout:
5057         if (ccb != NULL)
5058                 cam_freeccb(ccb);
5059         
5060         return (retval);
5061 }
5062
5063 /*
5064  * devtype is filled in with the type of device.
5065  * Returns 0 for success, non-zero for failure.
5066  */
5067 int
5068 get_device_type(struct cam_device *dev, int retry_count, int timeout,
5069                     int verbosemode, camcontrol_devtype *devtype)
5070 {
5071         struct ccb_getdev cgd;
5072         int retval = 0;
5073
5074         retval = get_cgd(dev, &cgd);
5075         if (retval != 0)
5076                 goto bailout;
5077
5078         switch (cgd.protocol) {
5079         case PROTO_SCSI:
5080                 break;
5081         case PROTO_ATA:
5082         case PROTO_ATAPI:
5083         case PROTO_SATAPM:
5084                 *devtype = CC_DT_ATA;
5085                 goto bailout;
5086                 break; /*NOTREACHED*/
5087         default:
5088                 *devtype = CC_DT_UNKNOWN;
5089                 goto bailout; 
5090                 break; /*NOTREACHED*/
5091         }
5092
5093         /*
5094          * Check for the ATA Information VPD page (0x89).  If this is an
5095          * ATA device behind a SCSI to ATA translation layer, this VPD page
5096          * should be present.
5097          *
5098          * If that VPD page isn't present, or we get an error back from the
5099          * INQUIRY command, we'll just treat it as a normal SCSI device.
5100          */
5101         retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5102                                   timeout, verbosemode);
5103         if (retval == 1)
5104                 *devtype = CC_DT_ATA_BEHIND_SCSI;
5105         else
5106                 *devtype = CC_DT_SCSI;
5107
5108         retval = 0;
5109
5110 bailout:
5111         return (retval);
5112 }
5113
5114 int
5115 build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5116     uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5117     uint16_t sector_count, uint64_t lba, uint8_t command, uint32_t auxiliary,
5118     uint8_t *data_ptr, uint32_t dxfer_len, uint8_t *cdb_storage,
5119     size_t cdb_storage_len, uint8_t sense_len, uint32_t timeout,
5120     int is48bit, camcontrol_devtype devtype)
5121 {
5122         int retval = 0;
5123
5124         if (devtype == CC_DT_ATA) {
5125                 cam_fill_ataio(&ccb->ataio,
5126                     /*retries*/ retry_count,
5127                     /*cbfcnp*/ NULL,
5128                     /*flags*/ flags,
5129                     /*tag_action*/ tag_action,
5130                     /*data_ptr*/ data_ptr,
5131                     /*dxfer_len*/ dxfer_len,
5132                     /*timeout*/ timeout);
5133                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5134                         ata_48bit_cmd(&ccb->ataio, command, features, lba,
5135                             sector_count);
5136                 else
5137                         ata_28bit_cmd(&ccb->ataio, command, features, lba,
5138                             sector_count);
5139
5140                 if (auxiliary != 0) {
5141                         ccb->ataio.ata_flags |= ATA_FLAG_AUX;
5142                         ccb->ataio.aux = auxiliary;
5143                 }
5144
5145                 if (ata_flags & AP_FLAG_CHK_COND)
5146                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
5147
5148                 if ((protocol & AP_PROTO_MASK) == AP_PROTO_DMA)
5149                         ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
5150                 else if ((protocol & AP_PROTO_MASK) == AP_PROTO_FPDMA)
5151                         ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
5152         } else {
5153                 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5154                         protocol |= AP_EXTEND;
5155
5156                 retval = scsi_ata_pass(&ccb->csio,
5157                     /*retries*/ retry_count,
5158                     /*cbfcnp*/ NULL,
5159                     /*flags*/ flags,
5160                     /*tag_action*/ tag_action,
5161                     /*protocol*/ protocol,
5162                     /*ata_flags*/ ata_flags,
5163                     /*features*/ features,
5164                     /*sector_count*/ sector_count, 
5165                     /*lba*/ lba,
5166                     /*command*/ command,
5167                     /*device*/ 0,
5168                     /*icc*/ 0,
5169                     /*auxiliary*/ auxiliary,
5170                     /*control*/ 0,
5171                     /*data_ptr*/ data_ptr,
5172                     /*dxfer_len*/ dxfer_len,
5173                     /*cdb_storage*/ cdb_storage,
5174                     /*cdb_storage_len*/ cdb_storage_len,
5175                     /*minimum_cmd_size*/ 0,
5176                     /*sense_len*/ sense_len,
5177                     /*timeout*/ timeout);
5178         }
5179
5180         return (retval);
5181 }
5182
5183 int
5184 get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
5185                uint16_t *count, uint64_t *lba, uint8_t *device, uint8_t *status)
5186 {
5187         int retval = 0;
5188
5189         switch (ccb->ccb_h.func_code) {
5190         case XPT_SCSI_IO: {
5191                 uint8_t opcode;
5192                 int error_code = 0, sense_key = 0, asc = 0, ascq = 0;
5193
5194                 /*
5195                  * In this case, we have SCSI ATA PASS-THROUGH command, 12
5196                  * or 16 byte, and need to see what 
5197                  */
5198                 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
5199                         opcode = ccb->csio.cdb_io.cdb_ptr[0];
5200                 else
5201                         opcode = ccb->csio.cdb_io.cdb_bytes[0];
5202                 if ((opcode != ATA_PASS_12)
5203                  && (opcode != ATA_PASS_16)) {
5204                         retval = 1;
5205                         warnx("%s: unsupported opcode %02x", __func__, opcode);
5206                         goto bailout;
5207                 }
5208
5209                 retval = scsi_extract_sense_ccb(ccb, &error_code, &sense_key,
5210                                                 &asc, &ascq);
5211                 /* Note: the _ccb() variant returns 0 for an error */
5212                 if (retval == 0) {
5213                         retval = 1;
5214                         goto bailout;
5215                 } else
5216                         retval = 0;
5217
5218                 switch (error_code) {
5219                 case SSD_DESC_CURRENT_ERROR:
5220                 case SSD_DESC_DEFERRED_ERROR: {
5221                         struct scsi_sense_data_desc *sense;
5222                         struct scsi_sense_ata_ret_desc *desc;
5223                         uint8_t *desc_ptr;
5224
5225                         sense = (struct scsi_sense_data_desc *)
5226                             &ccb->csio.sense_data;
5227
5228                         desc_ptr = scsi_find_desc(sense, ccb->csio.sense_len -
5229                             ccb->csio.sense_resid, SSD_DESC_ATA);
5230                         if (desc_ptr == NULL) {
5231                                 cam_error_print(dev, ccb, CAM_ESF_ALL,
5232                                     CAM_EPF_ALL, stderr);
5233                                 retval = 1;
5234                                 goto bailout;
5235                         }
5236                         desc = (struct scsi_sense_ata_ret_desc *)desc_ptr;
5237
5238                         *error = desc->error;
5239                         *count = (desc->count_15_8 << 8) |
5240                                   desc->count_7_0;
5241                         *lba = ((uint64_t)desc->lba_47_40 << 40) |
5242                                ((uint64_t)desc->lba_39_32 << 32) |
5243                                ((uint64_t)desc->lba_31_24 << 24) |
5244                                (desc->lba_23_16 << 16) |
5245                                (desc->lba_15_8  <<  8) |
5246                                 desc->lba_7_0;
5247                         *device = desc->device;
5248                         *status = desc->status;
5249
5250                         /*
5251                          * If the extend bit isn't set, the result is for a
5252                          * 12-byte ATA PASS-THROUGH command or a 16 or 32 byte
5253                          * command without the extend bit set.  This means
5254                          * that the device is supposed to return 28-bit
5255                          * status.  The count field is only 8 bits, and the
5256                          * LBA field is only 8 bits.
5257                          */
5258                         if ((desc->flags & SSD_DESC_ATA_FLAG_EXTEND) == 0){
5259                                 *count &= 0xff;
5260                                 *lba &= 0x0fffffff;
5261                         }
5262                         break;
5263                 }
5264                 case SSD_CURRENT_ERROR:
5265                 case SSD_DEFERRED_ERROR: {
5266 #if 0
5267                         struct scsi_sense_data_fixed *sense;
5268 #endif
5269                         /*
5270                          * XXX KDM need to support fixed sense data.
5271                          */
5272                         warnx("%s: Fixed sense data not supported yet",
5273                             __func__);
5274                         retval = 1;
5275                         goto bailout;
5276                         break; /*NOTREACHED*/
5277                 }
5278                 default:
5279                         retval = 1;
5280                         goto bailout;
5281                         break;
5282                 }
5283
5284                 break;
5285         }
5286         case XPT_ATA_IO: {
5287                 struct ata_res *res;
5288
5289                 /*
5290                  * In this case, we have an ATA command, and we need to
5291                  * fill in the requested values from the result register
5292                  * set.
5293                  */
5294                 res = &ccb->ataio.res;
5295                 *error = res->error;
5296                 *status = res->status;
5297                 *device = res->device; 
5298                 *count = res->sector_count;
5299                 *lba = (res->lba_high << 16) |
5300                        (res->lba_mid << 8) |
5301                        (res->lba_low);
5302                 if (res->flags & CAM_ATAIO_48BIT) {
5303                         *count |= (res->sector_count_exp << 8);
5304                         *lba |= ((uint64_t)res->lba_low_exp << 24) |
5305                                 ((uint64_t)res->lba_mid_exp << 32) |
5306                                 ((uint64_t)res->lba_high_exp << 40);
5307                 } else {
5308                         *lba |= (res->device & 0xf) << 24;
5309                 }
5310                 break;
5311         }
5312         default:
5313                 retval = 1;
5314                 break;
5315         }
5316 bailout:
5317         return (retval);
5318 }
5319
5320 static void
5321 cpi_print(struct ccb_pathinq *cpi)
5322 {
5323         char adapter_str[1024];
5324         int i;
5325
5326         snprintf(adapter_str, sizeof(adapter_str),
5327                  "%s%d:", cpi->dev_name, cpi->unit_number);
5328
5329         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5330                 cpi->version_num);
5331
5332         for (i = 1; i < 0xff; i = i << 1) {
5333                 const char *str;
5334
5335                 if ((i & cpi->hba_inquiry) == 0)
5336                         continue;
5337
5338                 fprintf(stdout, "%s supports ", adapter_str);
5339
5340                 switch(i) {
5341                 case PI_MDP_ABLE:
5342                         str = "MDP message";
5343                         break;
5344                 case PI_WIDE_32:
5345                         str = "32 bit wide SCSI";
5346                         break;
5347                 case PI_WIDE_16:
5348                         str = "16 bit wide SCSI";
5349                         break;
5350                 case PI_SDTR_ABLE:
5351                         str = "SDTR message";
5352                         break;
5353                 case PI_LINKED_CDB:
5354                         str = "linked CDBs";
5355                         break;
5356                 case PI_TAG_ABLE:
5357                         str = "tag queue messages";
5358                         break;
5359                 case PI_SOFT_RST:
5360                         str = "soft reset alternative";
5361                         break;
5362                 case PI_SATAPM:
5363                         str = "SATA Port Multiplier";
5364                         break;
5365                 default:
5366                         str = "unknown PI bit set";
5367                         break;
5368                 }
5369                 fprintf(stdout, "%s\n", str);
5370         }
5371
5372         for (i = 1; i < 0xff; i = i << 1) {
5373                 const char *str;
5374
5375                 if ((i & cpi->hba_misc) == 0)
5376                         continue;
5377
5378                 fprintf(stdout, "%s ", adapter_str);
5379
5380                 switch(i) {
5381                 case PIM_SCANHILO:
5382                         str = "bus scans from high ID to low ID";
5383                         break;
5384                 case PIM_NOREMOVE:
5385                         str = "removable devices not included in scan";
5386                         break;
5387                 case PIM_NOINITIATOR:
5388                         str = "initiator role not supported";
5389                         break;
5390                 case PIM_NOBUSRESET:
5391                         str = "user has disabled initial BUS RESET or"
5392                               " controller is in target/mixed mode";
5393                         break;
5394                 case PIM_NO_6_BYTE:
5395                         str = "do not send 6-byte commands";
5396                         break;
5397                 case PIM_SEQSCAN:
5398                         str = "scan bus sequentially";
5399                         break;
5400                 default:
5401                         str = "unknown PIM bit set";
5402                         break;
5403                 }
5404                 fprintf(stdout, "%s\n", str);
5405         }
5406
5407         for (i = 1; i < 0xff; i = i << 1) {
5408                 const char *str;
5409
5410                 if ((i & cpi->target_sprt) == 0)
5411                         continue;
5412
5413                 fprintf(stdout, "%s supports ", adapter_str);
5414                 switch(i) {
5415                 case PIT_PROCESSOR:
5416                         str = "target mode processor mode";
5417                         break;
5418                 case PIT_PHASE:
5419                         str = "target mode phase cog. mode";
5420                         break;
5421                 case PIT_DISCONNECT:
5422                         str = "disconnects in target mode";
5423                         break;
5424                 case PIT_TERM_IO:
5425                         str = "terminate I/O message in target mode";
5426                         break;
5427                 case PIT_GRP_6:
5428                         str = "group 6 commands in target mode";
5429                         break;
5430                 case PIT_GRP_7:
5431                         str = "group 7 commands in target mode";
5432                         break;
5433                 default:
5434                         str = "unknown PIT bit set";
5435                         break;
5436                 }
5437
5438                 fprintf(stdout, "%s\n", str);
5439         }
5440         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5441                 cpi->hba_eng_cnt);
5442         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5443                 cpi->max_target);
5444         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5445                 cpi->max_lun);
5446         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5447                 adapter_str, cpi->hpath_id);
5448         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5449                 cpi->initiator_id);
5450         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5451         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5452         fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5453             adapter_str, cpi->hba_vendor);
5454         fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5455             adapter_str, cpi->hba_device);
5456         fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5457             adapter_str, cpi->hba_subvendor);
5458         fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5459             adapter_str, cpi->hba_subdevice);
5460         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5461         fprintf(stdout, "%s base transfer speed: ", adapter_str);
5462         if (cpi->base_transfer_speed > 1000)
5463                 fprintf(stdout, "%d.%03dMB/sec\n",
5464                         cpi->base_transfer_speed / 1000,
5465                         cpi->base_transfer_speed % 1000);
5466         else
5467                 fprintf(stdout, "%dKB/sec\n",
5468                         (cpi->base_transfer_speed % 1000) * 1000);
5469         fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5470             adapter_str, cpi->maxio);
5471 }
5472
5473 static int
5474 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5475               struct ccb_trans_settings *cts)
5476 {
5477         int retval;
5478         union ccb *ccb;
5479
5480         retval = 0;
5481         ccb = cam_getccb(device);
5482
5483         if (ccb == NULL) {
5484                 warnx("get_print_cts: error allocating ccb");
5485                 return(1);
5486         }
5487
5488         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5489
5490         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5491
5492         if (user_settings == 0)
5493                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5494         else
5495                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5496
5497         if (cam_send_ccb(device, ccb) < 0) {
5498                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5499                 if (arglist & CAM_ARG_VERBOSE)
5500                         cam_error_print(device, ccb, CAM_ESF_ALL,
5501                                         CAM_EPF_ALL, stderr);
5502                 retval = 1;
5503                 goto get_print_cts_bailout;
5504         }
5505
5506         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5507                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5508                 if (arglist & CAM_ARG_VERBOSE)
5509                         cam_error_print(device, ccb, CAM_ESF_ALL,
5510                                         CAM_EPF_ALL, stderr);
5511                 retval = 1;
5512                 goto get_print_cts_bailout;
5513         }
5514
5515         if (quiet == 0)
5516                 cts_print(device, &ccb->cts);
5517
5518         if (cts != NULL)
5519                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5520
5521 get_print_cts_bailout:
5522
5523         cam_freeccb(ccb);
5524
5525         return(retval);
5526 }
5527
5528 static int
5529 ratecontrol(struct cam_device *device, int task_attr, int retry_count,
5530             int timeout, int argc, char **argv, char *combinedopt)
5531 {
5532         int c;
5533         union ccb *ccb;
5534         int user_settings = 0;
5535         int retval = 0;
5536         int disc_enable = -1, tag_enable = -1;
5537         int mode = -1;
5538         int offset = -1;
5539         double syncrate = -1;
5540         int bus_width = -1;
5541         int quiet = 0;
5542         int change_settings = 0, send_tur = 0;
5543         struct ccb_pathinq cpi;
5544
5545         ccb = cam_getccb(device);
5546         if (ccb == NULL) {
5547                 warnx("ratecontrol: error allocating ccb");
5548                 return(1);
5549         }
5550         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5551                 switch(c){
5552                 case 'a':
5553                         send_tur = 1;
5554                         break;
5555                 case 'c':
5556                         user_settings = 0;
5557                         break;
5558                 case 'D':
5559                         if (strncasecmp(optarg, "enable", 6) == 0)
5560                                 disc_enable = 1;
5561                         else if (strncasecmp(optarg, "disable", 7) == 0)
5562                                 disc_enable = 0;
5563                         else {
5564                                 warnx("-D argument \"%s\" is unknown", optarg);
5565                                 retval = 1;
5566                                 goto ratecontrol_bailout;
5567                         }
5568                         change_settings = 1;
5569                         break;
5570                 case 'M':
5571                         mode = ata_string2mode(optarg);
5572                         if (mode < 0) {
5573                                 warnx("unknown mode '%s'", optarg);
5574                                 retval = 1;
5575                                 goto ratecontrol_bailout;
5576                         }
5577                         change_settings = 1;
5578                         break;
5579                 case 'O':
5580                         offset = strtol(optarg, NULL, 0);
5581                         if (offset < 0) {
5582                                 warnx("offset value %d is < 0", offset);
5583                                 retval = 1;
5584                                 goto ratecontrol_bailout;
5585                         }
5586                         change_settings = 1;
5587                         break;
5588                 case 'q':
5589                         quiet++;
5590                         break;
5591                 case 'R':
5592                         syncrate = atof(optarg);
5593                         if (syncrate < 0) {
5594                                 warnx("sync rate %f is < 0", syncrate);
5595                                 retval = 1;
5596                                 goto ratecontrol_bailout;
5597                         }
5598                         change_settings = 1;
5599                         break;
5600                 case 'T':
5601                         if (strncasecmp(optarg, "enable", 6) == 0)
5602                                 tag_enable = 1;
5603                         else if (strncasecmp(optarg, "disable", 7) == 0)
5604                                 tag_enable = 0;
5605                         else {
5606                                 warnx("-T argument \"%s\" is unknown", optarg);
5607                                 retval = 1;
5608                                 goto ratecontrol_bailout;
5609                         }
5610                         change_settings = 1;
5611                         break;
5612                 case 'U':
5613                         user_settings = 1;
5614                         break;
5615                 case 'W':
5616                         bus_width = strtol(optarg, NULL, 0);
5617                         if (bus_width < 0) {
5618                                 warnx("bus width %d is < 0", bus_width);
5619                                 retval = 1;
5620                                 goto ratecontrol_bailout;
5621                         }
5622                         change_settings = 1;
5623                         break;
5624                 default:
5625                         break;
5626                 }
5627         }
5628         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
5629         /*
5630          * Grab path inquiry information, so we can determine whether
5631          * or not the initiator is capable of the things that the user
5632          * requests.
5633          */
5634         ccb->ccb_h.func_code = XPT_PATH_INQ;
5635         if (cam_send_ccb(device, ccb) < 0) {
5636                 perror("error sending XPT_PATH_INQ CCB");
5637                 if (arglist & CAM_ARG_VERBOSE) {
5638                         cam_error_print(device, ccb, CAM_ESF_ALL,
5639                                         CAM_EPF_ALL, stderr);
5640                 }
5641                 retval = 1;
5642                 goto ratecontrol_bailout;
5643         }
5644         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5645                 warnx("XPT_PATH_INQ CCB failed");
5646                 if (arglist & CAM_ARG_VERBOSE) {
5647                         cam_error_print(device, ccb, CAM_ESF_ALL,
5648                                         CAM_EPF_ALL, stderr);
5649                 }
5650                 retval = 1;
5651                 goto ratecontrol_bailout;
5652         }
5653         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5654         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5655         if (quiet == 0) {
5656                 fprintf(stdout, "%s parameters:\n",
5657                     user_settings ? "User" : "Current");
5658         }
5659         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5660         if (retval != 0)
5661                 goto ratecontrol_bailout;
5662
5663         if (arglist & CAM_ARG_VERBOSE)
5664                 cpi_print(&cpi);
5665
5666         if (change_settings) {
5667                 int didsettings = 0;
5668                 struct ccb_trans_settings_spi *spi = NULL;
5669                 struct ccb_trans_settings_pata *pata = NULL;
5670                 struct ccb_trans_settings_sata *sata = NULL;
5671                 struct ccb_trans_settings_ata *ata = NULL;
5672                 struct ccb_trans_settings_scsi *scsi = NULL;
5673
5674                 if (ccb->cts.transport == XPORT_SPI)
5675                         spi = &ccb->cts.xport_specific.spi;
5676                 if (ccb->cts.transport == XPORT_ATA)
5677                         pata = &ccb->cts.xport_specific.ata;
5678                 if (ccb->cts.transport == XPORT_SATA)
5679                         sata = &ccb->cts.xport_specific.sata;
5680                 if (ccb->cts.protocol == PROTO_ATA)
5681                         ata = &ccb->cts.proto_specific.ata;
5682                 if (ccb->cts.protocol == PROTO_SCSI)
5683                         scsi = &ccb->cts.proto_specific.scsi;
5684                 ccb->cts.xport_specific.valid = 0;
5685                 ccb->cts.proto_specific.valid = 0;
5686                 if (spi && disc_enable != -1) {
5687                         spi->valid |= CTS_SPI_VALID_DISC;
5688                         if (disc_enable == 0)
5689                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5690                         else
5691                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5692                         didsettings++;
5693                 }
5694                 if (tag_enable != -1) {
5695                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5696                                 warnx("HBA does not support tagged queueing, "
5697                                       "so you cannot modify tag settings");
5698                                 retval = 1;
5699                                 goto ratecontrol_bailout;
5700                         }
5701                         if (ata) {
5702                                 ata->valid |= CTS_SCSI_VALID_TQ;
5703                                 if (tag_enable == 0)
5704                                         ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5705                                 else
5706                                         ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5707                                 didsettings++;
5708                         } else if (scsi) {
5709                                 scsi->valid |= CTS_SCSI_VALID_TQ;
5710                                 if (tag_enable == 0)
5711                                         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5712                                 else
5713                                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5714                                 didsettings++;
5715                         }
5716                 }
5717                 if (spi && offset != -1) {
5718                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5719                                 warnx("HBA is not capable of changing offset");
5720                                 retval = 1;
5721                                 goto ratecontrol_bailout;
5722                         }
5723                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5724                         spi->sync_offset = offset;
5725                         didsettings++;
5726                 }
5727                 if (spi && syncrate != -1) {
5728                         int prelim_sync_period;
5729
5730                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5731                                 warnx("HBA is not capable of changing "
5732                                       "transfer rates");
5733                                 retval = 1;
5734                                 goto ratecontrol_bailout;
5735                         }
5736                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5737                         /*
5738                          * The sync rate the user gives us is in MHz.
5739                          * We need to translate it into KHz for this
5740                          * calculation.
5741                          */
5742                         syncrate *= 1000;
5743                         /*
5744                          * Next, we calculate a "preliminary" sync period
5745                          * in tenths of a nanosecond.
5746                          */
5747                         if (syncrate == 0)
5748                                 prelim_sync_period = 0;
5749                         else
5750                                 prelim_sync_period = 10000000 / syncrate;
5751                         spi->sync_period =
5752                                 scsi_calc_syncparam(prelim_sync_period);
5753                         didsettings++;
5754                 }
5755                 if (sata && syncrate != -1) {
5756                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5757                                 warnx("HBA is not capable of changing "
5758                                       "transfer rates");
5759                                 retval = 1;
5760                                 goto ratecontrol_bailout;
5761                         }
5762                         if  (!user_settings) {
5763                                 warnx("You can modify only user rate "
5764                                     "settings for SATA");
5765                                 retval = 1;
5766                                 goto ratecontrol_bailout;
5767                         }
5768                         sata->revision = ata_speed2revision(syncrate * 100);
5769                         if (sata->revision < 0) {
5770                                 warnx("Invalid rate %f", syncrate);
5771                                 retval = 1;
5772                                 goto ratecontrol_bailout;
5773                         }
5774                         sata->valid |= CTS_SATA_VALID_REVISION;
5775                         didsettings++;
5776                 }
5777                 if ((pata || sata) && mode != -1) {
5778                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5779                                 warnx("HBA is not capable of changing "
5780                                       "transfer rates");
5781                                 retval = 1;
5782                                 goto ratecontrol_bailout;
5783                         }
5784                         if  (!user_settings) {
5785                                 warnx("You can modify only user mode "
5786                                     "settings for ATA/SATA");
5787                                 retval = 1;
5788                                 goto ratecontrol_bailout;
5789                         }
5790                         if (pata) {
5791                                 pata->mode = mode;
5792                                 pata->valid |= CTS_ATA_VALID_MODE;
5793                         } else {
5794                                 sata->mode = mode;
5795                                 sata->valid |= CTS_SATA_VALID_MODE;
5796                         }
5797                         didsettings++;
5798                 }
5799                 /*
5800                  * The bus_width argument goes like this:
5801                  * 0 == 8 bit
5802                  * 1 == 16 bit
5803                  * 2 == 32 bit
5804                  * Therefore, if you shift the number of bits given on the
5805                  * command line right by 4, you should get the correct
5806                  * number.
5807                  */
5808                 if (spi && bus_width != -1) {
5809                         /*
5810                          * We might as well validate things here with a
5811                          * decipherable error message, rather than what
5812                          * will probably be an indecipherable error message
5813                          * by the time it gets back to us.
5814                          */
5815                         if ((bus_width == 16)
5816                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5817                                 warnx("HBA does not support 16 bit bus width");
5818                                 retval = 1;
5819                                 goto ratecontrol_bailout;
5820                         } else if ((bus_width == 32)
5821                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5822                                 warnx("HBA does not support 32 bit bus width");
5823                                 retval = 1;
5824                                 goto ratecontrol_bailout;
5825                         } else if ((bus_width != 8)
5826                                 && (bus_width != 16)
5827                                 && (bus_width != 32)) {
5828                                 warnx("Invalid bus width %d", bus_width);
5829                                 retval = 1;
5830                                 goto ratecontrol_bailout;
5831                         }
5832                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5833                         spi->bus_width = bus_width >> 4;
5834                         didsettings++;
5835                 }
5836                 if  (didsettings == 0) {
5837                         goto ratecontrol_bailout;
5838                 }
5839                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5840                 if (cam_send_ccb(device, ccb) < 0) {
5841                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5842                         if (arglist & CAM_ARG_VERBOSE) {
5843                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5844                                                 CAM_EPF_ALL, stderr);
5845                         }
5846                         retval = 1;
5847                         goto ratecontrol_bailout;
5848                 }
5849                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5850                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5851                         if (arglist & CAM_ARG_VERBOSE) {
5852                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5853                                                 CAM_EPF_ALL, stderr);
5854                         }
5855                         retval = 1;
5856                         goto ratecontrol_bailout;
5857                 }
5858         }
5859         if (send_tur) {
5860                 retval = testunitready(device, task_attr, retry_count, timeout,
5861                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5862                 /*
5863                  * If the TUR didn't succeed, just bail.
5864                  */
5865                 if (retval != 0) {
5866                         if (quiet == 0)
5867                                 fprintf(stderr, "Test Unit Ready failed\n");
5868                         goto ratecontrol_bailout;
5869                 }
5870         }
5871         if ((change_settings || send_tur) && !quiet &&
5872             (ccb->cts.transport == XPORT_ATA ||
5873              ccb->cts.transport == XPORT_SATA || send_tur)) {
5874                 fprintf(stdout, "New parameters:\n");
5875                 retval = get_print_cts(device, user_settings, 0, NULL);
5876         }
5877
5878 ratecontrol_bailout:
5879         cam_freeccb(ccb);
5880         return(retval);
5881 }
5882
5883 static int
5884 scsiformat(struct cam_device *device, int argc, char **argv,
5885            char *combinedopt, int task_attr, int retry_count, int timeout)
5886 {
5887         union ccb *ccb;
5888         int c;
5889         int ycount = 0, quiet = 0;
5890         int error = 0, retval = 0;
5891         int use_timeout = 10800 * 1000;
5892         int immediate = 1;
5893         struct format_defect_list_header fh;
5894         u_int8_t *data_ptr = NULL;
5895         u_int32_t dxfer_len = 0;
5896         u_int8_t byte2 = 0;
5897         int num_warnings = 0;
5898         int reportonly = 0;
5899
5900         ccb = cam_getccb(device);
5901
5902         if (ccb == NULL) {
5903                 warnx("scsiformat: error allocating ccb");
5904                 return(1);
5905         }
5906
5907         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5908
5909         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5910                 switch(c) {
5911                 case 'q':
5912                         quiet++;
5913                         break;
5914                 case 'r':
5915                         reportonly = 1;
5916                         break;
5917                 case 'w':
5918                         immediate = 0;
5919                         break;
5920                 case 'y':
5921                         ycount++;
5922                         break;
5923                 }
5924         }
5925
5926         if (reportonly)
5927                 goto doreport;
5928
5929         if (quiet == 0) {
5930                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5931                         "following device:\n");
5932
5933                 error = scsidoinquiry(device, argc, argv, combinedopt,
5934                                       task_attr, retry_count, timeout);
5935
5936                 if (error != 0) {
5937                         warnx("scsiformat: error sending inquiry");
5938                         goto scsiformat_bailout;
5939                 }
5940         }
5941
5942         if (ycount == 0) {
5943                 if (!get_confirmation()) {
5944                         error = 1;
5945                         goto scsiformat_bailout;
5946                 }
5947         }
5948
5949         if (timeout != 0)
5950                 use_timeout = timeout;
5951
5952         if (quiet == 0) {
5953                 fprintf(stdout, "Current format timeout is %d seconds\n",
5954                         use_timeout / 1000);
5955         }
5956
5957         /*
5958          * If the user hasn't disabled questions and didn't specify a
5959          * timeout on the command line, ask them if they want the current
5960          * timeout.
5961          */
5962         if ((ycount == 0)
5963          && (timeout == 0)) {
5964                 char str[1024];
5965                 int new_timeout = 0;
5966
5967                 fprintf(stdout, "Enter new timeout in seconds or press\n"
5968                         "return to keep the current timeout [%d] ",
5969                         use_timeout / 1000);
5970
5971                 if (fgets(str, sizeof(str), stdin) != NULL) {
5972                         if (str[0] != '\0')
5973                                 new_timeout = atoi(str);
5974                 }
5975
5976                 if (new_timeout != 0) {
5977                         use_timeout = new_timeout * 1000;
5978                         fprintf(stdout, "Using new timeout value %d\n",
5979                                 use_timeout / 1000);
5980                 }
5981         }
5982
5983         /*
5984          * Keep this outside the if block below to silence any unused
5985          * variable warnings.
5986          */
5987         bzero(&fh, sizeof(fh));
5988
5989         /*
5990          * If we're in immediate mode, we've got to include the format
5991          * header
5992          */
5993         if (immediate != 0) {
5994                 fh.byte2 = FU_DLH_IMMED;
5995                 data_ptr = (u_int8_t *)&fh;
5996                 dxfer_len = sizeof(fh);
5997                 byte2 = FU_FMT_DATA;
5998         } else if (quiet == 0) {
5999                 fprintf(stdout, "Formatting...");
6000                 fflush(stdout);
6001         }
6002
6003         scsi_format_unit(&ccb->csio,
6004                          /* retries */ retry_count,
6005                          /* cbfcnp */ NULL,
6006                          /* tag_action */ task_attr,
6007                          /* byte2 */ byte2,
6008                          /* ileave */ 0,
6009                          /* data_ptr */ data_ptr,
6010                          /* dxfer_len */ dxfer_len,
6011                          /* sense_len */ SSD_FULL_SIZE,
6012                          /* timeout */ use_timeout);
6013
6014         /* Disable freezing the device queue */
6015         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6016
6017         if (arglist & CAM_ARG_ERR_RECOVER)
6018                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6019
6020         if (((retval = cam_send_ccb(device, ccb)) < 0)
6021          || ((immediate == 0)
6022            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
6023                 const char errstr[] = "error sending format command";
6024
6025                 if (retval < 0)
6026                         warn(errstr);
6027                 else
6028                         warnx(errstr);
6029
6030                 if (arglist & CAM_ARG_VERBOSE) {
6031                         cam_error_print(device, ccb, CAM_ESF_ALL,
6032                                         CAM_EPF_ALL, stderr);
6033                 }
6034                 error = 1;
6035                 goto scsiformat_bailout;
6036         }
6037
6038         /*
6039          * If we ran in non-immediate mode, we already checked for errors
6040          * above and printed out any necessary information.  If we're in
6041          * immediate mode, we need to loop through and get status
6042          * information periodically.
6043          */
6044         if (immediate == 0) {
6045                 if (quiet == 0) {
6046                         fprintf(stdout, "Format Complete\n");
6047                 }
6048                 goto scsiformat_bailout;
6049         }
6050
6051 doreport:
6052         do {
6053                 cam_status status;
6054
6055                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6056
6057                 /*
6058                  * There's really no need to do error recovery or
6059                  * retries here, since we're just going to sit in a
6060                  * loop and wait for the device to finish formatting.
6061                  */
6062                 scsi_test_unit_ready(&ccb->csio,
6063                                      /* retries */ 0,
6064                                      /* cbfcnp */ NULL,
6065                                      /* tag_action */ task_attr,
6066                                      /* sense_len */ SSD_FULL_SIZE,
6067                                      /* timeout */ 5000);
6068
6069                 /* Disable freezing the device queue */
6070                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6071
6072                 retval = cam_send_ccb(device, ccb);
6073
6074                 /*
6075                  * If we get an error from the ioctl, bail out.  SCSI
6076                  * errors are expected.
6077                  */
6078                 if (retval < 0) {
6079                         warn("error sending CAMIOCOMMAND ioctl");
6080                         if (arglist & CAM_ARG_VERBOSE) {
6081                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6082                                                 CAM_EPF_ALL, stderr);
6083                         }
6084                         error = 1;
6085                         goto scsiformat_bailout;
6086                 }
6087
6088                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6089
6090                 if ((status != CAM_REQ_CMP)
6091                  && (status == CAM_SCSI_STATUS_ERROR)
6092                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6093                         struct scsi_sense_data *sense;
6094                         int error_code, sense_key, asc, ascq;
6095
6096                         sense = &ccb->csio.sense_data;
6097                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6098                             ccb->csio.sense_resid, &error_code, &sense_key,
6099                             &asc, &ascq, /*show_errors*/ 1);
6100
6101                         /*
6102                          * According to the SCSI-2 and SCSI-3 specs, a
6103                          * drive that is in the middle of a format should
6104                          * return NOT READY with an ASC of "logical unit
6105                          * not ready, format in progress".  The sense key
6106                          * specific bytes will then be a progress indicator.
6107                          */
6108                         if ((sense_key == SSD_KEY_NOT_READY)
6109                          && (asc == 0x04) && (ascq == 0x04)) {
6110                                 uint8_t sks[3];
6111
6112                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6113                                      ccb->csio.sense_resid, sks) == 0)
6114                                  && (quiet == 0)) {
6115                                         int val;
6116                                         u_int64_t percentage;
6117
6118                                         val = scsi_2btoul(&sks[1]);
6119                                         percentage = 10000 * val;
6120
6121                                         fprintf(stdout,
6122                                                 "\rFormatting:  %ju.%02u %% "
6123                                                 "(%d/%d) done",
6124                                                 (uintmax_t)(percentage /
6125                                                 (0x10000 * 100)),
6126                                                 (unsigned)((percentage /
6127                                                 0x10000) % 100),
6128                                                 val, 0x10000);
6129                                         fflush(stdout);
6130                                 } else if ((quiet == 0)
6131                                         && (++num_warnings <= 1)) {
6132                                         warnx("Unexpected SCSI Sense Key "
6133                                               "Specific value returned "
6134                                               "during format:");
6135                                         scsi_sense_print(device, &ccb->csio,
6136                                                          stderr);
6137                                         warnx("Unable to print status "
6138                                               "information, but format will "
6139                                               "proceed.");
6140                                         warnx("will exit when format is "
6141                                               "complete");
6142                                 }
6143                                 sleep(1);
6144                         } else {
6145                                 warnx("Unexpected SCSI error during format");
6146                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6147                                                 CAM_EPF_ALL, stderr);
6148                                 error = 1;
6149                                 goto scsiformat_bailout;
6150                         }
6151
6152                 } else if (status != CAM_REQ_CMP) {
6153                         warnx("Unexpected CAM status %#x", status);
6154                         if (arglist & CAM_ARG_VERBOSE)
6155                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6156                                                 CAM_EPF_ALL, stderr);
6157                         error = 1;
6158                         goto scsiformat_bailout;
6159                 }
6160
6161         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6162
6163         if (quiet == 0)
6164                 fprintf(stdout, "\nFormat Complete\n");
6165
6166 scsiformat_bailout:
6167
6168         cam_freeccb(ccb);
6169
6170         return(error);
6171 }
6172
6173 static int
6174 scsisanitize(struct cam_device *device, int argc, char **argv,
6175              char *combinedopt, int task_attr, int retry_count, int timeout)
6176 {
6177         union ccb *ccb;
6178         u_int8_t action = 0;
6179         int c;
6180         int ycount = 0, quiet = 0;
6181         int error = 0, retval = 0;
6182         int use_timeout = 10800 * 1000;
6183         int immediate = 1;
6184         int invert = 0;
6185         int passes = 0;
6186         int ause = 0;
6187         int fd = -1;
6188         const char *pattern = NULL;
6189         u_int8_t *data_ptr = NULL;
6190         u_int32_t dxfer_len = 0;
6191         u_int8_t byte2 = 0;
6192         int num_warnings = 0;
6193         int reportonly = 0;
6194
6195         ccb = cam_getccb(device);
6196
6197         if (ccb == NULL) {
6198                 warnx("scsisanitize: error allocating ccb");
6199                 return(1);
6200         }
6201
6202         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6203
6204         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6205                 switch(c) {
6206                 case 'a':
6207                         if (strcasecmp(optarg, "overwrite") == 0)
6208                                 action = SSZ_SERVICE_ACTION_OVERWRITE;
6209                         else if (strcasecmp(optarg, "block") == 0)
6210                                 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6211                         else if (strcasecmp(optarg, "crypto") == 0)
6212                                 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6213                         else if (strcasecmp(optarg, "exitfailure") == 0)
6214                                 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6215                         else {
6216                                 warnx("invalid service operation \"%s\"",
6217                                       optarg);
6218                                 error = 1;
6219                                 goto scsisanitize_bailout;
6220                         }
6221                         break;
6222                 case 'c':
6223                         passes = strtol(optarg, NULL, 0);
6224                         if (passes < 1 || passes > 31) {
6225                                 warnx("invalid passes value %d", passes);
6226                                 error = 1;
6227                                 goto scsisanitize_bailout;
6228                         }
6229                         break;
6230                 case 'I':
6231                         invert = 1;
6232                         break;
6233                 case 'P':
6234                         pattern = optarg;
6235                         break;
6236                 case 'q':
6237                         quiet++;
6238                         break;
6239                 case 'U':
6240                         ause = 1;
6241                         break;
6242                 case 'r':
6243                         reportonly = 1;
6244                         break;
6245                 case 'w':
6246                         immediate = 0;
6247                         break;
6248                 case 'y':
6249                         ycount++;
6250                         break;
6251                 }
6252         }
6253
6254         if (reportonly)
6255                 goto doreport;
6256
6257         if (action == 0) {
6258                 warnx("an action is required");
6259                 error = 1;
6260                 goto scsisanitize_bailout;
6261         } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6262                 struct scsi_sanitize_parameter_list *pl;
6263                 struct stat sb;
6264                 ssize_t sz, amt;
6265
6266                 if (pattern == NULL) {
6267                         warnx("overwrite action requires -P argument");
6268                         error = 1;
6269                         goto scsisanitize_bailout;
6270                 }
6271                 fd = open(pattern, O_RDONLY);
6272                 if (fd < 0) {
6273                         warn("cannot open pattern file %s", pattern);
6274                         error = 1;
6275                         goto scsisanitize_bailout;
6276                 }
6277                 if (fstat(fd, &sb) < 0) {
6278                         warn("cannot stat pattern file %s", pattern);
6279                         error = 1;
6280                         goto scsisanitize_bailout;
6281                 }
6282                 sz = sb.st_size;
6283                 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6284                         warnx("pattern file size exceeds maximum value %d",
6285                               SSZPL_MAX_PATTERN_LENGTH);
6286                         error = 1;
6287                         goto scsisanitize_bailout;
6288                 }
6289                 dxfer_len = sizeof(*pl) + sz;
6290                 data_ptr = calloc(1, dxfer_len);
6291                 if (data_ptr == NULL) {
6292                         warnx("cannot allocate parameter list buffer");
6293                         error = 1;
6294                         goto scsisanitize_bailout;
6295                 }
6296
6297                 amt = read(fd, data_ptr + sizeof(*pl), sz);
6298                 if (amt < 0) {
6299                         warn("cannot read pattern file");
6300                         error = 1;
6301                         goto scsisanitize_bailout;
6302                 } else if (amt != sz) {
6303                         warnx("short pattern file read");
6304                         error = 1;
6305                         goto scsisanitize_bailout;
6306                 }
6307
6308                 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6309                 if (passes == 0)
6310                         pl->byte1 = 1;
6311                 else
6312                         pl->byte1 = passes;
6313                 if (invert != 0)
6314                         pl->byte1 |= SSZPL_INVERT;
6315                 scsi_ulto2b(sz, pl->length);
6316         } else {
6317                 const char *arg;
6318
6319                 if (passes != 0)
6320                         arg = "-c";
6321                 else if (invert != 0)
6322                         arg = "-I";
6323                 else if (pattern != NULL)
6324                         arg = "-P";
6325                 else
6326                         arg = NULL;
6327                 if (arg != NULL) {
6328                         warnx("%s argument only valid with overwrite "
6329                               "operation", arg);
6330                         error = 1;
6331                         goto scsisanitize_bailout;
6332                 }
6333         }
6334
6335         if (quiet == 0) {
6336                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6337                         "following device:\n");
6338
6339                 error = scsidoinquiry(device, argc, argv, combinedopt,
6340                                       task_attr, retry_count, timeout);
6341
6342                 if (error != 0) {
6343                         warnx("scsisanitize: error sending inquiry");
6344                         goto scsisanitize_bailout;
6345                 }
6346         }
6347
6348         if (ycount == 0) {
6349                 if (!get_confirmation()) {
6350                         error = 1;
6351                         goto scsisanitize_bailout;
6352                 }
6353         }
6354
6355         if (timeout != 0)
6356                 use_timeout = timeout;
6357
6358         if (quiet == 0) {
6359                 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6360                         use_timeout / 1000);
6361         }
6362
6363         /*
6364          * If the user hasn't disabled questions and didn't specify a
6365          * timeout on the command line, ask them if they want the current
6366          * timeout.
6367          */
6368         if ((ycount == 0)
6369          && (timeout == 0)) {
6370                 char str[1024];
6371                 int new_timeout = 0;
6372
6373                 fprintf(stdout, "Enter new timeout in seconds or press\n"
6374                         "return to keep the current timeout [%d] ",
6375                         use_timeout / 1000);
6376
6377                 if (fgets(str, sizeof(str), stdin) != NULL) {
6378                         if (str[0] != '\0')
6379                                 new_timeout = atoi(str);
6380                 }
6381
6382                 if (new_timeout != 0) {
6383                         use_timeout = new_timeout * 1000;
6384                         fprintf(stdout, "Using new timeout value %d\n",
6385                                 use_timeout / 1000);
6386                 }
6387         }
6388
6389         byte2 = action;
6390         if (ause != 0)
6391                 byte2 |= SSZ_UNRESTRICTED_EXIT;
6392         if (immediate != 0)
6393                 byte2 |= SSZ_IMMED;
6394
6395         scsi_sanitize(&ccb->csio,
6396                       /* retries */ retry_count,
6397                       /* cbfcnp */ NULL,
6398                       /* tag_action */ task_attr,
6399                       /* byte2 */ byte2,
6400                       /* control */ 0,
6401                       /* data_ptr */ data_ptr,
6402                       /* dxfer_len */ dxfer_len,
6403                       /* sense_len */ SSD_FULL_SIZE,
6404                       /* timeout */ use_timeout);
6405
6406         /* Disable freezing the device queue */
6407         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6408
6409         if (arglist & CAM_ARG_ERR_RECOVER)
6410                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6411
6412         if (cam_send_ccb(device, ccb) < 0) {
6413                 warn("error sending sanitize command");
6414                 error = 1;
6415                 goto scsisanitize_bailout;
6416         }
6417
6418         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6419                 struct scsi_sense_data *sense;
6420                 int error_code, sense_key, asc, ascq;
6421
6422                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6423                     CAM_SCSI_STATUS_ERROR) {
6424                         sense = &ccb->csio.sense_data;
6425                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6426                             ccb->csio.sense_resid, &error_code, &sense_key,
6427                             &asc, &ascq, /*show_errors*/ 1);
6428
6429                         if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6430                             asc == 0x20 && ascq == 0x00)
6431                                 warnx("sanitize is not supported by "
6432                                       "this device");
6433                         else
6434                                 warnx("error sanitizing this device");
6435                 } else
6436                         warnx("error sanitizing this device");
6437
6438                 if (arglist & CAM_ARG_VERBOSE) {
6439                         cam_error_print(device, ccb, CAM_ESF_ALL,
6440                                         CAM_EPF_ALL, stderr);
6441                 }
6442                 error = 1;
6443                 goto scsisanitize_bailout;
6444         }
6445
6446         /*
6447          * If we ran in non-immediate mode, we already checked for errors
6448          * above and printed out any necessary information.  If we're in
6449          * immediate mode, we need to loop through and get status
6450          * information periodically.
6451          */
6452         if (immediate == 0) {
6453                 if (quiet == 0) {
6454                         fprintf(stdout, "Sanitize Complete\n");
6455                 }
6456                 goto scsisanitize_bailout;
6457         }
6458
6459 doreport:
6460         do {
6461                 cam_status status;
6462
6463                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6464
6465                 /*
6466                  * There's really no need to do error recovery or
6467                  * retries here, since we're just going to sit in a
6468                  * loop and wait for the device to finish sanitizing.
6469                  */
6470                 scsi_test_unit_ready(&ccb->csio,
6471                                      /* retries */ 0,
6472                                      /* cbfcnp */ NULL,
6473                                      /* tag_action */ task_attr,
6474                                      /* sense_len */ SSD_FULL_SIZE,
6475                                      /* timeout */ 5000);
6476
6477                 /* Disable freezing the device queue */
6478                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6479
6480                 retval = cam_send_ccb(device, ccb);
6481
6482                 /*
6483                  * If we get an error from the ioctl, bail out.  SCSI
6484                  * errors are expected.
6485                  */
6486                 if (retval < 0) {
6487                         warn("error sending CAMIOCOMMAND ioctl");
6488                         if (arglist & CAM_ARG_VERBOSE) {
6489                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6490                                                 CAM_EPF_ALL, stderr);
6491                         }
6492                         error = 1;
6493                         goto scsisanitize_bailout;
6494                 }
6495
6496                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6497
6498                 if ((status != CAM_REQ_CMP)
6499                  && (status == CAM_SCSI_STATUS_ERROR)
6500                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6501                         struct scsi_sense_data *sense;
6502                         int error_code, sense_key, asc, ascq;
6503
6504                         sense = &ccb->csio.sense_data;
6505                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
6506                             ccb->csio.sense_resid, &error_code, &sense_key,
6507                             &asc, &ascq, /*show_errors*/ 1);
6508
6509                         /*
6510                          * According to the SCSI-3 spec, a drive that is in the
6511                          * middle of a sanitize should return NOT READY with an
6512                          * ASC of "logical unit not ready, sanitize in
6513                          * progress". The sense key specific bytes will then
6514                          * be a progress indicator.
6515                          */
6516                         if ((sense_key == SSD_KEY_NOT_READY)
6517                          && (asc == 0x04) && (ascq == 0x1b)) {
6518                                 uint8_t sks[3];
6519
6520                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6521                                      ccb->csio.sense_resid, sks) == 0)
6522                                  && (quiet == 0)) {
6523                                         int val;
6524                                         u_int64_t percentage;
6525
6526                                         val = scsi_2btoul(&sks[1]);
6527                                         percentage = 10000 * val;
6528
6529                                         fprintf(stdout,
6530                                                 "\rSanitizing:  %ju.%02u %% "
6531                                                 "(%d/%d) done",
6532                                                 (uintmax_t)(percentage /
6533                                                 (0x10000 * 100)),
6534                                                 (unsigned)((percentage /
6535                                                 0x10000) % 100),
6536                                                 val, 0x10000);
6537                                         fflush(stdout);
6538                                 } else if ((quiet == 0)
6539                                         && (++num_warnings <= 1)) {
6540                                         warnx("Unexpected SCSI Sense Key "
6541                                               "Specific value returned "
6542                                               "during sanitize:");
6543                                         scsi_sense_print(device, &ccb->csio,
6544                                                          stderr);
6545                                         warnx("Unable to print status "
6546                                               "information, but sanitze will "
6547                                               "proceed.");
6548                                         warnx("will exit when sanitize is "
6549                                               "complete");
6550                                 }
6551                                 sleep(1);
6552                         } else {
6553                                 warnx("Unexpected SCSI error during sanitize");
6554                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6555                                                 CAM_EPF_ALL, stderr);
6556                                 error = 1;
6557                                 goto scsisanitize_bailout;
6558                         }
6559
6560                 } else if (status != CAM_REQ_CMP) {
6561                         warnx("Unexpected CAM status %#x", status);
6562                         if (arglist & CAM_ARG_VERBOSE)
6563                                 cam_error_print(device, ccb, CAM_ESF_ALL,
6564                                                 CAM_EPF_ALL, stderr);
6565                         error = 1;
6566                         goto scsisanitize_bailout;
6567                 }
6568         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6569
6570         if (quiet == 0)
6571                 fprintf(stdout, "\nSanitize Complete\n");
6572
6573 scsisanitize_bailout:
6574         if (fd >= 0)
6575                 close(fd);
6576         if (data_ptr != NULL)
6577                 free(data_ptr);
6578         cam_freeccb(ccb);
6579
6580         return(error);
6581 }
6582
6583 static int
6584 scsireportluns(struct cam_device *device, int argc, char **argv,
6585                char *combinedopt, int task_attr, int retry_count, int timeout)
6586 {
6587         union ccb *ccb;
6588         int c, countonly, lunsonly;
6589         struct scsi_report_luns_data *lundata;
6590         int alloc_len;
6591         uint8_t report_type;
6592         uint32_t list_len, i, j;
6593         int retval;
6594
6595         retval = 0;
6596         lundata = NULL;
6597         report_type = RPL_REPORT_DEFAULT;
6598         ccb = cam_getccb(device);
6599
6600         if (ccb == NULL) {
6601                 warnx("%s: error allocating ccb", __func__);
6602                 return (1);
6603         }
6604
6605         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6606
6607         countonly = 0;
6608         lunsonly = 0;
6609
6610         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6611                 switch (c) {
6612                 case 'c':
6613                         countonly++;
6614                         break;
6615                 case 'l':
6616                         lunsonly++;
6617                         break;
6618                 case 'r':
6619                         if (strcasecmp(optarg, "default") == 0)
6620                                 report_type = RPL_REPORT_DEFAULT;
6621                         else if (strcasecmp(optarg, "wellknown") == 0)
6622                                 report_type = RPL_REPORT_WELLKNOWN;
6623                         else if (strcasecmp(optarg, "all") == 0)
6624                                 report_type = RPL_REPORT_ALL;
6625                         else {
6626                                 warnx("%s: invalid report type \"%s\"",
6627                                       __func__, optarg);
6628                                 retval = 1;
6629                                 goto bailout;
6630                         }
6631                         break;
6632                 default:
6633                         break;
6634                 }
6635         }
6636
6637         if ((countonly != 0)
6638          && (lunsonly != 0)) {
6639                 warnx("%s: you can only specify one of -c or -l", __func__);
6640                 retval = 1;
6641                 goto bailout;
6642         }
6643         /*
6644          * According to SPC-4, the allocation length must be at least 16
6645          * bytes -- enough for the header and one LUN.
6646          */
6647         alloc_len = sizeof(*lundata) + 8;
6648
6649 retry:
6650
6651         lundata = malloc(alloc_len);
6652
6653         if (lundata == NULL) {
6654                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6655                 retval = 1;
6656                 goto bailout;
6657         }
6658
6659         scsi_report_luns(&ccb->csio,
6660                          /*retries*/ retry_count,
6661                          /*cbfcnp*/ NULL,
6662                          /*tag_action*/ task_attr,
6663                          /*select_report*/ report_type,
6664                          /*rpl_buf*/ lundata,
6665                          /*alloc_len*/ alloc_len,
6666                          /*sense_len*/ SSD_FULL_SIZE,
6667                          /*timeout*/ timeout ? timeout : 5000);
6668
6669         /* Disable freezing the device queue */
6670         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6671
6672         if (arglist & CAM_ARG_ERR_RECOVER)
6673                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6674
6675         if (cam_send_ccb(device, ccb) < 0) {
6676                 warn("error sending REPORT LUNS command");
6677
6678                 if (arglist & CAM_ARG_VERBOSE)
6679                         cam_error_print(device, ccb, CAM_ESF_ALL,
6680                                         CAM_EPF_ALL, stderr);
6681
6682                 retval = 1;
6683                 goto bailout;
6684         }
6685
6686         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6687                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6688                 retval = 1;
6689                 goto bailout;
6690         }
6691
6692
6693         list_len = scsi_4btoul(lundata->length);
6694
6695         /*
6696          * If we need to list the LUNs, and our allocation
6697          * length was too short, reallocate and retry.
6698          */
6699         if ((countonly == 0)
6700          && (list_len > (alloc_len - sizeof(*lundata)))) {
6701                 alloc_len = list_len + sizeof(*lundata);
6702                 free(lundata);
6703                 goto retry;
6704         }
6705
6706         if (lunsonly == 0)
6707                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6708                         ((list_len / 8) > 1) ? "s" : "");
6709
6710         if (countonly != 0)
6711                 goto bailout;
6712
6713         for (i = 0; i < (list_len / 8); i++) {
6714                 int no_more;
6715
6716                 no_more = 0;
6717                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6718                         if (j != 0)
6719                                 fprintf(stdout, ",");
6720                         switch (lundata->luns[i].lundata[j] &
6721                                 RPL_LUNDATA_ATYP_MASK) {
6722                         case RPL_LUNDATA_ATYP_PERIPH:
6723                                 if ((lundata->luns[i].lundata[j] &
6724                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6725                                         fprintf(stdout, "%d:",
6726                                                 lundata->luns[i].lundata[j] &
6727                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
6728                                 else if ((j == 0)
6729                                       && ((lundata->luns[i].lundata[j+2] &
6730                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6731                                         no_more = 1;
6732
6733                                 fprintf(stdout, "%d",
6734                                         lundata->luns[i].lundata[j+1]);
6735                                 break;
6736                         case RPL_LUNDATA_ATYP_FLAT: {
6737                                 uint8_t tmplun[2];
6738                                 tmplun[0] = lundata->luns[i].lundata[j] &
6739                                         RPL_LUNDATA_FLAT_LUN_MASK;
6740                                 tmplun[1] = lundata->luns[i].lundata[j+1];
6741
6742                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6743                                 no_more = 1;
6744                                 break;
6745                         }
6746                         case RPL_LUNDATA_ATYP_LUN:
6747                                 fprintf(stdout, "%d:%d:%d",
6748                                         (lundata->luns[i].lundata[j+1] &
6749                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6750                                         lundata->luns[i].lundata[j] &
6751                                         RPL_LUNDATA_LUN_TARG_MASK,
6752                                         lundata->luns[i].lundata[j+1] &
6753                                         RPL_LUNDATA_LUN_LUN_MASK);
6754                                 break;
6755                         case RPL_LUNDATA_ATYP_EXTLUN: {
6756                                 int field_len_code, eam_code;
6757
6758                                 eam_code = lundata->luns[i].lundata[j] &
6759                                         RPL_LUNDATA_EXT_EAM_MASK;
6760                                 field_len_code = (lundata->luns[i].lundata[j] &
6761                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6762
6763                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6764                                  && (field_len_code == 0x00)) {
6765                                         fprintf(stdout, "%d",
6766                                                 lundata->luns[i].lundata[j+1]);
6767                                 } else if ((eam_code ==
6768                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6769                                         && (field_len_code == 0x03)) {
6770                                         uint8_t tmp_lun[8];
6771
6772                                         /*
6773                                          * This format takes up all 8 bytes.
6774                                          * If we aren't starting at offset 0,
6775                                          * that's a bug.
6776                                          */
6777                                         if (j != 0) {
6778                                                 fprintf(stdout, "Invalid "
6779                                                         "offset %d for "
6780                                                         "Extended LUN not "
6781                                                         "specified format", j);
6782                                                 no_more = 1;
6783                                                 break;
6784                                         }
6785                                         bzero(tmp_lun, sizeof(tmp_lun));
6786                                         bcopy(&lundata->luns[i].lundata[j+1],
6787                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
6788                                         fprintf(stdout, "%#jx",
6789                                                (intmax_t)scsi_8btou64(tmp_lun));
6790                                         no_more = 1;
6791                                 } else {
6792                                         fprintf(stderr, "Unknown Extended LUN"
6793                                                 "Address method %#x, length "
6794                                                 "code %#x", eam_code,
6795                                                 field_len_code);
6796                                         no_more = 1;
6797                                 }
6798                                 break;
6799                         }
6800                         default:
6801                                 fprintf(stderr, "Unknown LUN address method "
6802                                         "%#x\n", lundata->luns[i].lundata[0] &
6803                                         RPL_LUNDATA_ATYP_MASK);
6804                                 break;
6805                         }
6806                         /*
6807                          * For the flat addressing method, there are no
6808                          * other levels after it.
6809                          */
6810                         if (no_more != 0)
6811                                 break;
6812                 }
6813                 fprintf(stdout, "\n");
6814         }
6815
6816 bailout:
6817
6818         cam_freeccb(ccb);
6819
6820         free(lundata);
6821
6822         return (retval);
6823 }
6824
6825 static int
6826 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6827                  char *combinedopt, int task_attr, int retry_count, int timeout)
6828 {
6829         union ccb *ccb;
6830         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6831         struct scsi_read_capacity_data rcap;
6832         struct scsi_read_capacity_data_long rcaplong;
6833         uint64_t maxsector;
6834         uint32_t block_len;
6835         int retval;
6836         int c;
6837
6838         blocksizeonly = 0;
6839         humanize = 0;
6840         numblocks = 0;
6841         quiet = 0;
6842         sizeonly = 0;
6843         baseten = 0;
6844         retval = 0;
6845
6846         ccb = cam_getccb(device);
6847
6848         if (ccb == NULL) {
6849                 warnx("%s: error allocating ccb", __func__);
6850                 return (1);
6851         }
6852
6853         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6854
6855         while ((c = getopt(argc, argv, combinedopt)) != -1) {
6856                 switch (c) {
6857                 case 'b':
6858                         blocksizeonly++;
6859                         break;
6860                 case 'h':
6861                         humanize++;
6862                         baseten = 0;
6863                         break;
6864                 case 'H':
6865                         humanize++;
6866                         baseten++;
6867                         break;
6868                 case 'N':
6869                         numblocks++;
6870                         break;
6871                 case 'q':
6872                         quiet++;
6873                         break;
6874                 case 's':
6875                         sizeonly++;
6876                         break;
6877                 default:
6878                         break;
6879                 }
6880         }
6881
6882         if ((blocksizeonly != 0)
6883          && (numblocks != 0)) {
6884                 warnx("%s: you can only specify one of -b or -N", __func__);
6885                 retval = 1;
6886                 goto bailout;
6887         }
6888
6889         if ((blocksizeonly != 0)
6890          && (sizeonly != 0)) {
6891                 warnx("%s: you can only specify one of -b or -s", __func__);
6892                 retval = 1;
6893                 goto bailout;
6894         }
6895
6896         if ((humanize != 0)
6897          && (quiet != 0)) {
6898                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6899                 retval = 1;
6900                 goto bailout;
6901         }
6902
6903         if ((humanize != 0)
6904          && (blocksizeonly != 0)) {
6905                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6906                 retval = 1;
6907                 goto bailout;
6908         }
6909
6910         scsi_read_capacity(&ccb->csio,
6911                            /*retries*/ retry_count,
6912                            /*cbfcnp*/ NULL,
6913                            /*tag_action*/ task_attr,
6914                            &rcap,
6915                            SSD_FULL_SIZE,
6916                            /*timeout*/ timeout ? timeout : 5000);
6917
6918         /* Disable freezing the device queue */
6919         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6920
6921         if (arglist & CAM_ARG_ERR_RECOVER)
6922                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6923
6924         if (cam_send_ccb(device, ccb) < 0) {
6925                 warn("error sending READ CAPACITY command");
6926
6927                 if (arglist & CAM_ARG_VERBOSE)
6928                         cam_error_print(device, ccb, CAM_ESF_ALL,
6929                                         CAM_EPF_ALL, stderr);
6930
6931                 retval = 1;
6932                 goto bailout;
6933         }
6934
6935         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6936                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6937                 retval = 1;
6938                 goto bailout;
6939         }
6940
6941         maxsector = scsi_4btoul(rcap.addr);
6942         block_len = scsi_4btoul(rcap.length);
6943
6944         /*
6945          * A last block of 2^32-1 means that the true capacity is over 2TB,
6946          * and we need to issue the long READ CAPACITY to get the real
6947          * capacity.  Otherwise, we're all set.
6948          */
6949         if (maxsector != 0xffffffff)
6950                 goto do_print;
6951
6952         scsi_read_capacity_16(&ccb->csio,
6953                               /*retries*/ retry_count,
6954                               /*cbfcnp*/ NULL,
6955                               /*tag_action*/ task_attr,
6956                               /*lba*/ 0,
6957                               /*reladdr*/ 0,
6958                               /*pmi*/ 0,
6959                               /*rcap_buf*/ (uint8_t *)&rcaplong,
6960                               /*rcap_buf_len*/ sizeof(rcaplong),
6961                               /*sense_len*/ SSD_FULL_SIZE,
6962                               /*timeout*/ timeout ? timeout : 5000);
6963
6964         /* Disable freezing the device queue */
6965         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6966
6967         if (arglist & CAM_ARG_ERR_RECOVER)
6968                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6969
6970         if (cam_send_ccb(device, ccb) < 0) {
6971                 warn("error sending READ CAPACITY (16) command");
6972
6973                 if (arglist & CAM_ARG_VERBOSE)
6974                         cam_error_print(device, ccb, CAM_ESF_ALL,
6975                                         CAM_EPF_ALL, stderr);
6976
6977                 retval = 1;
6978                 goto bailout;
6979         }
6980
6981         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6982                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6983                 retval = 1;
6984                 goto bailout;
6985         }
6986
6987         maxsector = scsi_8btou64(rcaplong.addr);
6988         block_len = scsi_4btoul(rcaplong.length);
6989
6990 do_print:
6991         if (blocksizeonly == 0) {
6992                 /*
6993                  * Humanize implies !quiet, and also implies numblocks.
6994                  */
6995                 if (humanize != 0) {
6996                         char tmpstr[6];
6997                         int64_t tmpbytes;
6998                         int ret;
6999
7000                         tmpbytes = (maxsector + 1) * block_len;
7001                         ret = humanize_number(tmpstr, sizeof(tmpstr),
7002                                               tmpbytes, "", HN_AUTOSCALE,
7003                                               HN_B | HN_DECIMAL |
7004                                               ((baseten != 0) ?
7005                                               HN_DIVISOR_1000 : 0));
7006                         if (ret == -1) {
7007                                 warnx("%s: humanize_number failed!", __func__);
7008                                 retval = 1;
7009                                 goto bailout;
7010                         }
7011                         fprintf(stdout, "Device Size: %s%s", tmpstr,
7012                                 (sizeonly == 0) ?  ", " : "\n");
7013                 } else if (numblocks != 0) {
7014                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7015                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
7016                                 (sizeonly == 0) ? ", " : "\n");
7017                 } else {
7018                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7019                                 "Last Block: " : "", (uintmax_t)maxsector,
7020                                 (sizeonly == 0) ? ", " : "\n");
7021                 }
7022         }
7023         if (sizeonly == 0)
7024                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
7025                         "Block Length: " : "", block_len, (quiet == 0) ?
7026                         " bytes" : "");
7027 bailout:
7028         cam_freeccb(ccb);
7029
7030         return (retval);
7031 }
7032
7033 static int
7034 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
7035        int retry_count, int timeout)
7036 {
7037         int c, error = 0;
7038         union ccb *ccb;
7039         uint8_t *smp_request = NULL, *smp_response = NULL;
7040         int request_size = 0, response_size = 0;
7041         int fd_request = 0, fd_response = 0;
7042         char *datastr = NULL;
7043         struct get_hook hook;
7044         int retval;
7045         int flags = 0;
7046
7047         /*
7048          * Note that at the moment we don't support sending SMP CCBs to
7049          * devices that aren't probed by CAM.
7050          */
7051         ccb = cam_getccb(device);
7052         if (ccb == NULL) {
7053                 warnx("%s: error allocating CCB", __func__);
7054                 return (1);
7055         }
7056
7057         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7058
7059         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7060                 switch (c) {
7061                 case 'R':
7062                         arglist |= CAM_ARG_CMD_IN;
7063                         response_size = strtol(optarg, NULL, 0);
7064                         if (response_size <= 0) {
7065                                 warnx("invalid number of response bytes %d",
7066                                       response_size);
7067                                 error = 1;
7068                                 goto smpcmd_bailout;
7069                         }
7070                         hook.argc = argc - optind;
7071                         hook.argv = argv + optind;
7072                         hook.got = 0;
7073                         optind++;
7074                         datastr = cget(&hook, NULL);
7075                         /*
7076                          * If the user supplied "-" instead of a format, he
7077                          * wants the data to be written to stdout.
7078                          */
7079                         if ((datastr != NULL)
7080                          && (datastr[0] == '-'))
7081                                 fd_response = 1;
7082
7083                         smp_response = (u_int8_t *)malloc(response_size);
7084                         if (smp_response == NULL) {
7085                                 warn("can't malloc memory for SMP response");
7086                                 error = 1;
7087                                 goto smpcmd_bailout;
7088                         }
7089                         break;
7090                 case 'r':
7091                         arglist |= CAM_ARG_CMD_OUT;
7092                         request_size = strtol(optarg, NULL, 0);
7093                         if (request_size <= 0) {
7094                                 warnx("invalid number of request bytes %d",
7095                                       request_size);
7096                                 error = 1;
7097                                 goto smpcmd_bailout;
7098                         }
7099                         hook.argc = argc - optind;
7100                         hook.argv = argv + optind;
7101                         hook.got = 0;
7102                         datastr = cget(&hook, NULL);
7103                         smp_request = (u_int8_t *)malloc(request_size);
7104                         if (smp_request == NULL) {
7105                                 warn("can't malloc memory for SMP request");
7106                                 error = 1;
7107                                 goto smpcmd_bailout;
7108                         }
7109                         bzero(smp_request, request_size);
7110                         /*
7111                          * If the user supplied "-" instead of a format, he
7112                          * wants the data to be read from stdin.
7113                          */
7114                         if ((datastr != NULL)
7115                          && (datastr[0] == '-'))
7116                                 fd_request = 1;
7117                         else
7118                                 buff_encode_visit(smp_request, request_size,
7119                                                   datastr,
7120                                                   iget, &hook);
7121                         optind += hook.got;
7122                         break;
7123                 default:
7124                         break;
7125                 }
7126         }
7127
7128         /*
7129          * If fd_data is set, and we're writing to the device, we need to
7130          * read the data the user wants written from stdin.
7131          */
7132         if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
7133                 ssize_t amt_read;
7134                 int amt_to_read = request_size;
7135                 u_int8_t *buf_ptr = smp_request;
7136
7137                 for (amt_read = 0; amt_to_read > 0;
7138                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
7139                         if (amt_read == -1) {
7140                                 warn("error reading data from stdin");
7141                                 error = 1;
7142                                 goto smpcmd_bailout;
7143                         }
7144                         amt_to_read -= amt_read;
7145                         buf_ptr += amt_read;
7146                 }
7147         }
7148
7149         if (((arglist & CAM_ARG_CMD_IN) == 0)
7150          || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
7151                 warnx("%s: need both the request (-r) and response (-R) "
7152                       "arguments", __func__);
7153                 error = 1;
7154                 goto smpcmd_bailout;
7155         }
7156
7157         flags |= CAM_DEV_QFRZDIS;
7158
7159         cam_fill_smpio(&ccb->smpio,
7160                        /*retries*/ retry_count,
7161                        /*cbfcnp*/ NULL,
7162                        /*flags*/ flags,
7163                        /*smp_request*/ smp_request,
7164                        /*smp_request_len*/ request_size,
7165                        /*smp_response*/ smp_response,
7166                        /*smp_response_len*/ response_size,
7167                        /*timeout*/ timeout ? timeout : 5000);
7168
7169         ccb->smpio.flags = SMP_FLAG_NONE;
7170
7171         if (((retval = cam_send_ccb(device, ccb)) < 0)
7172          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7173                 const char warnstr[] = "error sending command";
7174
7175                 if (retval < 0)
7176                         warn(warnstr);
7177                 else
7178                         warnx(warnstr);
7179
7180                 if (arglist & CAM_ARG_VERBOSE) {
7181                         cam_error_print(device, ccb, CAM_ESF_ALL,
7182                                         CAM_EPF_ALL, stderr);
7183                 }
7184         }
7185
7186         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
7187          && (response_size > 0)) {
7188                 if (fd_response == 0) {
7189                         buff_decode_visit(smp_response, response_size,
7190                                           datastr, arg_put, NULL);
7191                         fprintf(stdout, "\n");
7192                 } else {
7193                         ssize_t amt_written;
7194                         int amt_to_write = response_size;
7195                         u_int8_t *buf_ptr = smp_response;
7196
7197                         for (amt_written = 0; (amt_to_write > 0) &&
7198                              (amt_written = write(STDOUT_FILENO, buf_ptr,
7199                                                   amt_to_write)) > 0;){
7200                                 amt_to_write -= amt_written;
7201                                 buf_ptr += amt_written;
7202                         }
7203                         if (amt_written == -1) {
7204                                 warn("error writing data to stdout");
7205                                 error = 1;
7206                                 goto smpcmd_bailout;
7207                         } else if ((amt_written == 0)
7208                                 && (amt_to_write > 0)) {
7209                                 warnx("only wrote %u bytes out of %u",
7210                                       response_size - amt_to_write, 
7211                                       response_size);
7212                         }
7213                 }
7214         }
7215 smpcmd_bailout:
7216         if (ccb != NULL)
7217                 cam_freeccb(ccb);
7218
7219         if (smp_request != NULL)
7220                 free(smp_request);
7221
7222         if (smp_response != NULL)
7223                 free(smp_response);
7224
7225         return (error);
7226 }
7227
7228 static int
7229 smpreportgeneral(struct cam_device *device, int argc, char **argv,
7230                  char *combinedopt, int retry_count, int timeout)
7231 {
7232         union ccb *ccb;
7233         struct smp_report_general_request *request = NULL;
7234         struct smp_report_general_response *response = NULL;
7235         struct sbuf *sb = NULL;
7236         int error = 0;
7237         int c, long_response = 0;
7238         int retval;
7239
7240         /*
7241          * Note that at the moment we don't support sending SMP CCBs to
7242          * devices that aren't probed by CAM.
7243          */
7244         ccb = cam_getccb(device);
7245         if (ccb == NULL) {
7246                 warnx("%s: error allocating CCB", __func__);
7247                 return (1);
7248         }
7249
7250         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7251
7252         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7253                 switch (c) {
7254                 case 'l':
7255                         long_response = 1;
7256                         break;
7257                 default:
7258                         break;
7259                 }
7260         }
7261         request = malloc(sizeof(*request));
7262         if (request == NULL) {
7263                 warn("%s: unable to allocate %zd bytes", __func__,
7264                      sizeof(*request));
7265                 error = 1;
7266                 goto bailout;
7267         }
7268
7269         response = malloc(sizeof(*response));
7270         if (response == NULL) {
7271                 warn("%s: unable to allocate %zd bytes", __func__,
7272                      sizeof(*response));
7273                 error = 1;
7274                 goto bailout;
7275         }
7276
7277 try_long:
7278         smp_report_general(&ccb->smpio,
7279                            retry_count,
7280                            /*cbfcnp*/ NULL,
7281                            request,
7282                            /*request_len*/ sizeof(*request),
7283                            (uint8_t *)response,
7284                            /*response_len*/ sizeof(*response),
7285                            /*long_response*/ long_response,
7286                            timeout);
7287
7288         if (((retval = cam_send_ccb(device, ccb)) < 0)
7289          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7290                 const char warnstr[] = "error sending command";
7291
7292                 if (retval < 0)
7293                         warn(warnstr);
7294                 else
7295                         warnx(warnstr);
7296
7297                 if (arglist & CAM_ARG_VERBOSE) {
7298                         cam_error_print(device, ccb, CAM_ESF_ALL,
7299                                         CAM_EPF_ALL, stderr);
7300                 }
7301                 error = 1;
7302                 goto bailout;
7303         }
7304
7305         /*
7306          * If the device supports the long response bit, try again and see
7307          * if we can get all of the data.
7308          */
7309         if ((response->long_response & SMP_RG_LONG_RESPONSE)
7310          && (long_response == 0)) {
7311                 ccb->ccb_h.status = CAM_REQ_INPROG;
7312                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7313                 long_response = 1;
7314                 goto try_long;
7315         }
7316
7317         /*
7318          * XXX KDM detect and decode SMP errors here.
7319          */
7320         sb = sbuf_new_auto();
7321         if (sb == NULL) {
7322                 warnx("%s: error allocating sbuf", __func__);
7323                 goto bailout;
7324         }
7325
7326         smp_report_general_sbuf(response, sizeof(*response), sb);
7327
7328         if (sbuf_finish(sb) != 0) {
7329                 warnx("%s: sbuf_finish", __func__);
7330                 goto bailout;
7331         }
7332
7333         printf("%s", sbuf_data(sb));
7334
7335 bailout:
7336         if (ccb != NULL)
7337                 cam_freeccb(ccb);
7338
7339         if (request != NULL)
7340                 free(request);
7341
7342         if (response != NULL)
7343                 free(response);
7344
7345         if (sb != NULL)
7346                 sbuf_delete(sb);
7347
7348         return (error);
7349 }
7350
7351 static struct camcontrol_opts phy_ops[] = {
7352         {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7353         {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7354         {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7355         {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7356         {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7357         {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7358         {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7359         {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7360         {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7361         {NULL, 0, 0, NULL}
7362 };
7363
7364 static int
7365 smpphycontrol(struct cam_device *device, int argc, char **argv,
7366               char *combinedopt, int retry_count, int timeout)
7367 {
7368         union ccb *ccb;
7369         struct smp_phy_control_request *request = NULL;
7370         struct smp_phy_control_response *response = NULL;
7371         int long_response = 0;
7372         int retval = 0;
7373         int phy = -1;
7374         uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7375         int phy_op_set = 0;
7376         uint64_t attached_dev_name = 0;
7377         int dev_name_set = 0;
7378         uint32_t min_plr = 0, max_plr = 0;
7379         uint32_t pp_timeout_val = 0;
7380         int slumber_partial = 0;
7381         int set_pp_timeout_val = 0;
7382         int c;
7383
7384         /*
7385          * Note that at the moment we don't support sending SMP CCBs to
7386          * devices that aren't probed by CAM.
7387          */
7388         ccb = cam_getccb(device);
7389         if (ccb == NULL) {
7390                 warnx("%s: error allocating CCB", __func__);
7391                 return (1);
7392         }
7393
7394         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7395
7396         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7397                 switch (c) {
7398                 case 'a':
7399                 case 'A':
7400                 case 's':
7401                 case 'S': {
7402                         int enable = -1;
7403
7404                         if (strcasecmp(optarg, "enable") == 0)
7405                                 enable = 1;
7406                         else if (strcasecmp(optarg, "disable") == 0)
7407                                 enable = 2;
7408                         else {
7409                                 warnx("%s: Invalid argument %s", __func__,
7410                                       optarg);
7411                                 retval = 1;
7412                                 goto bailout;
7413                         }
7414                         switch (c) {
7415                         case 's':
7416                                 slumber_partial |= enable <<
7417                                                    SMP_PC_SAS_SLUMBER_SHIFT;
7418                                 break;
7419                         case 'S':
7420                                 slumber_partial |= enable <<
7421                                                    SMP_PC_SAS_PARTIAL_SHIFT;
7422                                 break;
7423                         case 'a':
7424                                 slumber_partial |= enable <<
7425                                                    SMP_PC_SATA_SLUMBER_SHIFT;
7426                                 break;
7427                         case 'A':
7428                                 slumber_partial |= enable <<
7429                                                    SMP_PC_SATA_PARTIAL_SHIFT;
7430                                 break;
7431                         default:
7432                                 warnx("%s: programmer error", __func__);
7433                                 retval = 1;
7434                                 goto bailout;
7435                                 break; /*NOTREACHED*/
7436                         }
7437                         break;
7438                 }
7439                 case 'd':
7440                         attached_dev_name = (uintmax_t)strtoumax(optarg,
7441                                                                  NULL,0);
7442                         dev_name_set = 1;
7443                         break;
7444                 case 'l':
7445                         long_response = 1;
7446                         break;
7447                 case 'm':
7448                         /*
7449                          * We don't do extensive checking here, so this
7450                          * will continue to work when new speeds come out.
7451                          */
7452                         min_plr = strtoul(optarg, NULL, 0);
7453                         if ((min_plr == 0)
7454                          || (min_plr > 0xf)) {
7455                                 warnx("%s: invalid link rate %x",
7456                                       __func__, min_plr);
7457                                 retval = 1;
7458                                 goto bailout;
7459                         }
7460                         break;
7461                 case 'M':
7462                         /*
7463                          * We don't do extensive checking here, so this
7464                          * will continue to work when new speeds come out.
7465                          */
7466                         max_plr = strtoul(optarg, NULL, 0);
7467                         if ((max_plr == 0)
7468                          || (max_plr > 0xf)) {
7469                                 warnx("%s: invalid link rate %x",
7470                                       __func__, max_plr);
7471                                 retval = 1;
7472                                 goto bailout;
7473                         }
7474                         break;
7475                 case 'o': {
7476                         camcontrol_optret optreturn;
7477                         cam_argmask argnums;
7478                         const char *subopt;
7479
7480                         if (phy_op_set != 0) {
7481                                 warnx("%s: only one phy operation argument "
7482                                       "(-o) allowed", __func__);
7483                                 retval = 1;
7484                                 goto bailout;
7485                         }
7486
7487                         phy_op_set = 1;
7488
7489                         /*
7490                          * Allow the user to specify the phy operation
7491                          * numerically, as well as with a name.  This will
7492                          * future-proof it a bit, so options that are added
7493                          * in future specs can be used.
7494                          */
7495                         if (isdigit(optarg[0])) {
7496                                 phy_operation = strtoul(optarg, NULL, 0);
7497                                 if ((phy_operation == 0)
7498                                  || (phy_operation > 0xff)) {
7499                                         warnx("%s: invalid phy operation %#x",
7500                                               __func__, phy_operation);
7501                                         retval = 1;
7502                                         goto bailout;
7503                                 }
7504                                 break;
7505                         }
7506                         optreturn = getoption(phy_ops, optarg, &phy_operation,
7507                                               &argnums, &subopt);
7508
7509                         if (optreturn == CC_OR_AMBIGUOUS) {
7510                                 warnx("%s: ambiguous option %s", __func__,
7511                                       optarg);
7512                                 usage(0);
7513                                 retval = 1;
7514                                 goto bailout;
7515                         } else if (optreturn == CC_OR_NOT_FOUND) {
7516                                 warnx("%s: option %s not found", __func__,
7517                                       optarg);
7518                                 usage(0);
7519                                 retval = 1;
7520                                 goto bailout;
7521                         }
7522                         break;
7523                 }
7524                 case 'p':
7525                         phy = atoi(optarg);
7526                         break;
7527                 case 'T':
7528                         pp_timeout_val = strtoul(optarg, NULL, 0);
7529                         if (pp_timeout_val > 15) {
7530                                 warnx("%s: invalid partial pathway timeout "
7531                                       "value %u, need a value less than 16",
7532                                       __func__, pp_timeout_val);
7533                                 retval = 1;
7534                                 goto bailout;
7535                         }
7536                         set_pp_timeout_val = 1;
7537                         break;
7538                 default:
7539                         break;
7540                 }
7541         }
7542
7543         if (phy == -1) {
7544                 warnx("%s: a PHY (-p phy) argument is required",__func__);
7545                 retval = 1;
7546                 goto bailout;
7547         }
7548
7549         if (((dev_name_set != 0)
7550           && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7551          || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7552           && (dev_name_set == 0))) {
7553                 warnx("%s: -d name and -o setdevname arguments both "
7554                       "required to set device name", __func__);
7555                 retval = 1;
7556                 goto bailout;
7557         }
7558
7559         request = malloc(sizeof(*request));
7560         if (request == NULL) {
7561                 warn("%s: unable to allocate %zd bytes", __func__,
7562                      sizeof(*request));
7563                 retval = 1;
7564                 goto bailout;
7565         }
7566
7567         response = malloc(sizeof(*response));
7568         if (response == NULL) {
7569                 warn("%s: unable to allocate %zd bytes", __func__,
7570                      sizeof(*response));
7571                 retval = 1;
7572                 goto bailout;
7573         }
7574
7575         smp_phy_control(&ccb->smpio,
7576                         retry_count,
7577                         /*cbfcnp*/ NULL,
7578                         request,
7579                         sizeof(*request),
7580                         (uint8_t *)response,
7581                         sizeof(*response),
7582                         long_response,
7583                         /*expected_exp_change_count*/ 0,
7584                         phy,
7585                         phy_operation,
7586                         (set_pp_timeout_val != 0) ? 1 : 0,
7587                         attached_dev_name,
7588                         min_plr,
7589                         max_plr,
7590                         slumber_partial,
7591                         pp_timeout_val,
7592                         timeout);
7593
7594         if (((retval = cam_send_ccb(device, ccb)) < 0)
7595          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7596                 const char warnstr[] = "error sending command";
7597
7598                 if (retval < 0)
7599                         warn(warnstr);
7600                 else
7601                         warnx(warnstr);
7602
7603                 if (arglist & CAM_ARG_VERBOSE) {
7604                         /*
7605                          * Use CAM_EPF_NORMAL so we only get one line of
7606                          * SMP command decoding.
7607                          */
7608                         cam_error_print(device, ccb, CAM_ESF_ALL,
7609                                         CAM_EPF_NORMAL, stderr);
7610                 }
7611                 retval = 1;
7612                 goto bailout;
7613         }
7614
7615         /* XXX KDM print out something here for success? */
7616 bailout:
7617         if (ccb != NULL)
7618                 cam_freeccb(ccb);
7619
7620         if (request != NULL)
7621                 free(request);
7622
7623         if (response != NULL)
7624                 free(response);
7625
7626         return (retval);
7627 }
7628
7629 static int
7630 smpmaninfo(struct cam_device *device, int argc, char **argv,
7631            char *combinedopt, int retry_count, int timeout)
7632 {
7633         union ccb *ccb;
7634         struct smp_report_manuf_info_request request;
7635         struct smp_report_manuf_info_response response;
7636         struct sbuf *sb = NULL;
7637         int long_response = 0;
7638         int retval = 0;
7639         int c;
7640
7641         /*
7642          * Note that at the moment we don't support sending SMP CCBs to
7643          * devices that aren't probed by CAM.
7644          */
7645         ccb = cam_getccb(device);
7646         if (ccb == NULL) {
7647                 warnx("%s: error allocating CCB", __func__);
7648                 return (1);
7649         }
7650
7651         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7652
7653         while ((c = getopt(argc, argv, combinedopt)) != -1) {
7654                 switch (c) {
7655                 case 'l':
7656                         long_response = 1;
7657                         break;
7658                 default:
7659                         break;
7660                 }
7661         }
7662         bzero(&request, sizeof(request));
7663         bzero(&response, sizeof(response));
7664
7665         smp_report_manuf_info(&ccb->smpio,
7666                               retry_count,
7667                               /*cbfcnp*/ NULL,
7668                               &request,
7669                               sizeof(request),
7670                               (uint8_t *)&response,
7671                               sizeof(response),
7672                               long_response,
7673                               timeout);
7674
7675         if (((retval = cam_send_ccb(device, ccb)) < 0)
7676          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7677                 const char warnstr[] = "error sending command";
7678
7679                 if (retval < 0)
7680                         warn(warnstr);
7681                 else
7682                         warnx(warnstr);
7683
7684                 if (arglist & CAM_ARG_VERBOSE) {
7685                         cam_error_print(device, ccb, CAM_ESF_ALL,
7686                                         CAM_EPF_ALL, stderr);
7687                 }
7688                 retval = 1;
7689                 goto bailout;
7690         }
7691
7692         sb = sbuf_new_auto();
7693         if (sb == NULL) {
7694                 warnx("%s: error allocating sbuf", __func__);
7695                 goto bailout;
7696         }
7697
7698         smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7699
7700         if (sbuf_finish(sb) != 0) {
7701                 warnx("%s: sbuf_finish", __func__);
7702                 goto bailout;
7703         }
7704
7705         printf("%s", sbuf_data(sb));
7706
7707 bailout:
7708
7709         if (ccb != NULL)
7710                 cam_freeccb(ccb);
7711
7712         if (sb != NULL)
7713                 sbuf_delete(sb);
7714
7715         return (retval);
7716 }
7717
7718 static int
7719 getdevid(struct cam_devitem *item)
7720 {
7721         int retval = 0;
7722         union ccb *ccb = NULL;
7723
7724         struct cam_device *dev;
7725
7726         dev = cam_open_btl(item->dev_match.path_id,
7727                            item->dev_match.target_id,
7728                            item->dev_match.target_lun, O_RDWR, NULL);
7729
7730         if (dev == NULL) {
7731                 warnx("%s", cam_errbuf);
7732                 retval = 1;
7733                 goto bailout;
7734         }
7735
7736         item->device_id_len = 0;
7737
7738         ccb = cam_getccb(dev);
7739         if (ccb == NULL) {
7740                 warnx("%s: error allocating CCB", __func__);
7741                 retval = 1;
7742                 goto bailout;
7743         }
7744
7745         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai);
7746
7747         /*
7748          * On the first try, we just probe for the size of the data, and
7749          * then allocate that much memory and try again.
7750          */
7751 retry:
7752         ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7753         ccb->ccb_h.flags = CAM_DIR_IN;
7754         ccb->cdai.flags = CDAI_FLAG_NONE;
7755         ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7756         ccb->cdai.bufsiz = item->device_id_len;
7757         if (item->device_id_len != 0)
7758                 ccb->cdai.buf = (uint8_t *)item->device_id;
7759
7760         if (cam_send_ccb(dev, ccb) < 0) {
7761                 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7762                 retval = 1;
7763                 goto bailout;
7764         }
7765
7766         if (ccb->ccb_h.status != CAM_REQ_CMP) {
7767                 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7768                 retval = 1;
7769                 goto bailout;
7770         }
7771
7772         if (item->device_id_len == 0) {
7773                 /*
7774                  * This is our first time through.  Allocate the buffer,
7775                  * and then go back to get the data.
7776                  */
7777                 if (ccb->cdai.provsiz == 0) {
7778                         warnx("%s: invalid .provsiz field returned with "
7779                              "XPT_GDEV_ADVINFO CCB", __func__);
7780                         retval = 1;
7781                         goto bailout;
7782                 }
7783                 item->device_id_len = ccb->cdai.provsiz;
7784                 item->device_id = malloc(item->device_id_len);
7785                 if (item->device_id == NULL) {
7786                         warn("%s: unable to allocate %d bytes", __func__,
7787                              item->device_id_len);
7788                         retval = 1;
7789                         goto bailout;
7790                 }
7791                 ccb->ccb_h.status = CAM_REQ_INPROG;
7792                 goto retry;
7793         }
7794
7795 bailout:
7796         if (dev != NULL)
7797                 cam_close_device(dev);
7798
7799         if (ccb != NULL)
7800                 cam_freeccb(ccb);
7801
7802         return (retval);
7803 }
7804
7805 /*
7806  * XXX KDM merge this code with getdevtree()?
7807  */
7808 static int
7809 buildbusdevlist(struct cam_devlist *devlist)
7810 {
7811         union ccb ccb;
7812         int bufsize, fd = -1;
7813         struct dev_match_pattern *patterns;
7814         struct cam_devitem *item = NULL;
7815         int skip_device = 0;
7816         int retval = 0;
7817
7818         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7819                 warn("couldn't open %s", XPT_DEVICE);
7820                 return(1);
7821         }
7822
7823         bzero(&ccb, sizeof(union ccb));
7824
7825         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7826         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7827         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7828
7829         ccb.ccb_h.func_code = XPT_DEV_MATCH;
7830         bufsize = sizeof(struct dev_match_result) * 100;
7831         ccb.cdm.match_buf_len = bufsize;
7832         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7833         if (ccb.cdm.matches == NULL) {
7834                 warnx("can't malloc memory for matches");
7835                 close(fd);
7836                 return(1);
7837         }
7838         ccb.cdm.num_matches = 0;
7839         ccb.cdm.num_patterns = 2;
7840         ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7841                 ccb.cdm.num_patterns;
7842
7843         patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7844         if (patterns == NULL) {
7845                 warnx("can't malloc memory for patterns");
7846                 retval = 1;
7847                 goto bailout;
7848         }
7849
7850         ccb.cdm.patterns = patterns;
7851         bzero(patterns, ccb.cdm.pattern_buf_len);
7852
7853         patterns[0].type = DEV_MATCH_DEVICE;
7854         patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7855         patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7856         patterns[1].type = DEV_MATCH_PERIPH;
7857         patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7858         patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7859
7860         /*
7861          * We do the ioctl multiple times if necessary, in case there are
7862          * more than 100 nodes in the EDT.
7863          */
7864         do {
7865                 unsigned int i;
7866
7867                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7868                         warn("error sending CAMIOCOMMAND ioctl");
7869                         retval = 1;
7870                         goto bailout;
7871                 }
7872
7873                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7874                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7875                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7876                         warnx("got CAM error %#x, CDM error %d\n",
7877                               ccb.ccb_h.status, ccb.cdm.status);
7878                         retval = 1;
7879                         goto bailout;
7880                 }
7881
7882                 for (i = 0; i < ccb.cdm.num_matches; i++) {
7883                         switch (ccb.cdm.matches[i].type) {
7884                         case DEV_MATCH_DEVICE: {
7885                                 struct device_match_result *dev_result;
7886
7887                                 dev_result = 
7888                                      &ccb.cdm.matches[i].result.device_result;
7889
7890                                 if (dev_result->flags &
7891                                     DEV_RESULT_UNCONFIGURED) {
7892                                         skip_device = 1;
7893                                         break;
7894                                 } else
7895                                         skip_device = 0;
7896
7897                                 item = malloc(sizeof(*item));
7898                                 if (item == NULL) {
7899                                         warn("%s: unable to allocate %zd bytes",
7900                                              __func__, sizeof(*item));
7901                                         retval = 1;
7902                                         goto bailout;
7903                                 }
7904                                 bzero(item, sizeof(*item));
7905                                 bcopy(dev_result, &item->dev_match,
7906                                       sizeof(*dev_result));
7907                                 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7908                                                    links);
7909
7910                                 if (getdevid(item) != 0) {
7911                                         retval = 1;
7912                                         goto bailout;
7913                                 }
7914                                 break;
7915                         }
7916                         case DEV_MATCH_PERIPH: {
7917                                 struct periph_match_result *periph_result;
7918
7919                                 periph_result =
7920                                       &ccb.cdm.matches[i].result.periph_result;
7921
7922                                 if (skip_device != 0)
7923                                         break;
7924                                 item->num_periphs++;
7925                                 item->periph_matches = realloc(
7926                                         item->periph_matches,
7927                                         item->num_periphs *
7928                                         sizeof(struct periph_match_result));
7929                                 if (item->periph_matches == NULL) {
7930                                         warn("%s: error allocating periph "
7931                                              "list", __func__);
7932                                         retval = 1;
7933                                         goto bailout;
7934                                 }
7935                                 bcopy(periph_result, &item->periph_matches[
7936                                       item->num_periphs - 1],
7937                                       sizeof(*periph_result));
7938                                 break;
7939                         }
7940                         default:
7941                                 fprintf(stderr, "%s: unexpected match "
7942                                         "type %d\n", __func__,
7943                                         ccb.cdm.matches[i].type);
7944                                 retval = 1;
7945                                 goto bailout;
7946                                 break; /*NOTREACHED*/
7947                         }
7948                 }
7949         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7950                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7951 bailout:
7952
7953         if (fd != -1)
7954                 close(fd);
7955
7956         free(patterns);
7957
7958         free(ccb.cdm.matches);
7959
7960         if (retval != 0)
7961                 freebusdevlist(devlist);
7962
7963         return (retval);
7964 }
7965
7966 static void
7967 freebusdevlist(struct cam_devlist *devlist)
7968 {
7969         struct cam_devitem *item, *item2;
7970
7971         STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7972                 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7973                               links);
7974                 free(item->device_id);
7975                 free(item->periph_matches);
7976                 free(item);
7977         }
7978 }
7979
7980 static struct cam_devitem *
7981 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7982 {
7983         struct cam_devitem *item;
7984
7985         STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7986                 struct scsi_vpd_id_descriptor *idd;
7987
7988                 /*
7989                  * XXX KDM look for LUN IDs as well?
7990                  */
7991                 idd = scsi_get_devid(item->device_id,
7992                                            item->device_id_len,
7993                                            scsi_devid_is_sas_target);
7994                 if (idd == NULL)
7995                         continue;
7996
7997                 if (scsi_8btou64(idd->identifier) == sasaddr)
7998                         return (item);
7999         }
8000
8001         return (NULL);
8002 }
8003
8004 static int
8005 smpphylist(struct cam_device *device, int argc, char **argv,
8006            char *combinedopt, int retry_count, int timeout)
8007 {
8008         struct smp_report_general_request *rgrequest = NULL;
8009         struct smp_report_general_response *rgresponse = NULL;
8010         struct smp_discover_request *disrequest = NULL;
8011         struct smp_discover_response *disresponse = NULL;
8012         struct cam_devlist devlist;
8013         union ccb *ccb;
8014         int long_response = 0;
8015         int num_phys = 0;
8016         int quiet = 0;
8017         int retval;
8018         int i, c;
8019
8020         /*
8021          * Note that at the moment we don't support sending SMP CCBs to
8022          * devices that aren't probed by CAM.
8023          */
8024         ccb = cam_getccb(device);
8025         if (ccb == NULL) {
8026                 warnx("%s: error allocating CCB", __func__);
8027                 return (1);
8028         }
8029
8030         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8031         STAILQ_INIT(&devlist.dev_queue);
8032
8033         rgrequest = malloc(sizeof(*rgrequest));
8034         if (rgrequest == NULL) {
8035                 warn("%s: unable to allocate %zd bytes", __func__,
8036                      sizeof(*rgrequest));
8037                 retval = 1;
8038                 goto bailout;
8039         }
8040
8041         rgresponse = malloc(sizeof(*rgresponse));
8042         if (rgresponse == NULL) {
8043                 warn("%s: unable to allocate %zd bytes", __func__,
8044                      sizeof(*rgresponse));
8045                 retval = 1;
8046                 goto bailout;
8047         }
8048
8049         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8050                 switch (c) {
8051                 case 'l':
8052                         long_response = 1;
8053                         break;
8054                 case 'q':
8055                         quiet = 1;
8056                         break;
8057                 default:
8058                         break;
8059                 }
8060         }
8061
8062         smp_report_general(&ccb->smpio,
8063                            retry_count,
8064                            /*cbfcnp*/ NULL,
8065                            rgrequest,
8066                            /*request_len*/ sizeof(*rgrequest),
8067                            (uint8_t *)rgresponse,
8068                            /*response_len*/ sizeof(*rgresponse),
8069                            /*long_response*/ long_response,
8070                            timeout);
8071
8072         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8073
8074         if (((retval = cam_send_ccb(device, ccb)) < 0)
8075          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8076                 const char warnstr[] = "error sending command";
8077
8078                 if (retval < 0)
8079                         warn(warnstr);
8080                 else
8081                         warnx(warnstr);
8082
8083                 if (arglist & CAM_ARG_VERBOSE) {
8084                         cam_error_print(device, ccb, CAM_ESF_ALL,
8085                                         CAM_EPF_ALL, stderr);
8086                 }
8087                 retval = 1;
8088                 goto bailout;
8089         }
8090
8091         num_phys = rgresponse->num_phys;
8092
8093         if (num_phys == 0) {
8094                 if (quiet == 0)
8095                         fprintf(stdout, "%s: No Phys reported\n", __func__);
8096                 retval = 1;
8097                 goto bailout;
8098         }
8099
8100         devlist.path_id = device->path_id;
8101
8102         retval = buildbusdevlist(&devlist);
8103         if (retval != 0)
8104                 goto bailout;
8105
8106         if (quiet == 0) {
8107                 fprintf(stdout, "%d PHYs:\n", num_phys);
8108                 fprintf(stdout, "PHY  Attached SAS Address\n");
8109         }
8110
8111         disrequest = malloc(sizeof(*disrequest));
8112         if (disrequest == NULL) {
8113                 warn("%s: unable to allocate %zd bytes", __func__,
8114                      sizeof(*disrequest));
8115                 retval = 1;
8116                 goto bailout;
8117         }
8118
8119         disresponse = malloc(sizeof(*disresponse));
8120         if (disresponse == NULL) {
8121                 warn("%s: unable to allocate %zd bytes", __func__,
8122                      sizeof(*disresponse));
8123                 retval = 1;
8124                 goto bailout;
8125         }
8126
8127         for (i = 0; i < num_phys; i++) {
8128                 struct cam_devitem *item;
8129                 struct device_match_result *dev_match;
8130                 char vendor[16], product[48], revision[16];
8131                 char tmpstr[256];
8132                 int j;
8133
8134                 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8135
8136                 ccb->ccb_h.status = CAM_REQ_INPROG;
8137                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8138
8139                 smp_discover(&ccb->smpio,
8140                              retry_count,
8141                              /*cbfcnp*/ NULL,
8142                              disrequest,
8143                              sizeof(*disrequest),
8144                              (uint8_t *)disresponse,
8145                              sizeof(*disresponse),
8146                              long_response,
8147                              /*ignore_zone_group*/ 0,
8148                              /*phy*/ i,
8149                              timeout);
8150
8151                 if (((retval = cam_send_ccb(device, ccb)) < 0)
8152                  || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
8153                   && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
8154                         const char warnstr[] = "error sending command";
8155
8156                         if (retval < 0)
8157                                 warn(warnstr);
8158                         else
8159                                 warnx(warnstr);
8160
8161                         if (arglist & CAM_ARG_VERBOSE) {
8162                                 cam_error_print(device, ccb, CAM_ESF_ALL,
8163                                                 CAM_EPF_ALL, stderr);
8164                         }
8165                         retval = 1;
8166                         goto bailout;
8167                 }
8168
8169                 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
8170                         if (quiet == 0)
8171                                 fprintf(stdout, "%3d  <vacant>\n", i);
8172                         continue;
8173                 }
8174
8175                 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
8176                         item = NULL;
8177                 } else {
8178                         item = findsasdevice(&devlist,
8179                             scsi_8btou64(disresponse->attached_sas_address));
8180                 }
8181
8182                 if ((quiet == 0)
8183                  || (item != NULL)) {
8184                         fprintf(stdout, "%3d  0x%016jx", i,
8185                                 (uintmax_t)scsi_8btou64(
8186                                 disresponse->attached_sas_address));
8187                         if (item == NULL) {
8188                                 fprintf(stdout, "\n");
8189                                 continue;
8190                         }
8191                 } else if (quiet != 0)
8192                         continue;
8193
8194                 dev_match = &item->dev_match;
8195
8196                 if (dev_match->protocol == PROTO_SCSI) {
8197                         cam_strvis(vendor, dev_match->inq_data.vendor,
8198                                    sizeof(dev_match->inq_data.vendor),
8199                                    sizeof(vendor));
8200                         cam_strvis(product, dev_match->inq_data.product,
8201                                    sizeof(dev_match->inq_data.product),
8202                                    sizeof(product));
8203                         cam_strvis(revision, dev_match->inq_data.revision,
8204                                    sizeof(dev_match->inq_data.revision),
8205                                    sizeof(revision));
8206                         sprintf(tmpstr, "<%s %s %s>", vendor, product,
8207                                 revision);
8208                 } else if ((dev_match->protocol == PROTO_ATA)
8209                         || (dev_match->protocol == PROTO_SATAPM)) {
8210                         cam_strvis(product, dev_match->ident_data.model,
8211                                    sizeof(dev_match->ident_data.model),
8212                                    sizeof(product));
8213                         cam_strvis(revision, dev_match->ident_data.revision,
8214                                    sizeof(dev_match->ident_data.revision),
8215                                    sizeof(revision));
8216                         sprintf(tmpstr, "<%s %s>", product, revision);
8217                 } else {
8218                         sprintf(tmpstr, "<>");
8219                 }
8220                 fprintf(stdout, "   %-33s ", tmpstr);
8221
8222                 /*
8223                  * If we have 0 periphs, that's a bug...
8224                  */
8225                 if (item->num_periphs == 0) {
8226                         fprintf(stdout, "\n");
8227                         continue;
8228                 }
8229
8230                 fprintf(stdout, "(");
8231                 for (j = 0; j < item->num_periphs; j++) {
8232                         if (j > 0)
8233                                 fprintf(stdout, ",");
8234
8235                         fprintf(stdout, "%s%d",
8236                                 item->periph_matches[j].periph_name,
8237                                 item->periph_matches[j].unit_number);
8238                                 
8239                 }
8240                 fprintf(stdout, ")\n");
8241         }
8242 bailout:
8243         if (ccb != NULL)
8244                 cam_freeccb(ccb);
8245
8246         free(rgrequest);
8247
8248         free(rgresponse);
8249
8250         free(disrequest);
8251
8252         free(disresponse);
8253
8254         freebusdevlist(&devlist);
8255
8256         return (retval);
8257 }
8258
8259 static int
8260 atapm(struct cam_device *device, int argc, char **argv,
8261                  char *combinedopt, int retry_count, int timeout)
8262 {
8263         union ccb *ccb;
8264         int retval = 0;
8265         int t = -1;
8266         int c;
8267         u_char cmd, sc;
8268
8269         ccb = cam_getccb(device);
8270
8271         if (ccb == NULL) {
8272                 warnx("%s: error allocating ccb", __func__);
8273                 return (1);
8274         }
8275
8276         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8277                 switch (c) {
8278                 case 't':
8279                         t = atoi(optarg);
8280                         break;
8281                 default:
8282                         break;
8283                 }
8284         }
8285         if (strcmp(argv[1], "idle") == 0) {
8286                 if (t == -1)
8287                         cmd = ATA_IDLE_IMMEDIATE;
8288                 else
8289                         cmd = ATA_IDLE_CMD;
8290         } else if (strcmp(argv[1], "standby") == 0) {
8291                 if (t == -1)
8292                         cmd = ATA_STANDBY_IMMEDIATE;
8293                 else
8294                         cmd = ATA_STANDBY_CMD;
8295         } else {
8296                 cmd = ATA_SLEEP;
8297                 t = -1;
8298         }
8299
8300         if (t < 0)
8301                 sc = 0;
8302         else if (t <= (240 * 5))
8303                 sc = (t + 4) / 5;
8304         else if (t <= (252 * 5))
8305                 /* special encoding for 21 minutes */
8306                 sc = 252;
8307         else if (t <= (11 * 30 * 60))
8308                 sc = (t - 1) / (30 * 60) + 241;
8309         else
8310                 sc = 253;
8311
8312         retval = ata_do_28bit_cmd(device,
8313             ccb,
8314             /*retries*/retry_count,
8315             /*flags*/CAM_DIR_NONE,
8316             /*protocol*/AP_PROTO_NON_DATA,
8317             /*tag_action*/MSG_SIMPLE_Q_TAG,
8318             /*command*/cmd,
8319             /*features*/0,
8320             /*lba*/0,
8321             /*sector_count*/sc,
8322             /*data_ptr*/NULL,
8323             /*dxfer_len*/0,
8324             /*timeout*/timeout ? timeout : 30 * 1000,
8325             /*quiet*/1);
8326
8327         cam_freeccb(ccb);
8328         return (retval);
8329 }
8330
8331 static int
8332 ataaxm(struct cam_device *device, int argc, char **argv,
8333                  char *combinedopt, int retry_count, int timeout)
8334 {
8335         union ccb *ccb;
8336         int retval = 0;
8337         int l = -1;
8338         int c;
8339         u_char cmd, sc;
8340
8341         ccb = cam_getccb(device);
8342
8343         if (ccb == NULL) {
8344                 warnx("%s: error allocating ccb", __func__);
8345                 return (1);
8346         }
8347
8348         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8349                 switch (c) {
8350                 case 'l':
8351                         l = atoi(optarg);
8352                         break;
8353                 default:
8354                         break;
8355                 }
8356         }
8357         sc = 0;
8358         if (strcmp(argv[1], "apm") == 0) {
8359                 if (l == -1)
8360                         cmd = 0x85;
8361                 else {
8362                         cmd = 0x05;
8363                         sc = l;
8364                 }
8365         } else /* aam */ {
8366                 if (l == -1)
8367                         cmd = 0xC2;
8368                 else {
8369                         cmd = 0x42;
8370                         sc = l;
8371                 }
8372         }
8373
8374         retval = ata_do_28bit_cmd(device,
8375             ccb,
8376             /*retries*/retry_count,
8377             /*flags*/CAM_DIR_NONE,
8378             /*protocol*/AP_PROTO_NON_DATA,
8379             /*tag_action*/MSG_SIMPLE_Q_TAG,
8380             /*command*/ATA_SETFEATURES,
8381             /*features*/cmd,
8382             /*lba*/0,
8383             /*sector_count*/sc,
8384             /*data_ptr*/NULL,
8385             /*dxfer_len*/0,
8386             /*timeout*/timeout ? timeout : 30 * 1000,
8387             /*quiet*/1);
8388
8389         cam_freeccb(ccb);
8390         return (retval);
8391 }
8392
8393 int
8394 scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8395                int show_sa_errors, int sa_set, int service_action,
8396                int timeout_desc, int task_attr, int retry_count, int timeout,
8397                int verbosemode, uint32_t *fill_len, uint8_t **data_ptr)
8398 {
8399         union ccb *ccb = NULL;
8400         uint8_t *buf = NULL;
8401         uint32_t alloc_len = 0, num_opcodes;
8402         uint32_t valid_len = 0;
8403         uint32_t avail_len = 0;
8404         struct scsi_report_supported_opcodes_all *all_hdr;
8405         struct scsi_report_supported_opcodes_one *one;
8406         int options = 0;
8407         int retval = 0;
8408
8409         /*
8410          * Make it clear that we haven't yet allocated or filled anything.
8411          */
8412         *fill_len = 0;
8413         *data_ptr = NULL;
8414
8415         ccb = cam_getccb(device);
8416         if (ccb == NULL) {
8417                 warnx("couldn't allocate CCB");
8418                 retval = 1;
8419                 goto bailout;
8420         }
8421
8422         /* cam_getccb cleans up the header, caller has to zero the payload */
8423         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8424
8425         if (opcode_set != 0) {
8426                 options |= RSO_OPTIONS_OC;
8427                 num_opcodes = 1;
8428                 alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8429         } else {
8430                 num_opcodes = 256;
8431                 alloc_len = sizeof(*all_hdr) + (num_opcodes *
8432                     sizeof(struct scsi_report_supported_opcodes_descr));
8433         }
8434
8435         if (timeout_desc != 0) {
8436                 options |= RSO_RCTD;
8437                 alloc_len += num_opcodes *
8438                     sizeof(struct scsi_report_supported_opcodes_timeout);
8439         }
8440         
8441         if (sa_set != 0) {
8442                 options |= RSO_OPTIONS_OC_SA;
8443                 if (show_sa_errors != 0)
8444                         options &= ~RSO_OPTIONS_OC;
8445         }
8446
8447 retry_alloc:
8448         if (buf != NULL) {
8449                 free(buf);
8450                 buf = NULL;
8451         } 
8452
8453         buf = malloc(alloc_len);
8454         if (buf == NULL) {
8455                 warn("Unable to allocate %u bytes", alloc_len);
8456                 retval = 1;
8457                 goto bailout;
8458         }
8459         bzero(buf, alloc_len);
8460
8461         scsi_report_supported_opcodes(&ccb->csio,
8462                                       /*retries*/ retry_count,
8463                                       /*cbfcnp*/ NULL,
8464                                       /*tag_action*/ task_attr,
8465                                       /*options*/ options,
8466                                       /*req_opcode*/ opcode,
8467                                       /*req_service_action*/ service_action,
8468                                       /*data_ptr*/ buf,
8469                                       /*dxfer_len*/ alloc_len,
8470                                       /*sense_len*/ SSD_FULL_SIZE,
8471                                       /*timeout*/ timeout ? timeout : 10000);
8472
8473         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8474
8475         if (retry_count != 0)
8476                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
8477
8478         if (cam_send_ccb(device, ccb) < 0) {
8479                 perror("error sending REPORT SUPPORTED OPERATION CODES");
8480                 retval = 1;
8481                 goto bailout;
8482         }
8483
8484         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8485                 if (verbosemode != 0)
8486                         cam_error_print(device, ccb, CAM_ESF_ALL,
8487                                         CAM_EPF_ALL, stderr);
8488                 
8489                 retval = 1;
8490                 goto bailout;
8491         }
8492
8493         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
8494
8495         if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
8496          && (valid_len >= sizeof(*all_hdr))) {
8497                 all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
8498                 avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
8499         } else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
8500                 && (valid_len >= sizeof(*one))) {
8501                 uint32_t cdb_length;
8502
8503                 one = (struct scsi_report_supported_opcodes_one *)buf;
8504                 cdb_length = scsi_2btoul(one->cdb_length);
8505                 avail_len = sizeof(*one) + cdb_length;
8506                 if (one->support & RSO_ONE_CTDP) {
8507                         struct scsi_report_supported_opcodes_timeout *td;
8508
8509                         td = (struct scsi_report_supported_opcodes_timeout *)
8510                             &buf[avail_len];
8511                         if (valid_len >= (avail_len + sizeof(td->length))) {
8512                                 avail_len += scsi_2btoul(td->length) +
8513                                     sizeof(td->length);
8514                         } else {
8515                                 avail_len += sizeof(*td);
8516                         }
8517                 }
8518         }
8519
8520         /*
8521          * avail_len could be zero if we didn't get enough data back from
8522          * thet target to determine
8523          */
8524         if ((avail_len != 0)
8525          && (avail_len > valid_len)) {
8526                 alloc_len = avail_len;
8527                 goto retry_alloc;
8528         }
8529
8530         *fill_len = valid_len;
8531         *data_ptr = buf;
8532 bailout:
8533         if (retval != 0)
8534                 free(buf);
8535
8536         cam_freeccb(ccb);
8537
8538         return (retval);
8539 }
8540
8541 static int
8542 scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
8543                    int req_sa, uint8_t *buf, uint32_t valid_len)
8544 {
8545         struct scsi_report_supported_opcodes_one *one;
8546         struct scsi_report_supported_opcodes_timeout *td;
8547         uint32_t cdb_len = 0, td_len = 0;
8548         const char *op_desc = NULL;
8549         unsigned int i;
8550         int retval = 0;
8551
8552         one = (struct scsi_report_supported_opcodes_one *)buf;
8553
8554         /*
8555          * If we don't have the full single opcode descriptor, no point in
8556          * continuing.
8557          */
8558         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8559             cdb_length)) {
8560                 warnx("Only %u bytes returned, not enough to verify support",
8561                       valid_len);
8562                 retval = 1;
8563                 goto bailout;
8564         }
8565
8566         op_desc = scsi_op_desc(req_opcode, &device->inq_data);
8567
8568         printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
8569                req_opcode);
8570         if (sa_set != 0)
8571                 printf(", SA 0x%x", req_sa);
8572         printf(": ");
8573
8574         switch (one->support & RSO_ONE_SUP_MASK) {
8575         case RSO_ONE_SUP_UNAVAIL:
8576                 printf("No command support information currently available\n");
8577                 break;
8578         case RSO_ONE_SUP_NOT_SUP:
8579                 printf("Command not supported\n");
8580                 retval = 1;
8581                 goto bailout;
8582                 break; /*NOTREACHED*/
8583         case RSO_ONE_SUP_AVAIL:
8584                 printf("Command is supported, complies with a SCSI standard\n");
8585                 break;
8586         case RSO_ONE_SUP_VENDOR:
8587                 printf("Command is supported, vendor-specific "
8588                        "implementation\n");
8589                 break;
8590         default:
8591                 printf("Unknown command support flags 0x%#x\n",
8592                        one->support & RSO_ONE_SUP_MASK);
8593                 break;
8594         }
8595
8596         /*
8597          * If we don't have the CDB length, it isn't exactly an error, the
8598          * command probably isn't supported.
8599          */
8600         if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8601             cdb_usage))
8602                 goto bailout;
8603
8604         cdb_len = scsi_2btoul(one->cdb_length);
8605
8606         /*
8607          * If our valid data doesn't include the full reported length,
8608          * return.  The caller should have detected this and adjusted his
8609          * allocation length to get all of the available data.
8610          */
8611         if (valid_len < sizeof(*one) + cdb_len) {
8612                 retval = 1;
8613                 goto bailout;
8614         }
8615
8616         /*
8617          * If all we have is the opcode, there is no point in printing out
8618          * the usage bitmap.
8619          */
8620         if (cdb_len <= 1) {
8621                 retval = 1;
8622                 goto bailout;
8623         }
8624
8625         printf("CDB usage bitmap:");
8626         for (i = 0; i < cdb_len; i++) {
8627                 printf(" %02x", one->cdb_usage[i]);
8628         }
8629         printf("\n");
8630
8631         /*
8632          * If we don't have a timeout descriptor, we're done.
8633          */
8634         if ((one->support & RSO_ONE_CTDP) == 0)
8635                 goto bailout;
8636
8637         /*
8638          * If we don't have enough valid length to include the timeout
8639          * descriptor length, we're done.
8640          */
8641         if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
8642                 goto bailout;
8643
8644         td = (struct scsi_report_supported_opcodes_timeout *)
8645             &buf[sizeof(*one) + cdb_len];
8646         td_len = scsi_2btoul(td->length);
8647         td_len += sizeof(td->length);
8648
8649         /*
8650          * If we don't have the full timeout descriptor, we're done.
8651          */
8652         if (td_len < sizeof(*td))
8653                 goto bailout;
8654
8655         /*
8656          * If we don't have enough valid length to contain the full timeout
8657          * descriptor, we're done.
8658          */
8659         if (valid_len < (sizeof(*one) + cdb_len + td_len))
8660                 goto bailout;
8661
8662         printf("Timeout information:\n");
8663         printf("Command-specific:    0x%02x\n", td->cmd_specific);
8664         printf("Nominal timeout:     %u seconds\n",
8665                scsi_4btoul(td->nominal_time));
8666         printf("Recommended timeout: %u seconds\n",
8667                scsi_4btoul(td->recommended_time));
8668
8669 bailout:
8670         return (retval);
8671 }
8672
8673 static int
8674 scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
8675                  uint32_t valid_len)
8676 {
8677         struct scsi_report_supported_opcodes_all *hdr;
8678         struct scsi_report_supported_opcodes_descr *desc;
8679         uint32_t avail_len = 0, used_len = 0;
8680         uint8_t *cur_ptr;
8681         int retval = 0;
8682
8683         if (valid_len < sizeof(*hdr)) {
8684                 warnx("%s: not enough returned data (%u bytes) opcode list",
8685                       __func__, valid_len);
8686                 retval = 1;
8687                 goto bailout;
8688         }
8689         hdr = (struct scsi_report_supported_opcodes_all *)buf;
8690         avail_len = scsi_4btoul(hdr->length);
8691         avail_len += sizeof(hdr->length);
8692         /*
8693          * Take the lesser of the amount of data the drive claims is
8694          * available, and the amount of data the HBA says was returned.
8695          */
8696         avail_len = MIN(avail_len, valid_len);
8697
8698         used_len = sizeof(hdr->length);
8699
8700         printf("%-6s %4s %8s ",
8701                "Opcode", "SA", "CDB len" );
8702
8703         if (td_req != 0)
8704                 printf("%5s %6s %6s ", "CS", "Nom", "Rec");
8705         printf(" Description\n");
8706
8707         while ((avail_len - used_len) > sizeof(*desc)) {
8708                 struct scsi_report_supported_opcodes_timeout *td;
8709                 uint32_t td_len;
8710                 const char *op_desc = NULL;
8711
8712                 cur_ptr = &buf[used_len];
8713                 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
8714
8715                 op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
8716                 if (op_desc == NULL)
8717                         op_desc = "UNKNOWN";
8718
8719                 printf("0x%02x   %#4x %8u ", desc->opcode,
8720                        scsi_2btoul(desc->service_action),
8721                        scsi_2btoul(desc->cdb_length));
8722
8723                 used_len += sizeof(*desc);
8724
8725                 if ((desc->flags & RSO_CTDP) == 0) {
8726                         printf(" %s\n", op_desc);
8727                         continue;
8728                 }
8729
8730                 /*
8731                  * If we don't have enough space to fit a timeout
8732                  * descriptor, then we're done.
8733                  */
8734                 if (avail_len - used_len < sizeof(*td)) {
8735                         used_len = avail_len;
8736                         printf(" %s\n", op_desc);
8737                         continue;
8738                 }
8739                 cur_ptr = &buf[used_len];
8740                 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
8741                 td_len = scsi_2btoul(td->length);
8742                 td_len += sizeof(td->length);
8743
8744                 used_len += td_len;
8745                 /*
8746                  * If the given timeout descriptor length is less than what
8747                  * we understand, skip it.
8748                  */
8749                 if (td_len < sizeof(*td)) {
8750                         printf(" %s\n", op_desc);
8751                         continue;
8752                 }
8753
8754                 printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
8755                        scsi_4btoul(td->nominal_time),
8756                        scsi_4btoul(td->recommended_time), op_desc);
8757         }
8758 bailout:
8759         return (retval);
8760 }
8761
8762 static int
8763 scsiopcodes(struct cam_device *device, int argc, char **argv,
8764             char *combinedopt, int task_attr, int retry_count, int timeout,
8765             int verbosemode)
8766 {
8767         int c;
8768         uint32_t opcode = 0, service_action = 0;
8769         int td_set = 0, opcode_set = 0, sa_set = 0;
8770         int show_sa_errors = 1;
8771         uint32_t valid_len = 0;
8772         uint8_t *buf = NULL;
8773         char *endptr;
8774         int retval = 0;
8775
8776         while ((c = getopt(argc, argv, combinedopt)) != -1) {
8777                 switch (c) {
8778                 case 'N':
8779                         show_sa_errors = 0;
8780                         break;
8781                 case 'o':
8782                         opcode = strtoul(optarg, &endptr, 0);
8783                         if (*endptr != '\0') {
8784                                 warnx("Invalid opcode \"%s\", must be a number",
8785                                       optarg);
8786                                 retval = 1;
8787                                 goto bailout;
8788                         }
8789                         if (opcode > 0xff) {
8790                                 warnx("Invalid opcode 0x%#x, must be between"
8791                                       "0 and 0xff inclusive", opcode);
8792                                 retval = 1;
8793                                 goto bailout;
8794                         }
8795                         opcode_set = 1;
8796                         break;
8797                 case 's':
8798                         service_action = strtoul(optarg, &endptr, 0);
8799                         if (*endptr != '\0') {
8800                                 warnx("Invalid service action \"%s\", must "
8801                                       "be a number", optarg);
8802                                 retval = 1;
8803                                 goto bailout;
8804                         }
8805                         if (service_action > 0xffff) {
8806                                 warnx("Invalid service action 0x%#x, must "
8807                                       "be between 0 and 0xffff inclusive",
8808                                       service_action);
8809                                 retval = 1;
8810                         }
8811                         sa_set = 1;
8812                         break;
8813                 case 'T':
8814                         td_set = 1;
8815                         break;
8816                 default:
8817                         break;
8818                 }
8819         }
8820
8821         if ((sa_set != 0)
8822          && (opcode_set == 0)) {
8823                 warnx("You must specify an opcode with -o if a service "
8824                       "action is given");
8825                 retval = 1;
8826                 goto bailout;
8827         }
8828         retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
8829                                 sa_set, service_action, td_set, task_attr,
8830                                 retry_count, timeout, verbosemode, &valid_len,
8831                                 &buf);
8832         if (retval != 0)
8833                 goto bailout;
8834
8835         if ((opcode_set != 0)
8836          || (sa_set != 0)) {
8837                 retval = scsiprintoneopcode(device, opcode, sa_set,
8838                                             service_action, buf, valid_len);
8839         } else {
8840                 retval = scsiprintopcodes(device, td_set, buf, valid_len);
8841         }
8842
8843 bailout:
8844         free(buf);
8845
8846         return (retval);
8847 }
8848
8849 #endif /* MINIMALISTIC */
8850
8851 static int
8852 scsireprobe(struct cam_device *device)
8853 {
8854         union ccb *ccb;
8855         int retval = 0;
8856
8857         ccb = cam_getccb(device);
8858
8859         if (ccb == NULL) {
8860                 warnx("%s: error allocating ccb", __func__);
8861                 return (1);
8862         }
8863
8864         CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8865
8866         ccb->ccb_h.func_code = XPT_REPROBE_LUN;
8867
8868         if (cam_send_ccb(device, ccb) < 0) {
8869                 warn("error sending XPT_REPROBE_LUN CCB");
8870                 retval = 1;
8871                 goto bailout;
8872         }
8873
8874         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8875                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
8876                 retval = 1;
8877                 goto bailout;
8878         }
8879
8880 bailout:
8881         cam_freeccb(ccb);
8882
8883         return (retval);
8884 }
8885
8886 void
8887 usage(int printlong)
8888 {
8889
8890         fprintf(printlong ? stdout : stderr,
8891 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
8892 "        camcontrol devlist    [-b] [-v]\n"
8893 #ifndef MINIMALISTIC
8894 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8895 "        camcontrol tur        [dev_id][generic args]\n"
8896 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
8897 "        camcontrol identify   [dev_id][generic args] [-v]\n"
8898 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8899 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8900 "                              [-q] [-s]\n"
8901 "        camcontrol start      [dev_id][generic args]\n"
8902 "        camcontrol stop       [dev_id][generic args]\n"
8903 "        camcontrol load       [dev_id][generic args]\n"
8904 "        camcontrol eject      [dev_id][generic args]\n"
8905 "        camcontrol reprobe    [dev_id][generic args]\n"
8906 #endif /* MINIMALISTIC */
8907 "        camcontrol rescan     <all | bus[:target:lun]>\n"
8908 "        camcontrol reset      <all | bus[:target:lun]>\n"
8909 #ifndef MINIMALISTIC
8910 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
8911 "                              [-q][-s][-S offset][-X]\n"
8912 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
8913 "                              [-P pagectl][-e | -b][-d]\n"
8914 "        camcontrol cmd        [dev_id][generic args]\n"
8915 "                              <-a cmd [args] | -c cmd [args]>\n"
8916 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8917 "        camcontrol smpcmd     [dev_id][generic args]\n"
8918 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
8919 "        camcontrol smprg      [dev_id][generic args][-l]\n"
8920 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
8921 "                              [-o operation][-d name][-m rate][-M rate]\n"
8922 "                              [-T pp_timeout][-a enable|disable]\n"
8923 "                              [-A enable|disable][-s enable|disable]\n"
8924 "                              [-S enable|disable]\n"
8925 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8926 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8927 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
8928 "                              <all|bus[:target[:lun]]|off>\n"
8929 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
8930 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
8931 "                              [-D <enable|disable>][-M mode][-O offset]\n"
8932 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
8933 "                              [-U][-W bus_width]\n"
8934 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
8935 "        camcontrol sanitize   [dev_id][generic args]\n"
8936 "                              [-a overwrite|block|crypto|exitfailure]\n"
8937 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8938 "                              [-y]\n"
8939 "        camcontrol idle       [dev_id][generic args][-t time]\n"
8940 "        camcontrol standby    [dev_id][generic args][-t time]\n"
8941 "        camcontrol sleep      [dev_id][generic args]\n"
8942 "        camcontrol apm        [dev_id][generic args][-l level]\n"
8943 "        camcontrol aam        [dev_id][generic args][-l level]\n"
8944 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
8945 "                              [-s][-y]\n"
8946 "        camcontrol security   [dev_id][generic args]\n"
8947 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8948 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8949 "                              [-U <user|master>] [-y]\n"
8950 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8951 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
8952 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
8953 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8954 "                              [-s scope][-S][-T type][-U]\n"
8955 "        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
8956 "                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
8957 "                              [-p part][-s start][-T type][-V vol]\n"
8958 "        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
8959 "                              [-N][-T]\n"
8960 "        camcontrol zone       [dev_id][generic args]<-c cmd> [-a] [-l LBA]\n"
8961 "                              [-o rep_opts] [-P print_opts]\n"
8962 "        camcontrol epc        [dev_id][generic_args]<-c cmd> [-d] [-D] [-e]\n"
8963 "                              [-H] [-p power_cond] [-P] [-r rst_src] [-s]\n"
8964 "                              [-S power_src] [-T timer]\n"
8965 "        camcontrol timestamp  [dev_id][generic_args] <-r [-f format|-m|-U]>|\n"
8966 "                              <-s <-f format -T time | -U >>\n"
8967 "                              \n"
8968 #endif /* MINIMALISTIC */
8969 "        camcontrol help\n");
8970         if (!printlong)
8971                 return;
8972 #ifndef MINIMALISTIC
8973         fprintf(stdout,
8974 "Specify one of the following options:\n"
8975 "devlist     list all CAM devices\n"
8976 "periphlist  list all CAM peripheral drivers attached to a device\n"
8977 "tur         send a test unit ready to the named device\n"
8978 "inquiry     send a SCSI inquiry command to the named device\n"
8979 "identify    send a ATA identify command to the named device\n"
8980 "reportluns  send a SCSI report luns command to the device\n"
8981 "readcap     send a SCSI read capacity command to the device\n"
8982 "start       send a Start Unit command to the device\n"
8983 "stop        send a Stop Unit command to the device\n"
8984 "load        send a Start Unit command to the device with the load bit set\n"
8985 "eject       send a Stop Unit command to the device with the eject bit set\n"
8986 "reprobe     update capacity information of the given device\n"
8987 "rescan      rescan all buses, the given bus, or bus:target:lun\n"
8988 "reset       reset all buses, the given bus, or bus:target:lun\n"
8989 "defects     read the defect list of the specified device\n"
8990 "modepage    display or edit (-e) the given mode page\n"
8991 "cmd         send the given SCSI command, may need -i or -o as well\n"
8992 "smpcmd      send the given SMP command, requires -o and -i\n"
8993 "smprg       send the SMP Report General command\n"
8994 "smppc       send the SMP PHY Control command, requires -p\n"
8995 "smpphylist  display phys attached to a SAS expander\n"
8996 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
8997 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
8998 "tags        report or set the number of transaction slots for a device\n"
8999 "negotiate   report or set device negotiation parameters\n"
9000 "format      send the SCSI FORMAT UNIT command to the named device\n"
9001 "sanitize    send the SCSI SANITIZE command to the named device\n"
9002 "idle        send the ATA IDLE command to the named device\n"
9003 "standby     send the ATA STANDBY command to the named device\n"
9004 "sleep       send the ATA SLEEP command to the named device\n"
9005 "fwdownload  program firmware of the named device with the given image\n"
9006 "security    report or send ATA security commands to the named device\n"
9007 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
9008 "attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
9009 "opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
9010 "zone        manage Zoned Block (Shingled) devices\n"
9011 "epc         send ATA Extended Power Conditions commands\n"
9012 "timestamp   report or set the device's timestamp\n"
9013 "help        this message\n"
9014 "Device Identifiers:\n"
9015 "bus:target        specify the bus and target, lun defaults to 0\n"
9016 "bus:target:lun    specify the bus, target and lun\n"
9017 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
9018 "Generic arguments:\n"
9019 "-v                be verbose, print out sense information\n"
9020 "-t timeout        command timeout in seconds, overrides default timeout\n"
9021 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
9022 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
9023 "-E                have the kernel attempt to perform SCSI error recovery\n"
9024 "-C count          specify the SCSI command retry count (needs -E to work)\n"
9025 "-Q task_attr      specify ordered, simple or head tag type for SCSI cmds\n"
9026 "modepage arguments:\n"
9027 "-l                list all available mode pages\n"
9028 "-m page           specify the mode page to view or edit\n"
9029 "-e                edit the specified mode page\n"
9030 "-b                force view to binary mode\n"
9031 "-d                disable block descriptors for mode sense\n"
9032 "-P pgctl          page control field 0-3\n"
9033 "defects arguments:\n"
9034 "-f format         specify defect list format (block, bfi or phys)\n"
9035 "-G                get the grown defect list\n"
9036 "-P                get the permanent defect list\n"
9037 "inquiry arguments:\n"
9038 "-D                get the standard inquiry data\n"
9039 "-S                get the serial number\n"
9040 "-R                get the transfer rate, etc.\n"
9041 "reportluns arguments:\n"
9042 "-c                only report a count of available LUNs\n"
9043 "-l                only print out luns, and not a count\n"
9044 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
9045 "readcap arguments\n"
9046 "-b                only report the blocksize\n"
9047 "-h                human readable device size, base 2\n"
9048 "-H                human readable device size, base 10\n"
9049 "-N                print the number of blocks instead of last block\n"
9050 "-q                quiet, print numbers only\n"
9051 "-s                only report the last block/device size\n"
9052 "cmd arguments:\n"
9053 "-c cdb [args]     specify the SCSI CDB\n"
9054 "-i len fmt        specify input data and input data format\n"
9055 "-o len fmt [args] specify output data and output data fmt\n"
9056 "smpcmd arguments:\n"
9057 "-r len fmt [args] specify the SMP command to be sent\n"
9058 "-R len fmt [args] specify SMP response format\n"
9059 "smprg arguments:\n"
9060 "-l                specify the long response format\n"
9061 "smppc arguments:\n"
9062 "-p phy            specify the PHY to operate on\n"
9063 "-l                specify the long request/response format\n"
9064 "-o operation      specify the phy control operation\n"
9065 "-d name           set the attached device name\n"
9066 "-m rate           set the minimum physical link rate\n"
9067 "-M rate           set the maximum physical link rate\n"
9068 "-T pp_timeout     set the partial pathway timeout value\n"
9069 "-a enable|disable enable or disable SATA slumber\n"
9070 "-A enable|disable enable or disable SATA partial phy power\n"
9071 "-s enable|disable enable or disable SAS slumber\n"
9072 "-S enable|disable enable or disable SAS partial phy power\n"
9073 "smpphylist arguments:\n"
9074 "-l                specify the long response format\n"
9075 "-q                only print phys with attached devices\n"
9076 "smpmaninfo arguments:\n"
9077 "-l                specify the long response format\n"
9078 "debug arguments:\n"
9079 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
9080 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
9081 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
9082 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
9083 "tags arguments:\n"
9084 "-N tags           specify the number of tags to use for this device\n"
9085 "-q                be quiet, don't report the number of tags\n"
9086 "-v                report a number of tag-related parameters\n"
9087 "negotiate arguments:\n"
9088 "-a                send a test unit ready after negotiation\n"
9089 "-c                report/set current negotiation settings\n"
9090 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
9091 "-M mode           set ATA mode\n"
9092 "-O offset         set command delay offset\n"
9093 "-q                be quiet, don't report anything\n"
9094 "-R syncrate       synchronization rate in MHz\n"
9095 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
9096 "-U                report/set user negotiation settings\n"
9097 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
9098 "-v                also print a Path Inquiry CCB for the controller\n"
9099 "format arguments:\n"
9100 "-q                be quiet, don't print status messages\n"
9101 "-r                run in report only mode\n"
9102 "-w                don't send immediate format command\n"
9103 "-y                don't ask any questions\n"
9104 "sanitize arguments:\n"
9105 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
9106 "-c passes         overwrite passes to perform (1 to 31)\n"
9107 "-I                invert overwrite pattern after each pass\n"
9108 "-P pattern        path to overwrite pattern file\n"
9109 "-q                be quiet, don't print status messages\n"
9110 "-r                run in report only mode\n"
9111 "-U                run operation in unrestricted completion exit mode\n"
9112 "-w                don't send immediate sanitize command\n"
9113 "-y                don't ask any questions\n"
9114 "idle/standby arguments:\n"
9115 "-t <arg>          number of seconds before respective state.\n"
9116 "fwdownload arguments:\n"
9117 "-f fw_image       path to firmware image file\n"
9118 "-q                don't print informational messages, only errors\n"
9119 "-s                run in simulation mode\n"
9120 "-v                print info for every firmware segment sent to device\n"
9121 "-y                don't ask any questions\n"
9122 "security arguments:\n"
9123 "-d pwd            disable security using the given password for the selected\n"
9124 "                  user\n"
9125 "-e pwd            erase the device using the given pwd for the selected user\n"
9126 "-f                freeze the security configuration of the specified device\n"
9127 "-h pwd            enhanced erase the device using the given pwd for the\n"
9128 "                  selected user\n"
9129 "-k pwd            unlock the device using the given pwd for the selected\n"
9130 "                  user\n"
9131 "-l <high|maximum> specifies which security level to set: high or maximum\n"
9132 "-q                be quiet, do not print any status messages\n"
9133 "-s pwd            password the device (enable security) using the given\n"
9134 "                  pwd for the selected user\n"
9135 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
9136 "-U <user|master>  specifies which user to set: user or master\n"
9137 "-y                don't ask any questions\n"
9138 "hpa arguments:\n"
9139 "-f                freeze the HPA configuration of the device\n"
9140 "-l                lock the HPA configuration of the device\n"
9141 "-P                make the HPA max sectors persist\n"
9142 "-p pwd            Set the HPA configuration password required for unlock\n"
9143 "                  calls\n"
9144 "-q                be quiet, do not print any status messages\n"
9145 "-s sectors        configures the maximum user accessible sectors of the\n"
9146 "                  device\n"
9147 "-U pwd            unlock the HPA configuration of the device\n"
9148 "-y                don't ask any questions\n"
9149 "persist arguments:\n"
9150 "-i action         specify read_keys, read_reservation, report_cap, or\n"
9151 "                  read_full_status\n"
9152 "-o action         specify register, register_ignore, reserve, release,\n"
9153 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
9154 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
9155 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
9156 "-k key            specify the Reservation Key\n"
9157 "-K sa_key         specify the Service Action Reservation Key\n"
9158 "-p                set the Activate Persist Through Power Loss bit\n"
9159 "-R rtp            specify the Relative Target Port\n"
9160 "-s scope          specify the scope: lun, extent, element or a number\n"
9161 "-S                specify Transport ID for register, requires -I\n"
9162 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
9163 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
9164 "-U                unregister the current initiator for register_move\n"
9165 "attrib arguments:\n"
9166 "-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
9167 "                  supp_attr\n"
9168 "-w attr           specify an attribute to write, one -w argument per attr\n"
9169 "-a attr_num       only display this attribute number\n"
9170 "-c                get cached attributes\n"
9171 "-e elem_addr      request attributes for the given element in a changer\n"
9172 "-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
9173 "                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
9174 "                  field_none, field_desc, field_num, field_size, field_rw\n"
9175 "-p partition      request attributes for the given partition\n"
9176 "-s start_attr     request attributes starting at the given number\n"
9177 "-T elem_type      specify the element type (used with -e)\n"
9178 "-V logical_vol    specify the logical volume ID\n"
9179 "opcodes arguments:\n"
9180 "-o opcode         specify the individual opcode to list\n"
9181 "-s service_action specify the service action for the opcode\n"
9182 "-N                do not return SCSI error for unsupported SA\n"
9183 "-T                request nominal and recommended timeout values\n"
9184 "zone arguments:\n"
9185 "-c cmd            required: rz, open, close, finish, or rwp\n"
9186 "-a                apply the action to all zones\n"
9187 "-l LBA            specify the zone starting LBA\n"
9188 "-o rep_opts       report zones options: all, empty, imp_open, exp_open,\n"
9189 "                  closed, full, ro, offline, reset, nonseq, nonwp\n"
9190 "-P print_opt      report zones printing:  normal, summary, script\n"
9191 "epc arguments:\n"
9192 "-c cmd            required: restore, goto, timer, state, enable, disable,\n"
9193 "                  source, status, list\n"
9194 "-d                disable power mode (timer, state)\n"
9195 "-D                delayed entry (goto)\n"
9196 "-e                enable power mode (timer, state)\n"
9197 "-H                hold power mode (goto)\n"
9198 "-p power_cond     Idle_a, Idle_b, Idle_c, Standby_y, Standby_z (timer,\n"
9199 "                  state, goto)\n"
9200 "-P                only display power mode (status)\n"
9201 "-r rst_src        restore settings from: default, saved (restore)\n"
9202 "-s                save mode (timer, state, restore)\n"
9203 "-S power_src      set power source: battery, nonbattery (source)\n"
9204 "-T timer          set timer, seconds, .1 sec resolution (timer)\n"
9205 "timestamp arguments:\n"
9206 "-r                report the timestamp of the device\n"
9207 "-f format         report the timestamp of the device with the given\n"
9208 "                  strftime(3) format string\n"
9209 "-m                report the timestamp of the device as milliseconds since\n"
9210 "                  January 1st, 1970\n"
9211 "-U                report the time with UTC instead of the local time zone\n"
9212 "-s                set the timestamp of the device\n"
9213 "-f format         the format of the time string passed into strptime(3)\n"
9214 "-T time           the time value passed into strptime(3)\n"
9215 "-U                set the timestamp of the device to UTC time\n"
9216 );
9217 #endif /* MINIMALISTIC */
9218 }
9219
9220 int
9221 main(int argc, char **argv)
9222 {
9223         int c;
9224         char *device = NULL;
9225         int unit = 0;
9226         struct cam_device *cam_dev = NULL;
9227         int timeout = 0, retry_count = 1;
9228         camcontrol_optret optreturn;
9229         char *tstr;
9230         const char *mainopt = "C:En:Q:t:u:v";
9231         const char *subopt = NULL;
9232         char combinedopt[256];
9233         int error = 0, optstart = 2;
9234         int task_attr = MSG_SIMPLE_Q_TAG;
9235         int devopen = 1;
9236 #ifndef MINIMALISTIC
9237         path_id_t bus;
9238         target_id_t target;
9239         lun_id_t lun;
9240 #endif /* MINIMALISTIC */
9241
9242         cmdlist = CAM_CMD_NONE;
9243         arglist = CAM_ARG_NONE;
9244
9245         if (argc < 2) {
9246                 usage(0);
9247                 exit(1);
9248         }
9249
9250         /*
9251          * Get the base option.
9252          */
9253         optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
9254
9255         if (optreturn == CC_OR_AMBIGUOUS) {
9256                 warnx("ambiguous option %s", argv[1]);
9257                 usage(0);
9258                 exit(1);
9259         } else if (optreturn == CC_OR_NOT_FOUND) {
9260                 warnx("option %s not found", argv[1]);
9261                 usage(0);
9262                 exit(1);
9263         }
9264
9265         /*
9266          * Ahh, getopt(3) is a pain.
9267          *
9268          * This is a gross hack.  There really aren't many other good
9269          * options (excuse the pun) for parsing options in a situation like
9270          * this.  getopt is kinda braindead, so you end up having to run
9271          * through the options twice, and give each invocation of getopt
9272          * the option string for the other invocation.
9273          *
9274          * You would think that you could just have two groups of options.
9275          * The first group would get parsed by the first invocation of
9276          * getopt, and the second group would get parsed by the second
9277          * invocation of getopt.  It doesn't quite work out that way.  When
9278          * the first invocation of getopt finishes, it leaves optind pointing
9279          * to the argument _after_ the first argument in the second group.
9280          * So when the second invocation of getopt comes around, it doesn't
9281          * recognize the first argument it gets and then bails out.
9282          *
9283          * A nice alternative would be to have a flag for getopt that says
9284          * "just keep parsing arguments even when you encounter an unknown
9285          * argument", but there isn't one.  So there's no real clean way to
9286          * easily parse two sets of arguments without having one invocation
9287          * of getopt know about the other.
9288          *
9289          * Without this hack, the first invocation of getopt would work as
9290          * long as the generic arguments are first, but the second invocation
9291          * (in the subfunction) would fail in one of two ways.  In the case
9292          * where you don't set optreset, it would fail because optind may be
9293          * pointing to the argument after the one it should be pointing at.
9294          * In the case where you do set optreset, and reset optind, it would
9295          * fail because getopt would run into the first set of options, which
9296          * it doesn't understand.
9297          *
9298          * All of this would "sort of" work if you could somehow figure out
9299          * whether optind had been incremented one option too far.  The
9300          * mechanics of that, however, are more daunting than just giving
9301          * both invocations all of the expect options for either invocation.
9302          *
9303          * Needless to say, I wouldn't mind if someone invented a better
9304          * (non-GPL!) command line parsing interface than getopt.  I
9305          * wouldn't mind if someone added more knobs to getopt to make it
9306          * work better.  Who knows, I may talk myself into doing it someday,
9307          * if the standards weenies let me.  As it is, it just leads to
9308          * hackery like this and causes people to avoid it in some cases.
9309          *
9310          * KDM, September 8th, 1998
9311          */
9312         if (subopt != NULL)
9313                 sprintf(combinedopt, "%s%s", mainopt, subopt);
9314         else
9315                 sprintf(combinedopt, "%s", mainopt);
9316
9317         /*
9318          * For these options we do not parse optional device arguments and
9319          * we do not open a passthrough device.
9320          */
9321         if ((cmdlist == CAM_CMD_RESCAN)
9322          || (cmdlist == CAM_CMD_RESET)
9323          || (cmdlist == CAM_CMD_DEVTREE)
9324          || (cmdlist == CAM_CMD_USAGE)
9325          || (cmdlist == CAM_CMD_DEBUG))
9326                 devopen = 0;
9327
9328 #ifndef MINIMALISTIC
9329         if ((devopen == 1)
9330          && (argc > 2 && argv[2][0] != '-')) {
9331                 char name[30];
9332                 int rv;
9333
9334                 if (isdigit(argv[2][0])) {
9335                         /* device specified as bus:target[:lun] */
9336                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9337                         if (rv < 2)
9338                                 errx(1, "numeric device specification must "
9339                                      "be either bus:target, or "
9340                                      "bus:target:lun");
9341                         /* default to 0 if lun was not specified */
9342                         if ((arglist & CAM_ARG_LUN) == 0) {
9343                                 lun = 0;
9344                                 arglist |= CAM_ARG_LUN;
9345                         }
9346                         optstart++;
9347                 } else {
9348                         if (cam_get_device(argv[2], name, sizeof name, &unit)
9349                             == -1)
9350                                 errx(1, "%s", cam_errbuf);
9351                         device = strdup(name);
9352                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9353                         optstart++;
9354                 }
9355         }
9356 #endif /* MINIMALISTIC */
9357         /*
9358          * Start getopt processing at argv[2/3], since we've already
9359          * accepted argv[1..2] as the command name, and as a possible
9360          * device name.
9361          */
9362         optind = optstart;
9363
9364         /*
9365          * Now we run through the argument list looking for generic
9366          * options, and ignoring options that possibly belong to
9367          * subfunctions.
9368          */
9369         while ((c = getopt(argc, argv, combinedopt))!= -1){
9370                 switch(c) {
9371                         case 'C':
9372                                 retry_count = strtol(optarg, NULL, 0);
9373                                 if (retry_count < 0)
9374                                         errx(1, "retry count %d is < 0",
9375                                              retry_count);
9376                                 arglist |= CAM_ARG_RETRIES;
9377                                 break;
9378                         case 'E':
9379                                 arglist |= CAM_ARG_ERR_RECOVER;
9380                                 break;
9381                         case 'n':
9382                                 arglist |= CAM_ARG_DEVICE;
9383                                 tstr = optarg;
9384                                 while (isspace(*tstr) && (*tstr != '\0'))
9385                                         tstr++;
9386                                 device = (char *)strdup(tstr);
9387                                 break;
9388                         case 'Q': {
9389                                 char *endptr;
9390                                 int table_entry = 0;
9391
9392                                 tstr = optarg;
9393                                 while (isspace(*tstr) && (*tstr != '\0'))
9394                                         tstr++;
9395                                 if (isdigit(*tstr)) {
9396                                         task_attr = strtol(tstr, &endptr, 0);
9397                                         if (*endptr != '\0') {
9398                                                 errx(1, "Invalid queue option "
9399                                                     "%s", tstr);
9400                                         }
9401                                 } else {
9402                                         size_t table_size;
9403                                         scsi_nv_status status;
9404
9405                                         table_size = sizeof(task_attrs) /
9406                                                      sizeof(task_attrs[0]);
9407                                         status = scsi_get_nv(task_attrs,
9408                                             table_size, tstr, &table_entry,
9409                                             SCSI_NV_FLAG_IG_CASE);
9410                                         if (status == SCSI_NV_FOUND)
9411                                                 task_attr = task_attrs[
9412                                                     table_entry].value;
9413                                         else {
9414                                                 errx(1, "%s option %s",
9415                                                   (status == SCSI_NV_AMBIGUOUS)?
9416                                                     "ambiguous" : "invalid",
9417                                                     tstr);
9418                                         }
9419                                 }
9420                                 break;
9421                         }
9422                         case 't':
9423                                 timeout = strtol(optarg, NULL, 0);
9424                                 if (timeout < 0)
9425                                         errx(1, "invalid timeout %d", timeout);
9426                                 /* Convert the timeout from seconds to ms */
9427                                 timeout *= 1000;
9428                                 arglist |= CAM_ARG_TIMEOUT;
9429                                 break;
9430                         case 'u':
9431                                 arglist |= CAM_ARG_UNIT;
9432                                 unit = strtol(optarg, NULL, 0);
9433                                 break;
9434                         case 'v':
9435                                 arglist |= CAM_ARG_VERBOSE;
9436                                 break;
9437                         default:
9438                                 break;
9439                 }
9440         }
9441
9442 #ifndef MINIMALISTIC
9443         /*
9444          * For most commands we'll want to open the passthrough device
9445          * associated with the specified device.  In the case of the rescan
9446          * commands, we don't use a passthrough device at all, just the
9447          * transport layer device.
9448          */
9449         if (devopen == 1) {
9450                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
9451                  && (((arglist & CAM_ARG_DEVICE) == 0)
9452                   || ((arglist & CAM_ARG_UNIT) == 0))) {
9453                         errx(1, "subcommand \"%s\" requires a valid device "
9454                              "identifier", argv[1]);
9455                 }
9456
9457                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
9458                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
9459                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
9460                      == NULL)
9461                         errx(1,"%s", cam_errbuf);
9462         }
9463 #endif /* MINIMALISTIC */
9464
9465         /*
9466          * Reset optind to 2, and reset getopt, so these routines can parse
9467          * the arguments again.
9468          */
9469         optind = optstart;
9470         optreset = 1;
9471
9472         switch(cmdlist) {
9473 #ifndef MINIMALISTIC
9474                 case CAM_CMD_DEVLIST:
9475                         error = getdevlist(cam_dev);
9476                         break;
9477                 case CAM_CMD_HPA:
9478                         error = atahpa(cam_dev, retry_count, timeout,
9479                                        argc, argv, combinedopt);
9480                         break;
9481 #endif /* MINIMALISTIC */
9482                 case CAM_CMD_DEVTREE:
9483                         error = getdevtree(argc, argv, combinedopt);
9484                         break;
9485 #ifndef MINIMALISTIC
9486                 case CAM_CMD_TUR:
9487                         error = testunitready(cam_dev, task_attr, retry_count,
9488                             timeout, 0);
9489                         break;
9490                 case CAM_CMD_INQUIRY:
9491                         error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
9492                                               task_attr, retry_count, timeout);
9493                         break;
9494                 case CAM_CMD_IDENTIFY:
9495                         error = ataidentify(cam_dev, retry_count, timeout);
9496                         break;
9497                 case CAM_CMD_STARTSTOP:
9498                         error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
9499                                           arglist & CAM_ARG_EJECT, task_attr,
9500                                           retry_count, timeout);
9501                         break;
9502 #endif /* MINIMALISTIC */
9503                 case CAM_CMD_RESCAN:
9504                         error = dorescan_or_reset(argc, argv, 1);
9505                         break;
9506                 case CAM_CMD_RESET:
9507                         error = dorescan_or_reset(argc, argv, 0);
9508                         break;
9509 #ifndef MINIMALISTIC
9510                 case CAM_CMD_READ_DEFECTS:
9511                         error = readdefects(cam_dev, argc, argv, combinedopt,
9512                                             task_attr, retry_count, timeout);
9513                         break;
9514                 case CAM_CMD_MODE_PAGE:
9515                         modepage(cam_dev, argc, argv, combinedopt,
9516                                  task_attr, retry_count, timeout);
9517                         break;
9518                 case CAM_CMD_SCSI_CMD:
9519                         error = scsicmd(cam_dev, argc, argv, combinedopt,
9520                                         task_attr, retry_count, timeout);
9521                         break;
9522                 case CAM_CMD_SMP_CMD:
9523                         error = smpcmd(cam_dev, argc, argv, combinedopt,
9524                                        retry_count, timeout);
9525                         break;
9526                 case CAM_CMD_SMP_RG:
9527                         error = smpreportgeneral(cam_dev, argc, argv,
9528                                                  combinedopt, retry_count,
9529                                                  timeout);
9530                         break;
9531                 case CAM_CMD_SMP_PC:
9532                         error = smpphycontrol(cam_dev, argc, argv, combinedopt, 
9533                                               retry_count, timeout);
9534                         break;
9535                 case CAM_CMD_SMP_PHYLIST:
9536                         error = smpphylist(cam_dev, argc, argv, combinedopt,
9537                                            retry_count, timeout);
9538                         break;
9539                 case CAM_CMD_SMP_MANINFO:
9540                         error = smpmaninfo(cam_dev, argc, argv, combinedopt,
9541                                            retry_count, timeout);
9542                         break;
9543                 case CAM_CMD_DEBUG:
9544                         error = camdebug(argc, argv, combinedopt);
9545                         break;
9546                 case CAM_CMD_TAG:
9547                         error = tagcontrol(cam_dev, argc, argv, combinedopt);
9548                         break;
9549                 case CAM_CMD_RATE:
9550                         error = ratecontrol(cam_dev, task_attr, retry_count,
9551                                             timeout, argc, argv, combinedopt);
9552                         break;
9553                 case CAM_CMD_FORMAT:
9554                         error = scsiformat(cam_dev, argc, argv,
9555                                            combinedopt, task_attr, retry_count,
9556                                            timeout);
9557                         break;
9558                 case CAM_CMD_REPORTLUNS:
9559                         error = scsireportluns(cam_dev, argc, argv,
9560                                                combinedopt, task_attr,
9561                                                retry_count, timeout);
9562                         break;
9563                 case CAM_CMD_READCAP:
9564                         error = scsireadcapacity(cam_dev, argc, argv,
9565                                                  combinedopt, task_attr,
9566                                                  retry_count, timeout);
9567                         break;
9568                 case CAM_CMD_IDLE:
9569                 case CAM_CMD_STANDBY:
9570                 case CAM_CMD_SLEEP:
9571                         error = atapm(cam_dev, argc, argv,
9572                                       combinedopt, retry_count, timeout);
9573                         break;
9574                 case CAM_CMD_APM:
9575                 case CAM_CMD_AAM:
9576                         error = ataaxm(cam_dev, argc, argv,
9577                                       combinedopt, retry_count, timeout);
9578                         break;
9579                 case CAM_CMD_SECURITY:
9580                         error = atasecurity(cam_dev, retry_count, timeout,
9581                                             argc, argv, combinedopt);
9582                         break;
9583                 case CAM_CMD_DOWNLOAD_FW:
9584                         error = fwdownload(cam_dev, argc, argv, combinedopt,
9585                             arglist & CAM_ARG_VERBOSE, task_attr, retry_count,
9586                             timeout);
9587                         break;
9588                 case CAM_CMD_SANITIZE:
9589                         error = scsisanitize(cam_dev, argc, argv,
9590                                              combinedopt, task_attr,
9591                                              retry_count, timeout);
9592                         break;
9593                 case CAM_CMD_PERSIST:
9594                         error = scsipersist(cam_dev, argc, argv, combinedopt,
9595                             task_attr, retry_count, timeout,
9596                             arglist & CAM_ARG_VERBOSE,
9597                             arglist & CAM_ARG_ERR_RECOVER);
9598                         break;
9599                 case CAM_CMD_ATTRIB:
9600                         error = scsiattrib(cam_dev, argc, argv, combinedopt,
9601                             task_attr, retry_count, timeout,
9602                             arglist & CAM_ARG_VERBOSE,
9603                             arglist & CAM_ARG_ERR_RECOVER);
9604                         break;
9605                 case CAM_CMD_OPCODES:
9606                         error = scsiopcodes(cam_dev, argc, argv, combinedopt,
9607                             task_attr, retry_count, timeout,
9608                             arglist & CAM_ARG_VERBOSE);
9609                         break;
9610                 case CAM_CMD_REPROBE:
9611                         error = scsireprobe(cam_dev);
9612                         break;
9613                 case CAM_CMD_ZONE:
9614                         error = zone(cam_dev, argc, argv, combinedopt,
9615                             task_attr, retry_count, timeout,
9616                             arglist & CAM_ARG_VERBOSE);
9617                         break;
9618                 case CAM_CMD_EPC:
9619                         error = epc(cam_dev, argc, argv, combinedopt,
9620                             retry_count, timeout, arglist & CAM_ARG_VERBOSE);
9621                         break;
9622                 case CAM_CMD_TIMESTAMP:
9623                         error = timestamp(cam_dev, argc, argv, combinedopt,
9624                             task_attr, retry_count, timeout,
9625                             arglist & CAM_ARG_VERBOSE);
9626                         break;
9627 #endif /* MINIMALISTIC */
9628                 case CAM_CMD_USAGE:
9629                         usage(1);
9630                         break;
9631                 default:
9632                         usage(0);
9633                         error = 1;
9634                         break;
9635         }
9636
9637         if (cam_dev != NULL)
9638                 cam_close_device(cam_dev);
9639
9640         exit(error);
9641 }