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