]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - sbin/camcontrol/camcontrol.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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
49 #include <cam/cam.h>
50 #include <cam/cam_debug.h>
51 #include <cam/cam_ccb.h>
52 #include <cam/scsi/scsi_all.h>
53 #include <cam/scsi/scsi_da.h>
54 #include <cam/scsi/scsi_pass.h>
55 #include <cam/scsi/scsi_message.h>
56 #include <cam/scsi/smp_all.h>
57 #include <cam/ata/ata_all.h>
58 #include <camlib.h>
59 #include "camcontrol.h"
60
61 typedef enum {
62         CAM_CMD_NONE            = 0x00000000,
63         CAM_CMD_DEVLIST         = 0x00000001,
64         CAM_CMD_TUR             = 0x00000002,
65         CAM_CMD_INQUIRY         = 0x00000003,
66         CAM_CMD_STARTSTOP       = 0x00000004,
67         CAM_CMD_RESCAN          = 0x00000005,
68         CAM_CMD_READ_DEFECTS    = 0x00000006,
69         CAM_CMD_MODE_PAGE       = 0x00000007,
70         CAM_CMD_SCSI_CMD        = 0x00000008,
71         CAM_CMD_DEVTREE         = 0x00000009,
72         CAM_CMD_USAGE           = 0x0000000a,
73         CAM_CMD_DEBUG           = 0x0000000b,
74         CAM_CMD_RESET           = 0x0000000c,
75         CAM_CMD_FORMAT          = 0x0000000d,
76         CAM_CMD_TAG             = 0x0000000e,
77         CAM_CMD_RATE            = 0x0000000f,
78         CAM_CMD_DETACH          = 0x00000010,
79         CAM_CMD_REPORTLUNS      = 0x00000011,
80         CAM_CMD_READCAP         = 0x00000012,
81         CAM_CMD_IDENTIFY        = 0x00000013,
82         CAM_CMD_IDLE            = 0x00000014,
83         CAM_CMD_STANDBY         = 0x00000015,
84         CAM_CMD_SLEEP           = 0x00000016,
85         CAM_CMD_SMP_CMD         = 0x00000017,
86         CAM_CMD_SMP_RG          = 0x00000018,
87         CAM_CMD_SMP_PC          = 0x00000019,
88         CAM_CMD_SMP_PHYLIST     = 0x0000001a,
89         CAM_CMD_SMP_MANINFO     = 0x0000001b
90 } cam_cmdmask;
91
92 typedef enum {
93         CAM_ARG_NONE            = 0x00000000,
94         CAM_ARG_VERBOSE         = 0x00000001,
95         CAM_ARG_DEVICE          = 0x00000002,
96         CAM_ARG_BUS             = 0x00000004,
97         CAM_ARG_TARGET          = 0x00000008,
98         CAM_ARG_LUN             = 0x00000010,
99         CAM_ARG_EJECT           = 0x00000020,
100         CAM_ARG_UNIT            = 0x00000040,
101         CAM_ARG_FORMAT_BLOCK    = 0x00000080,
102         CAM_ARG_FORMAT_BFI      = 0x00000100,
103         CAM_ARG_FORMAT_PHYS     = 0x00000200,
104         CAM_ARG_PLIST           = 0x00000400,
105         CAM_ARG_GLIST           = 0x00000800,
106         CAM_ARG_GET_SERIAL      = 0x00001000,
107         CAM_ARG_GET_STDINQ      = 0x00002000,
108         CAM_ARG_GET_XFERRATE    = 0x00004000,
109         CAM_ARG_INQ_MASK        = 0x00007000,
110         CAM_ARG_MODE_EDIT       = 0x00008000,
111         CAM_ARG_PAGE_CNTL       = 0x00010000,
112         CAM_ARG_TIMEOUT         = 0x00020000,
113         CAM_ARG_CMD_IN          = 0x00040000,
114         CAM_ARG_CMD_OUT         = 0x00080000,
115         CAM_ARG_DBD             = 0x00100000,
116         CAM_ARG_ERR_RECOVER     = 0x00200000,
117         CAM_ARG_RETRIES         = 0x00400000,
118         CAM_ARG_START_UNIT      = 0x00800000,
119         CAM_ARG_DEBUG_INFO      = 0x01000000,
120         CAM_ARG_DEBUG_TRACE     = 0x02000000,
121         CAM_ARG_DEBUG_SUBTRACE  = 0x04000000,
122         CAM_ARG_DEBUG_CDB       = 0x08000000,
123         CAM_ARG_DEBUG_XPT       = 0x10000000,
124         CAM_ARG_DEBUG_PERIPH    = 0x20000000,
125 } cam_argmask;
126
127 struct camcontrol_opts {
128         const char      *optname;
129         uint32_t        cmdnum;
130         cam_argmask     argnum;
131         const char      *subopt;
132 };
133
134 #ifndef MINIMALISTIC
135 static const char scsicmd_opts[] = "a:c:dfi:o:r";
136 static const char readdefect_opts[] = "f:GP";
137 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
138 static const char smprg_opts[] = "l";
139 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
140 static const char smpphylist_opts[] = "lq";
141 #endif
142
143 struct camcontrol_opts option_table[] = {
144 #ifndef MINIMALISTIC
145         {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
146         {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
147         {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
148         {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
149         {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
150         {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
151         {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
152         {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
153         {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
154 #endif /* MINIMALISTIC */
155         {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
156         {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
157 #ifndef MINIMALISTIC
158         {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
159         {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
160         {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
161         {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
162         {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
163         {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
164         {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
165         {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
166         {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
167         {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
168         {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
169         {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
170 #endif /* MINIMALISTIC */
171         {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
172 #ifndef MINIMALISTIC
173         {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
174         {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
175         {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
176         {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
177         {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
178         {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
179         {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
180         {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
181         {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
182         {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
183 #endif /* MINIMALISTIC */
184         {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
185         {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
186         {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
187         {NULL, 0, 0, NULL}
188 };
189
190 typedef enum {
191         CC_OR_NOT_FOUND,
192         CC_OR_AMBIGUOUS,
193         CC_OR_FOUND
194 } camcontrol_optret;
195
196 struct cam_devitem {
197         struct device_match_result dev_match;
198         int num_periphs;
199         struct periph_match_result *periph_matches;
200         struct scsi_vpd_device_id *device_id;
201         int device_id_len;
202         STAILQ_ENTRY(cam_devitem) links;
203 };
204
205 struct cam_devlist {
206         STAILQ_HEAD(, cam_devitem) dev_queue;
207         path_id_t path_id;
208 };
209
210 cam_cmdmask cmdlist;
211 cam_argmask arglist;
212
213 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
214                             uint32_t *cmdnum, cam_argmask *argnum,
215                             const char **subopt);
216 #ifndef MINIMALISTIC
217 static int getdevlist(struct cam_device *device);
218 #endif /* MINIMALISTIC */
219 static int getdevtree(void);
220 #ifndef MINIMALISTIC
221 static int testunitready(struct cam_device *device, int retry_count,
222                          int timeout, int quiet);
223 static int scsistart(struct cam_device *device, int startstop, int loadeject,
224                      int retry_count, int timeout);
225 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
226                          char *combinedopt, int retry_count, int timeout);
227 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
228 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
229 static int camxferrate(struct cam_device *device);
230 #endif /* MINIMALISTIC */
231 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
232                      cam_argmask *arglst);
233 static int dorescan_or_reset(int argc, char **argv, int rescan);
234 static int rescan_or_reset_bus(int bus, int rescan);
235 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
236 #ifndef MINIMALISTIC
237 static int readdefects(struct cam_device *device, int argc, char **argv,
238                        char *combinedopt, int retry_count, int timeout);
239 static void modepage(struct cam_device *device, int argc, char **argv,
240                      char *combinedopt, int retry_count, int timeout);
241 static int scsicmd(struct cam_device *device, int argc, char **argv,
242                    char *combinedopt, int retry_count, int timeout);
243 static int smpcmd(struct cam_device *device, int argc, char **argv,
244                   char *combinedopt, int retry_count, int timeout);
245 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
246                             char *combinedopt, int retry_count, int timeout);
247 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
248                          char *combinedopt, int retry_count, int timeout);
249 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
250                       char *combinedopt, int retry_count, int timeout);
251 static int getdevid(struct cam_devitem *item);
252 static int buildbusdevlist(struct cam_devlist *devlist);
253 static void freebusdevlist(struct cam_devlist *devlist);
254 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
255                                          uint64_t sasaddr);
256 static int smpphylist(struct cam_device *device, int argc, char **argv,
257                       char *combinedopt, int retry_count, int timeout);
258 static int tagcontrol(struct cam_device *device, int argc, char **argv,
259                       char *combinedopt);
260 static void cts_print(struct cam_device *device,
261                       struct ccb_trans_settings *cts);
262 static void cpi_print(struct ccb_pathinq *cpi);
263 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
264 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
265 static int get_print_cts(struct cam_device *device, int user_settings,
266                          int quiet, struct ccb_trans_settings *cts);
267 static int ratecontrol(struct cam_device *device, int retry_count,
268                        int timeout, int argc, char **argv, char *combinedopt);
269 static int scsiformat(struct cam_device *device, int argc, char **argv,
270                       char *combinedopt, int retry_count, int timeout);
271 static int scsireportluns(struct cam_device *device, int argc, char **argv,
272                           char *combinedopt, int retry_count, int timeout);
273 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
274                             char *combinedopt, int retry_count, int timeout);
275 static int atapm(struct cam_device *device, int argc, char **argv,
276                             char *combinedopt, int retry_count, int timeout);
277 #endif /* MINIMALISTIC */
278 #ifndef min
279 #define min(a,b) (((a)<(b))?(a):(b))
280 #endif
281 #ifndef max
282 #define max(a,b) (((a)>(b))?(a):(b))
283 #endif
284
285 camcontrol_optret
286 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
287           cam_argmask *argnum, const char **subopt)
288 {
289         struct camcontrol_opts *opts;
290         int num_matches = 0;
291
292         for (opts = table; (opts != NULL) && (opts->optname != NULL);
293              opts++) {
294                 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
295                         *cmdnum = opts->cmdnum;
296                         *argnum = opts->argnum;
297                         *subopt = opts->subopt;
298                         if (++num_matches > 1)
299                                 return(CC_OR_AMBIGUOUS);
300                 }
301         }
302
303         if (num_matches > 0)
304                 return(CC_OR_FOUND);
305         else
306                 return(CC_OR_NOT_FOUND);
307 }
308
309 #ifndef MINIMALISTIC
310 static int
311 getdevlist(struct cam_device *device)
312 {
313         union ccb *ccb;
314         char status[32];
315         int error = 0;
316
317         ccb = cam_getccb(device);
318
319         ccb->ccb_h.func_code = XPT_GDEVLIST;
320         ccb->ccb_h.flags = CAM_DIR_NONE;
321         ccb->ccb_h.retry_count = 1;
322         ccb->cgdl.index = 0;
323         ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
324         while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
325                 if (cam_send_ccb(device, ccb) < 0) {
326                         perror("error getting device list");
327                         cam_freeccb(ccb);
328                         return(1);
329                 }
330
331                 status[0] = '\0';
332
333                 switch (ccb->cgdl.status) {
334                         case CAM_GDEVLIST_MORE_DEVS:
335                                 strcpy(status, "MORE");
336                                 break;
337                         case CAM_GDEVLIST_LAST_DEVICE:
338                                 strcpy(status, "LAST");
339                                 break;
340                         case CAM_GDEVLIST_LIST_CHANGED:
341                                 strcpy(status, "CHANGED");
342                                 break;
343                         case CAM_GDEVLIST_ERROR:
344                                 strcpy(status, "ERROR");
345                                 error = 1;
346                                 break;
347                 }
348
349                 fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
350                         ccb->cgdl.periph_name,
351                         ccb->cgdl.unit_number,
352                         ccb->cgdl.generation,
353                         ccb->cgdl.index,
354                         status);
355
356                 /*
357                  * If the list has changed, we need to start over from the
358                  * beginning.
359                  */
360                 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
361                         ccb->cgdl.index = 0;
362         }
363
364         cam_freeccb(ccb);
365
366         return(error);
367 }
368 #endif /* MINIMALISTIC */
369
370 static int
371 getdevtree(void)
372 {
373         union ccb ccb;
374         int bufsize, fd;
375         unsigned int i;
376         int need_close = 0;
377         int error = 0;
378         int skip_device = 0;
379
380         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
381                 warn("couldn't open %s", XPT_DEVICE);
382                 return(1);
383         }
384
385         bzero(&ccb, sizeof(union ccb));
386
387         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
388         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
389         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
390
391         ccb.ccb_h.func_code = XPT_DEV_MATCH;
392         bufsize = sizeof(struct dev_match_result) * 100;
393         ccb.cdm.match_buf_len = bufsize;
394         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
395         if (ccb.cdm.matches == NULL) {
396                 warnx("can't malloc memory for matches");
397                 close(fd);
398                 return(1);
399         }
400         ccb.cdm.num_matches = 0;
401
402         /*
403          * We fetch all nodes, since we display most of them in the default
404          * case, and all in the verbose case.
405          */
406         ccb.cdm.num_patterns = 0;
407         ccb.cdm.pattern_buf_len = 0;
408
409         /*
410          * We do the ioctl multiple times if necessary, in case there are
411          * more than 100 nodes in the EDT.
412          */
413         do {
414                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
415                         warn("error sending CAMIOCOMMAND ioctl");
416                         error = 1;
417                         break;
418                 }
419
420                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
421                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
422                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
423                         warnx("got CAM error %#x, CDM error %d\n",
424                               ccb.ccb_h.status, ccb.cdm.status);
425                         error = 1;
426                         break;
427                 }
428
429                 for (i = 0; i < ccb.cdm.num_matches; i++) {
430                         switch (ccb.cdm.matches[i].type) {
431                         case DEV_MATCH_BUS: {
432                                 struct bus_match_result *bus_result;
433
434                                 /*
435                                  * Only print the bus information if the
436                                  * user turns on the verbose flag.
437                                  */
438                                 if ((arglist & CAM_ARG_VERBOSE) == 0)
439                                         break;
440
441                                 bus_result =
442                                         &ccb.cdm.matches[i].result.bus_result;
443
444                                 if (need_close) {
445                                         fprintf(stdout, ")\n");
446                                         need_close = 0;
447                                 }
448
449                                 fprintf(stdout, "scbus%d on %s%d bus %d:\n",
450                                         bus_result->path_id,
451                                         bus_result->dev_name,
452                                         bus_result->unit_number,
453                                         bus_result->bus_id);
454                                 break;
455                         }
456                         case DEV_MATCH_DEVICE: {
457                                 struct device_match_result *dev_result;
458                                 char vendor[16], product[48], revision[16];
459                                 char tmpstr[256];
460
461                                 dev_result =
462                                      &ccb.cdm.matches[i].result.device_result;
463
464                                 if ((dev_result->flags
465                                      & DEV_RESULT_UNCONFIGURED)
466                                  && ((arglist & CAM_ARG_VERBOSE) == 0)) {
467                                         skip_device = 1;
468                                         break;
469                                 } else
470                                         skip_device = 0;
471
472                                 if (dev_result->protocol == PROTO_SCSI) {
473                                     cam_strvis(vendor, dev_result->inq_data.vendor,
474                                            sizeof(dev_result->inq_data.vendor),
475                                            sizeof(vendor));
476                                     cam_strvis(product,
477                                            dev_result->inq_data.product,
478                                            sizeof(dev_result->inq_data.product),
479                                            sizeof(product));
480                                     cam_strvis(revision,
481                                            dev_result->inq_data.revision,
482                                           sizeof(dev_result->inq_data.revision),
483                                            sizeof(revision));
484                                     sprintf(tmpstr, "<%s %s %s>", vendor, product,
485                                         revision);
486                                 } else if (dev_result->protocol == PROTO_ATA ||
487                                     dev_result->protocol == PROTO_SATAPM) {
488                                     cam_strvis(product,
489                                            dev_result->ident_data.model,
490                                            sizeof(dev_result->ident_data.model),
491                                            sizeof(product));
492                                     cam_strvis(revision,
493                                            dev_result->ident_data.revision,
494                                           sizeof(dev_result->ident_data.revision),
495                                            sizeof(revision));
496                                     sprintf(tmpstr, "<%s %s>", product,
497                                         revision);
498                                 } else {
499                                     sprintf(tmpstr, "<>");
500                                 }
501                                 if (need_close) {
502                                         fprintf(stdout, ")\n");
503                                         need_close = 0;
504                                 }
505
506                                 fprintf(stdout, "%-33s  at scbus%d "
507                                         "target %d lun %d (",
508                                         tmpstr,
509                                         dev_result->path_id,
510                                         dev_result->target_id,
511                                         dev_result->target_lun);
512
513                                 need_close = 1;
514
515                                 break;
516                         }
517                         case DEV_MATCH_PERIPH: {
518                                 struct periph_match_result *periph_result;
519
520                                 periph_result =
521                                       &ccb.cdm.matches[i].result.periph_result;
522
523                                 if (skip_device != 0)
524                                         break;
525
526                                 if (need_close > 1)
527                                         fprintf(stdout, ",");
528
529                                 fprintf(stdout, "%s%d",
530                                         periph_result->periph_name,
531                                         periph_result->unit_number);
532
533                                 need_close++;
534                                 break;
535                         }
536                         default:
537                                 fprintf(stdout, "unknown match type\n");
538                                 break;
539                         }
540                 }
541
542         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
543                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
544
545         if (need_close)
546                 fprintf(stdout, ")\n");
547
548         close(fd);
549
550         return(error);
551 }
552
553 #ifndef MINIMALISTIC
554 static int
555 testunitready(struct cam_device *device, int retry_count, int timeout,
556               int quiet)
557 {
558         int error = 0;
559         union ccb *ccb;
560
561         ccb = cam_getccb(device);
562
563         scsi_test_unit_ready(&ccb->csio,
564                              /* retries */ retry_count,
565                              /* cbfcnp */ NULL,
566                              /* tag_action */ MSG_SIMPLE_Q_TAG,
567                              /* sense_len */ SSD_FULL_SIZE,
568                              /* timeout */ timeout ? timeout : 5000);
569
570         /* Disable freezing the device queue */
571         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
572
573         if (arglist & CAM_ARG_ERR_RECOVER)
574                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
575
576         if (cam_send_ccb(device, ccb) < 0) {
577                 if (quiet == 0)
578                         perror("error sending test unit ready");
579
580                 if (arglist & CAM_ARG_VERBOSE) {
581                         cam_error_print(device, ccb, CAM_ESF_ALL,
582                                         CAM_EPF_ALL, stderr);
583                 }
584
585                 cam_freeccb(ccb);
586                 return(1);
587         }
588
589         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
590                 if (quiet == 0)
591                         fprintf(stdout, "Unit is ready\n");
592         } else {
593                 if (quiet == 0)
594                         fprintf(stdout, "Unit is not ready\n");
595                 error = 1;
596
597                 if (arglist & CAM_ARG_VERBOSE) {
598                         cam_error_print(device, ccb, CAM_ESF_ALL,
599                                         CAM_EPF_ALL, stderr);
600                 }
601         }
602
603         cam_freeccb(ccb);
604
605         return(error);
606 }
607
608 static int
609 scsistart(struct cam_device *device, int startstop, int loadeject,
610           int retry_count, int timeout)
611 {
612         union ccb *ccb;
613         int error = 0;
614
615         ccb = cam_getccb(device);
616
617         /*
618          * If we're stopping, send an ordered tag so the drive in question
619          * will finish any previously queued writes before stopping.  If
620          * the device isn't capable of tagged queueing, or if tagged
621          * queueing is turned off, the tag action is a no-op.
622          */
623         scsi_start_stop(&ccb->csio,
624                         /* retries */ retry_count,
625                         /* cbfcnp */ NULL,
626                         /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
627                                                      MSG_ORDERED_Q_TAG,
628                         /* start/stop */ startstop,
629                         /* load_eject */ loadeject,
630                         /* immediate */ 0,
631                         /* sense_len */ SSD_FULL_SIZE,
632                         /* timeout */ timeout ? timeout : 120000);
633
634         /* Disable freezing the device queue */
635         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
636
637         if (arglist & CAM_ARG_ERR_RECOVER)
638                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
639
640         if (cam_send_ccb(device, ccb) < 0) {
641                 perror("error sending start unit");
642
643                 if (arglist & CAM_ARG_VERBOSE) {
644                         cam_error_print(device, ccb, CAM_ESF_ALL,
645                                         CAM_EPF_ALL, stderr);
646                 }
647
648                 cam_freeccb(ccb);
649                 return(1);
650         }
651
652         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
653                 if (startstop) {
654                         fprintf(stdout, "Unit started successfully");
655                         if (loadeject)
656                                 fprintf(stdout,", Media loaded\n");
657                         else
658                                 fprintf(stdout,"\n");
659                 } else {
660                         fprintf(stdout, "Unit stopped successfully");
661                         if (loadeject)
662                                 fprintf(stdout, ", Media ejected\n");
663                         else
664                                 fprintf(stdout, "\n");
665                 }
666         else {
667                 error = 1;
668                 if (startstop)
669                         fprintf(stdout,
670                                 "Error received from start unit command\n");
671                 else
672                         fprintf(stdout,
673                                 "Error received from stop unit command\n");
674
675                 if (arglist & CAM_ARG_VERBOSE) {
676                         cam_error_print(device, ccb, CAM_ESF_ALL,
677                                         CAM_EPF_ALL, stderr);
678                 }
679         }
680
681         cam_freeccb(ccb);
682
683         return(error);
684 }
685
686 static int
687 scsidoinquiry(struct cam_device *device, int argc, char **argv,
688               char *combinedopt, int retry_count, int timeout)
689 {
690         int c;
691         int error = 0;
692
693         while ((c = getopt(argc, argv, combinedopt)) != -1) {
694                 switch(c) {
695                 case 'D':
696                         arglist |= CAM_ARG_GET_STDINQ;
697                         break;
698                 case 'R':
699                         arglist |= CAM_ARG_GET_XFERRATE;
700                         break;
701                 case 'S':
702                         arglist |= CAM_ARG_GET_SERIAL;
703                         break;
704                 default:
705                         break;
706                 }
707         }
708
709         /*
710          * If the user didn't specify any inquiry options, he wants all of
711          * them.
712          */
713         if ((arglist & CAM_ARG_INQ_MASK) == 0)
714                 arglist |= CAM_ARG_INQ_MASK;
715
716         if (arglist & CAM_ARG_GET_STDINQ)
717                 error = scsiinquiry(device, retry_count, timeout);
718
719         if (error != 0)
720                 return(error);
721
722         if (arglist & CAM_ARG_GET_SERIAL)
723                 scsiserial(device, retry_count, timeout);
724
725         if (error != 0)
726                 return(error);
727
728         if (arglist & CAM_ARG_GET_XFERRATE)
729                 error = camxferrate(device);
730
731         return(error);
732 }
733
734 static int
735 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
736 {
737         union ccb *ccb;
738         struct scsi_inquiry_data *inq_buf;
739         int error = 0;
740
741         ccb = cam_getccb(device);
742
743         if (ccb == NULL) {
744                 warnx("couldn't allocate CCB");
745                 return(1);
746         }
747
748         /* cam_getccb cleans up the header, caller has to zero the payload */
749         bzero(&(&ccb->ccb_h)[1],
750               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
751
752         inq_buf = (struct scsi_inquiry_data *)malloc(
753                 sizeof(struct scsi_inquiry_data));
754
755         if (inq_buf == NULL) {
756                 cam_freeccb(ccb);
757                 warnx("can't malloc memory for inquiry\n");
758                 return(1);
759         }
760         bzero(inq_buf, sizeof(*inq_buf));
761
762         /*
763          * Note that although the size of the inquiry buffer is the full
764          * 256 bytes specified in the SCSI spec, we only tell the device
765          * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
766          * two reasons for this:
767          *
768          *  - The SCSI spec says that when a length field is only 1 byte,
769          *    a value of 0 will be interpreted as 256.  Therefore
770          *    scsi_inquiry() will convert an inq_len (which is passed in as
771          *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
772          *    to 0.  Evidently, very few devices meet the spec in that
773          *    regard.  Some devices, like many Seagate disks, take the 0 as
774          *    0, and don't return any data.  One Pioneer DVD-R drive
775          *    returns more data than the command asked for.
776          *
777          *    So, since there are numerous devices that just don't work
778          *    right with the full inquiry size, we don't send the full size.
779          *
780          *  - The second reason not to use the full inquiry data length is
781          *    that we don't need it here.  The only reason we issue a
782          *    standard inquiry is to get the vendor name, device name,
783          *    and revision so scsi_print_inquiry() can print them.
784          *
785          * If, at some point in the future, more inquiry data is needed for
786          * some reason, this code should use a procedure similar to the
787          * probe code.  i.e., issue a short inquiry, and determine from
788          * the additional length passed back from the device how much
789          * inquiry data the device supports.  Once the amount the device
790          * supports is determined, issue an inquiry for that amount and no
791          * more.
792          *
793          * KDM, 2/18/2000
794          */
795         scsi_inquiry(&ccb->csio,
796                      /* retries */ retry_count,
797                      /* cbfcnp */ NULL,
798                      /* tag_action */ MSG_SIMPLE_Q_TAG,
799                      /* inq_buf */ (u_int8_t *)inq_buf,
800                      /* inq_len */ SHORT_INQUIRY_LENGTH,
801                      /* evpd */ 0,
802                      /* page_code */ 0,
803                      /* sense_len */ SSD_FULL_SIZE,
804                      /* timeout */ timeout ? timeout : 5000);
805
806         /* Disable freezing the device queue */
807         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
808
809         if (arglist & CAM_ARG_ERR_RECOVER)
810                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
811
812         if (cam_send_ccb(device, ccb) < 0) {
813                 perror("error sending SCSI inquiry");
814
815                 if (arglist & CAM_ARG_VERBOSE) {
816                         cam_error_print(device, ccb, CAM_ESF_ALL,
817                                         CAM_EPF_ALL, stderr);
818                 }
819
820                 cam_freeccb(ccb);
821                 return(1);
822         }
823
824         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
825                 error = 1;
826
827                 if (arglist & CAM_ARG_VERBOSE) {
828                         cam_error_print(device, ccb, CAM_ESF_ALL,
829                                         CAM_EPF_ALL, stderr);
830                 }
831         }
832
833         cam_freeccb(ccb);
834
835         if (error != 0) {
836                 free(inq_buf);
837                 return(error);
838         }
839
840         fprintf(stdout, "%s%d: ", device->device_name,
841                 device->dev_unit_num);
842         scsi_print_inquiry(inq_buf);
843
844         free(inq_buf);
845
846         return(0);
847 }
848
849 static int
850 scsiserial(struct cam_device *device, int retry_count, int timeout)
851 {
852         union ccb *ccb;
853         struct scsi_vpd_unit_serial_number *serial_buf;
854         char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
855         int error = 0;
856
857         ccb = cam_getccb(device);
858
859         if (ccb == NULL) {
860                 warnx("couldn't allocate CCB");
861                 return(1);
862         }
863
864         /* cam_getccb cleans up the header, caller has to zero the payload */
865         bzero(&(&ccb->ccb_h)[1],
866               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
867
868         serial_buf = (struct scsi_vpd_unit_serial_number *)
869                 malloc(sizeof(*serial_buf));
870
871         if (serial_buf == NULL) {
872                 cam_freeccb(ccb);
873                 warnx("can't malloc memory for serial number");
874                 return(1);
875         }
876
877         scsi_inquiry(&ccb->csio,
878                      /*retries*/ retry_count,
879                      /*cbfcnp*/ NULL,
880                      /* tag_action */ MSG_SIMPLE_Q_TAG,
881                      /* inq_buf */ (u_int8_t *)serial_buf,
882                      /* inq_len */ sizeof(*serial_buf),
883                      /* evpd */ 1,
884                      /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
885                      /* sense_len */ SSD_FULL_SIZE,
886                      /* timeout */ timeout ? timeout : 5000);
887
888         /* Disable freezing the device queue */
889         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
890
891         if (arglist & CAM_ARG_ERR_RECOVER)
892                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
893
894         if (cam_send_ccb(device, ccb) < 0) {
895                 warn("error getting serial number");
896
897                 if (arglist & CAM_ARG_VERBOSE) {
898                         cam_error_print(device, ccb, CAM_ESF_ALL,
899                                         CAM_EPF_ALL, stderr);
900                 }
901
902                 cam_freeccb(ccb);
903                 free(serial_buf);
904                 return(1);
905         }
906
907         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
908                 error = 1;
909
910                 if (arglist & CAM_ARG_VERBOSE) {
911                         cam_error_print(device, ccb, CAM_ESF_ALL,
912                                         CAM_EPF_ALL, stderr);
913                 }
914         }
915
916         cam_freeccb(ccb);
917
918         if (error != 0) {
919                 free(serial_buf);
920                 return(error);
921         }
922
923         bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
924         serial_num[serial_buf->length] = '\0';
925
926         if ((arglist & CAM_ARG_GET_STDINQ)
927          || (arglist & CAM_ARG_GET_XFERRATE))
928                 fprintf(stdout, "%s%d: Serial Number ",
929                         device->device_name, device->dev_unit_num);
930
931         fprintf(stdout, "%.60s\n", serial_num);
932
933         free(serial_buf);
934
935         return(0);
936 }
937
938 static int
939 camxferrate(struct cam_device *device)
940 {
941         struct ccb_pathinq cpi;
942         u_int32_t freq = 0;
943         u_int32_t speed = 0;
944         union ccb *ccb;
945         u_int mb;
946         int retval = 0;
947
948         if ((retval = get_cpi(device, &cpi)) != 0)
949                 return (1);
950
951         ccb = cam_getccb(device);
952
953         if (ccb == NULL) {
954                 warnx("couldn't allocate CCB");
955                 return(1);
956         }
957
958         bzero(&(&ccb->ccb_h)[1],
959               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
960
961         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
962         ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
963
964         if (((retval = cam_send_ccb(device, ccb)) < 0)
965          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
966                 const char error_string[] = "error getting transfer settings";
967
968                 if (retval < 0)
969                         warn(error_string);
970                 else
971                         warnx(error_string);
972
973                 if (arglist & CAM_ARG_VERBOSE)
974                         cam_error_print(device, ccb, CAM_ESF_ALL,
975                                         CAM_EPF_ALL, stderr);
976
977                 retval = 1;
978
979                 goto xferrate_bailout;
980
981         }
982
983         speed = cpi.base_transfer_speed;
984         freq = 0;
985         if (ccb->cts.transport == XPORT_SPI) {
986                 struct ccb_trans_settings_spi *spi =
987                     &ccb->cts.xport_specific.spi;
988
989                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
990                         freq = scsi_calc_syncsrate(spi->sync_period);
991                         speed = freq;
992                 }
993                 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
994                         speed *= (0x01 << spi->bus_width);
995                 }
996         } else if (ccb->cts.transport == XPORT_FC) {
997                 struct ccb_trans_settings_fc *fc =
998                     &ccb->cts.xport_specific.fc;
999
1000                 if (fc->valid & CTS_FC_VALID_SPEED)
1001                         speed = fc->bitrate;
1002         } else if (ccb->cts.transport == XPORT_SAS) {
1003                 struct ccb_trans_settings_sas *sas =
1004                     &ccb->cts.xport_specific.sas;
1005
1006                 if (sas->valid & CTS_SAS_VALID_SPEED)
1007                         speed = sas->bitrate;
1008         } else if (ccb->cts.transport == XPORT_ATA) {
1009                 struct ccb_trans_settings_ata *ata =
1010                     &ccb->cts.xport_specific.ata;
1011
1012                 if (ata->valid & CTS_ATA_VALID_MODE)
1013                         speed = ata_mode2speed(ata->mode);
1014         } else if (ccb->cts.transport == XPORT_SATA) {
1015                 struct  ccb_trans_settings_sata *sata =
1016                     &ccb->cts.xport_specific.sata;
1017
1018                 if (sata->valid & CTS_SATA_VALID_REVISION)
1019                         speed = ata_revision2speed(sata->revision);
1020         }
1021
1022         mb = speed / 1000;
1023         if (mb > 0) {
1024                 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1025                         device->device_name, device->dev_unit_num,
1026                         mb, speed % 1000);
1027         } else {
1028                 fprintf(stdout, "%s%d: %dKB/s transfers",
1029                         device->device_name, device->dev_unit_num,
1030                         speed);
1031         }
1032
1033         if (ccb->cts.transport == XPORT_SPI) {
1034                 struct ccb_trans_settings_spi *spi =
1035                     &ccb->cts.xport_specific.spi;
1036
1037                 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1038                  && (spi->sync_offset != 0))
1039                         fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1040                                 freq % 1000, spi->sync_offset);
1041
1042                 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1043                  && (spi->bus_width > 0)) {
1044                         if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1045                          && (spi->sync_offset != 0)) {
1046                                 fprintf(stdout, ", ");
1047                         } else {
1048                                 fprintf(stdout, " (");
1049                         }
1050                         fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1051                 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1052                  && (spi->sync_offset != 0)) {
1053                         fprintf(stdout, ")");
1054                 }
1055         } else if (ccb->cts.transport == XPORT_ATA) {
1056                 struct ccb_trans_settings_ata *ata =
1057                     &ccb->cts.xport_specific.ata;
1058
1059                 printf(" (");
1060                 if (ata->valid & CTS_ATA_VALID_MODE)
1061                         printf("%s, ", ata_mode2string(ata->mode));
1062                 if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0)
1063                         printf("ATAPI %dbytes, ", ata->atapi);
1064                 if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
1065                         printf("PIO %dbytes", ata->bytecount);
1066                 printf(")");
1067         } else if (ccb->cts.transport == XPORT_SATA) {
1068                 struct ccb_trans_settings_sata *sata =
1069                     &ccb->cts.xport_specific.sata;
1070
1071                 printf(" (");
1072                 if (sata->valid & CTS_SATA_VALID_REVISION)
1073                         printf("SATA %d.x, ", sata->revision);
1074                 else
1075                         printf("SATA, ");
1076                 if (sata->valid & CTS_SATA_VALID_MODE)
1077                         printf("%s, ", ata_mode2string(sata->mode));
1078                 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1079                         printf("ATAPI %dbytes, ", sata->atapi);
1080                 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1081                         printf("PIO %dbytes", sata->bytecount);
1082                 printf(")");
1083         }
1084
1085         if (ccb->cts.protocol == PROTO_SCSI) {
1086                 struct ccb_trans_settings_scsi *scsi =
1087                     &ccb->cts.proto_specific.scsi;
1088                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1089                         if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1090                                 fprintf(stdout, ", Command Queueing Enabled");
1091                         }
1092                 }
1093         }
1094
1095         fprintf(stdout, "\n");
1096
1097 xferrate_bailout:
1098
1099         cam_freeccb(ccb);
1100
1101         return(retval);
1102 }
1103
1104 static void
1105 atacapprint(struct ata_params *parm)
1106 {
1107         u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1108                                 ((u_int32_t)parm->lba_size_2 << 16);
1109
1110         u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1111                                 ((u_int64_t)parm->lba_size48_2 << 16) |
1112                                 ((u_int64_t)parm->lba_size48_3 << 32) |
1113                                 ((u_int64_t)parm->lba_size48_4 << 48);
1114
1115         printf("\n");
1116         printf("protocol              ");
1117         printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1118         if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1119                 if (parm->satacapabilities & ATA_SATA_GEN3)
1120                         printf(" SATA 3.x\n");
1121                 else if (parm->satacapabilities & ATA_SATA_GEN2)
1122                         printf(" SATA 2.x\n");
1123                 else if (parm->satacapabilities & ATA_SATA_GEN1)
1124                         printf(" SATA 1.x\n");
1125                 else
1126                         printf(" SATA\n");
1127         }
1128         else
1129                 printf("\n");
1130         printf("device model          %.40s\n", parm->model);
1131         printf("firmware revision     %.8s\n", parm->revision);
1132         printf("serial number         %.20s\n", parm->serial);
1133         if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1134                 printf("WWN                   %04x%04x%04x%04x\n",
1135                     parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1136         }
1137         if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1138                 printf("media serial number   %.30s\n",
1139                     parm->media_serial);
1140         }
1141
1142         printf("cylinders             %d\n", parm->cylinders);
1143         printf("heads                 %d\n", parm->heads);
1144         printf("sectors/track         %d\n", parm->sectors);
1145         printf("sector size           logical %u, physical %lu, offset %lu\n",
1146             ata_logical_sector_size(parm),
1147             (unsigned long)ata_physical_sector_size(parm),
1148             (unsigned long)ata_logical_sector_offset(parm));
1149
1150         if (parm->config == ATA_PROTO_CFA ||
1151             (parm->support.command2 & ATA_SUPPORT_CFA))
1152                 printf("CFA supported\n");
1153
1154         printf("LBA%ssupported         ",
1155                 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1156         if (lbasize)
1157                 printf("%d sectors\n", lbasize);
1158         else
1159                 printf("\n");
1160
1161         printf("LBA48%ssupported       ",
1162                 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1163         if (lbasize48)
1164                 printf("%ju sectors\n", (uintmax_t)lbasize48);
1165         else
1166                 printf("\n");
1167
1168         printf("PIO supported         PIO");
1169         switch (ata_max_pmode(parm)) {
1170         case ATA_PIO4:
1171                 printf("4");
1172                 break;
1173         case ATA_PIO3:
1174                 printf("3");
1175                 break;
1176         case ATA_PIO2:
1177                 printf("2");
1178                 break;
1179         case ATA_PIO1:
1180                 printf("1");
1181                 break;
1182         default:
1183                 printf("0");
1184         }
1185         if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1186                 printf(" w/o IORDY");
1187         printf("\n");
1188
1189         printf("DMA%ssupported         ",
1190                 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1191         if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1192                 if (parm->mwdmamodes & 0xff) {
1193                         printf("WDMA");
1194                         if (parm->mwdmamodes & 0x04)
1195                                 printf("2");
1196                         else if (parm->mwdmamodes & 0x02)
1197                                 printf("1");
1198                         else if (parm->mwdmamodes & 0x01)
1199                                 printf("0");
1200                         printf(" ");
1201                 }
1202                 if ((parm->atavalid & ATA_FLAG_88) &&
1203                     (parm->udmamodes & 0xff)) {
1204                         printf("UDMA");
1205                         if (parm->udmamodes & 0x40)
1206                                 printf("6");
1207                         else if (parm->udmamodes & 0x20)
1208                                 printf("5");
1209                         else if (parm->udmamodes & 0x10)
1210                                 printf("4");
1211                         else if (parm->udmamodes & 0x08)
1212                                 printf("3");
1213                         else if (parm->udmamodes & 0x04)
1214                                 printf("2");
1215                         else if (parm->udmamodes & 0x02)
1216                                 printf("1");
1217                         else if (parm->udmamodes & 0x01)
1218                                 printf("0");
1219                         printf(" ");
1220                 }
1221         }
1222         printf("\n");
1223
1224         if (parm->media_rotation_rate == 1) {
1225                 printf("media RPM             non-rotating\n");
1226         } else if (parm->media_rotation_rate >= 0x0401 &&
1227             parm->media_rotation_rate <= 0xFFFE) {
1228                 printf("media RPM             %d\n",
1229                         parm->media_rotation_rate);
1230         }
1231
1232         printf("\nFeature                      "
1233                 "Support  Enabled   Value           Vendor\n");
1234         printf("read ahead                     %s       %s\n",
1235                 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1236                 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1237         printf("write cache                    %s       %s\n",
1238                 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1239                 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1240         printf("flush cache                    %s       %s\n",
1241                 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1242                 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1243         printf("overlap                        %s\n",
1244                 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1245         printf("Tagged Command Queuing (TCQ)   %s       %s",
1246                 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1247                 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1248                 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1249                         printf("        %d tags\n",
1250                             ATA_QUEUE_LEN(parm->queue) + 1);
1251                 } else
1252                         printf("\n");
1253         printf("Native Command Queuing (NCQ)   ");
1254         if (parm->satacapabilities != 0xffff &&
1255             (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1256                 printf("yes             %d tags\n",
1257                     ATA_QUEUE_LEN(parm->queue) + 1);
1258         } else
1259                 printf("no\n");
1260         printf("SMART                          %s       %s\n",
1261                 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1262                 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1263         printf("microcode download             %s       %s\n",
1264                 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1265                 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1266         printf("security                       %s       %s\n",
1267                 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1268                 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1269         printf("power management               %s       %s\n",
1270                 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1271                 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1272         printf("advanced power management      %s       %s",
1273                 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1274                 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1275                 if (parm->support.command2 & ATA_SUPPORT_APM) {
1276                         printf("        %d/0x%02X\n",
1277                             parm->apm_value, parm->apm_value);
1278                 } else
1279                         printf("\n");
1280         printf("automatic acoustic management  %s       %s",
1281                 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1282                 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1283                 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1284                         printf("        %d/0x%02X       %d/0x%02X\n",
1285                             ATA_ACOUSTIC_CURRENT(parm->acoustic),
1286                             ATA_ACOUSTIC_CURRENT(parm->acoustic),
1287                             ATA_ACOUSTIC_VENDOR(parm->acoustic),
1288                             ATA_ACOUSTIC_VENDOR(parm->acoustic));
1289                 } else
1290                         printf("\n");
1291         printf("media status notification      %s       %s\n",
1292                 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1293                 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1294         printf("power-up in Standby            %s       %s\n",
1295                 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1296                 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1297         printf("write-read-verify              %s       %s",
1298                 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1299                 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1300                 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1301                         printf("        %d/0x%x\n",
1302                             parm->wrv_mode, parm->wrv_mode);
1303                 } else
1304                         printf("\n");
1305         printf("unload                         %s       %s\n",
1306                 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1307                 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1308         printf("free-fall                      %s       %s\n",
1309                 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1310                 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1311         printf("data set management (TRIM)     %s\n",
1312                 parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1313 }
1314
1315 static int
1316 ataidentify(struct cam_device *device, int retry_count, int timeout)
1317 {
1318         union ccb *ccb;
1319         struct ata_params *ident_buf;
1320         struct ccb_getdev cgd;
1321         u_int i, error = 0;
1322         int16_t *ptr;
1323
1324         if (get_cgd(device, &cgd) != 0) {
1325                 warnx("couldn't get CGD");
1326                 return(1);
1327         }
1328         ccb = cam_getccb(device);
1329
1330         if (ccb == NULL) {
1331                 warnx("couldn't allocate CCB");
1332                 return(1);
1333         }
1334
1335         /* cam_getccb cleans up the header, caller has to zero the payload */
1336         bzero(&(&ccb->ccb_h)[1],
1337               sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1338
1339         ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1340
1341         if (ptr == NULL) {
1342                 cam_freeccb(ccb);
1343                 warnx("can't malloc memory for identify\n");
1344                 return(1);
1345         }
1346         bzero(ptr, sizeof(struct ata_params));
1347
1348         cam_fill_ataio(&ccb->ataio,
1349                       retry_count,
1350                       NULL,
1351                       /*flags*/CAM_DIR_IN,
1352                       MSG_SIMPLE_Q_TAG,
1353                       /*data_ptr*/(u_int8_t *)ptr,
1354                       /*dxfer_len*/sizeof(struct ata_params),
1355                       timeout ? timeout : 30 * 1000);
1356         if (cgd.protocol == PROTO_ATA)
1357                 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1358         else
1359                 ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1360
1361         /* Disable freezing the device queue */
1362         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1363
1364         if (arglist & CAM_ARG_ERR_RECOVER)
1365                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1366
1367         if (cam_send_ccb(device, ccb) < 0) {
1368                 perror("error sending ATA identify");
1369
1370                 if (arglist & CAM_ARG_VERBOSE) {
1371                         cam_error_print(device, ccb, CAM_ESF_ALL,
1372                                         CAM_EPF_ALL, stderr);
1373                 }
1374
1375                 free(ptr);
1376                 cam_freeccb(ccb);
1377                 return(1);
1378         }
1379
1380         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1381                 error = 1;
1382
1383                 if (arglist & CAM_ARG_VERBOSE) {
1384                         cam_error_print(device, ccb, CAM_ESF_ALL,
1385                                         CAM_EPF_ALL, stderr);
1386                 }
1387         }
1388
1389         cam_freeccb(ccb);
1390
1391         if (error != 0) {
1392                 free(ptr);
1393                 return(error);
1394         }
1395
1396         for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1397                 ptr[i] = le16toh(ptr[i]);
1398         if (arglist & CAM_ARG_VERBOSE) {
1399                 fprintf(stdout, "%s%d: Raw identify data:\n",
1400                     device->device_name, device->dev_unit_num);
1401                 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1402                         if ((i % 8) == 0)
1403                             fprintf(stdout, " %3d: ", i);
1404                         fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1405                         if ((i % 8) == 7)
1406                             fprintf(stdout, "\n");
1407                 }
1408         }
1409         ident_buf = (struct ata_params *)ptr;
1410         if (strncmp(ident_buf->model, "FX", 2) &&
1411             strncmp(ident_buf->model, "NEC", 3) &&
1412             strncmp(ident_buf->model, "Pioneer", 7) &&
1413             strncmp(ident_buf->model, "SHARP", 5)) {
1414                 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1415                 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1416                 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1417                 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1418         }
1419         ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1420         ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1421         ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1422         ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1423         ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1424         ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1425         ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1426         ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1427             sizeof(ident_buf->media_serial));
1428
1429         fprintf(stdout, "%s%d: ", device->device_name,
1430                 device->dev_unit_num);
1431         ata_print_ident(ident_buf);
1432         camxferrate(device);
1433         atacapprint(ident_buf);
1434
1435         free(ident_buf);
1436
1437         return(0);
1438 }
1439 #endif /* MINIMALISTIC */
1440
1441 /*
1442  * Parse out a bus, or a bus, target and lun in the following
1443  * format:
1444  * bus
1445  * bus:target
1446  * bus:target:lun
1447  *
1448  * Returns the number of parsed components, or 0.
1449  */
1450 static int
1451 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1452 {
1453         char *tmpstr;
1454         int convs = 0;
1455
1456         while (isspace(*tstr) && (*tstr != '\0'))
1457                 tstr++;
1458
1459         tmpstr = (char *)strtok(tstr, ":");
1460         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1461                 *bus = strtol(tmpstr, NULL, 0);
1462                 *arglst |= CAM_ARG_BUS;
1463                 convs++;
1464                 tmpstr = (char *)strtok(NULL, ":");
1465                 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1466                         *target = strtol(tmpstr, NULL, 0);
1467                         *arglst |= CAM_ARG_TARGET;
1468                         convs++;
1469                         tmpstr = (char *)strtok(NULL, ":");
1470                         if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1471                                 *lun = strtol(tmpstr, NULL, 0);
1472                                 *arglst |= CAM_ARG_LUN;
1473                                 convs++;
1474                         }
1475                 }
1476         }
1477
1478         return convs;
1479 }
1480
1481 static int
1482 dorescan_or_reset(int argc, char **argv, int rescan)
1483 {
1484         static const char must[] =
1485                 "you must specify \"all\", a bus, or a bus:target:lun to %s";
1486         int rv, error = 0;
1487         int bus = -1, target = -1, lun = -1;
1488         char *tstr;
1489
1490         if (argc < 3) {
1491                 warnx(must, rescan? "rescan" : "reset");
1492                 return(1);
1493         }
1494
1495         tstr = argv[optind];
1496         while (isspace(*tstr) && (*tstr != '\0'))
1497                 tstr++;
1498         if (strncasecmp(tstr, "all", strlen("all")) == 0)
1499                 arglist |= CAM_ARG_BUS;
1500         else {
1501                 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1502                 if (rv != 1 && rv != 3) {
1503                         warnx(must, rescan? "rescan" : "reset");
1504                         return(1);
1505                 }
1506         }
1507
1508         if ((arglist & CAM_ARG_BUS)
1509             && (arglist & CAM_ARG_TARGET)
1510             && (arglist & CAM_ARG_LUN))
1511                 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1512         else
1513                 error = rescan_or_reset_bus(bus, rescan);
1514
1515         return(error);
1516 }
1517
1518 static int
1519 rescan_or_reset_bus(int bus, int rescan)
1520 {
1521         union ccb ccb, matchccb;
1522         int fd, retval;
1523         int bufsize;
1524
1525         retval = 0;
1526
1527         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1528                 warnx("error opening transport layer device %s", XPT_DEVICE);
1529                 warn("%s", XPT_DEVICE);
1530                 return(1);
1531         }
1532
1533         if (bus != -1) {
1534                 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1535                 ccb.ccb_h.path_id = bus;
1536                 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1537                 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1538                 ccb.crcn.flags = CAM_FLAG_NONE;
1539
1540                 /* run this at a low priority */
1541                 ccb.ccb_h.pinfo.priority = 5;
1542
1543                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1544                         warn("CAMIOCOMMAND ioctl failed");
1545                         close(fd);
1546                         return(1);
1547                 }
1548
1549                 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1550                         fprintf(stdout, "%s of bus %d was successful\n",
1551                             rescan ? "Re-scan" : "Reset", bus);
1552                 } else {
1553                         fprintf(stdout, "%s of bus %d returned error %#x\n",
1554                                 rescan ? "Re-scan" : "Reset", bus,
1555                                 ccb.ccb_h.status & CAM_STATUS_MASK);
1556                         retval = 1;
1557                 }
1558
1559                 close(fd);
1560                 return(retval);
1561
1562         }
1563
1564
1565         /*
1566          * The right way to handle this is to modify the xpt so that it can
1567          * handle a wildcarded bus in a rescan or reset CCB.  At the moment
1568          * that isn't implemented, so instead we enumerate the busses and
1569          * send the rescan or reset to those busses in the case where the
1570          * given bus is -1 (wildcard).  We don't send a rescan or reset
1571          * to the xpt bus; sending a rescan to the xpt bus is effectively a
1572          * no-op, sending a rescan to the xpt bus would result in a status of
1573          * CAM_REQ_INVALID.
1574          */
1575         bzero(&(&matchccb.ccb_h)[1],
1576               sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1577         matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1578         matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
1579         bufsize = sizeof(struct dev_match_result) * 20;
1580         matchccb.cdm.match_buf_len = bufsize;
1581         matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1582         if (matchccb.cdm.matches == NULL) {
1583                 warnx("can't malloc memory for matches");
1584                 retval = 1;
1585                 goto bailout;
1586         }
1587         matchccb.cdm.num_matches = 0;
1588
1589         matchccb.cdm.num_patterns = 1;
1590         matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1591
1592         matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1593                 matchccb.cdm.pattern_buf_len);
1594         if (matchccb.cdm.patterns == NULL) {
1595                 warnx("can't malloc memory for patterns");
1596                 retval = 1;
1597                 goto bailout;
1598         }
1599         matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1600         matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1601
1602         do {
1603                 unsigned int i;
1604
1605                 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1606                         warn("CAMIOCOMMAND ioctl failed");
1607                         retval = 1;
1608                         goto bailout;
1609                 }
1610
1611                 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1612                  || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1613                    && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1614                         warnx("got CAM error %#x, CDM error %d\n",
1615                               matchccb.ccb_h.status, matchccb.cdm.status);
1616                         retval = 1;
1617                         goto bailout;
1618                 }
1619
1620                 for (i = 0; i < matchccb.cdm.num_matches; i++) {
1621                         struct bus_match_result *bus_result;
1622
1623                         /* This shouldn't happen. */
1624                         if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1625                                 continue;
1626
1627                         bus_result = &matchccb.cdm.matches[i].result.bus_result;
1628
1629                         /*
1630                          * We don't want to rescan or reset the xpt bus.
1631                          * See above.
1632                          */
1633                         if ((int)bus_result->path_id == -1)
1634                                 continue;
1635
1636                         ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1637                                                        XPT_RESET_BUS;
1638                         ccb.ccb_h.path_id = bus_result->path_id;
1639                         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1640                         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1641                         ccb.crcn.flags = CAM_FLAG_NONE;
1642
1643                         /* run this at a low priority */
1644                         ccb.ccb_h.pinfo.priority = 5;
1645
1646                         if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1647                                 warn("CAMIOCOMMAND ioctl failed");
1648                                 retval = 1;
1649                                 goto bailout;
1650                         }
1651
1652                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1653                                 fprintf(stdout, "%s of bus %d was successful\n",
1654                                         rescan? "Re-scan" : "Reset",
1655                                         bus_result->path_id);
1656                         } else {
1657                                 /*
1658                                  * Don't bail out just yet, maybe the other
1659                                  * rescan or reset commands will complete
1660                                  * successfully.
1661                                  */
1662                                 fprintf(stderr, "%s of bus %d returned error "
1663                                         "%#x\n", rescan? "Re-scan" : "Reset",
1664                                         bus_result->path_id,
1665                                         ccb.ccb_h.status & CAM_STATUS_MASK);
1666                                 retval = 1;
1667                         }
1668                 }
1669         } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1670                  && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1671
1672 bailout:
1673
1674         if (fd != -1)
1675                 close(fd);
1676
1677         if (matchccb.cdm.patterns != NULL)
1678                 free(matchccb.cdm.patterns);
1679         if (matchccb.cdm.matches != NULL)
1680                 free(matchccb.cdm.matches);
1681
1682         return(retval);
1683 }
1684
1685 static int
1686 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1687 {
1688         union ccb ccb;
1689         struct cam_device *device;
1690         int fd;
1691
1692         device = NULL;
1693
1694         if (bus < 0) {
1695                 warnx("invalid bus number %d", bus);
1696                 return(1);
1697         }
1698
1699         if (target < 0) {
1700                 warnx("invalid target number %d", target);
1701                 return(1);
1702         }
1703
1704         if (lun < 0) {
1705                 warnx("invalid lun number %d", lun);
1706                 return(1);
1707         }
1708
1709         fd = -1;
1710
1711         bzero(&ccb, sizeof(union ccb));
1712
1713         if (scan) {
1714                 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1715                         warnx("error opening transport layer device %s\n",
1716                             XPT_DEVICE);
1717                         warn("%s", XPT_DEVICE);
1718                         return(1);
1719                 }
1720         } else {
1721                 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1722                 if (device == NULL) {
1723                         warnx("%s", cam_errbuf);
1724                         return(1);
1725                 }
1726         }
1727
1728         ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1729         ccb.ccb_h.path_id = bus;
1730         ccb.ccb_h.target_id = target;
1731         ccb.ccb_h.target_lun = lun;
1732         ccb.ccb_h.timeout = 5000;
1733         ccb.crcn.flags = CAM_FLAG_NONE;
1734
1735         /* run this at a low priority */
1736         ccb.ccb_h.pinfo.priority = 5;
1737
1738         if (scan) {
1739                 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1740                         warn("CAMIOCOMMAND ioctl failed");
1741                         close(fd);
1742                         return(1);
1743                 }
1744         } else {
1745                 if (cam_send_ccb(device, &ccb) < 0) {
1746                         warn("error sending XPT_RESET_DEV CCB");
1747                         cam_close_device(device);
1748                         return(1);
1749                 }
1750         }
1751
1752         if (scan)
1753                 close(fd);
1754         else
1755                 cam_close_device(device);
1756
1757         /*
1758          * An error code of CAM_BDR_SENT is normal for a BDR request.
1759          */
1760         if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1761          || ((!scan)
1762           && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1763                 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1764                     scan? "Re-scan" : "Reset", bus, target, lun);
1765                 return(0);
1766         } else {
1767                 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1768                     scan? "Re-scan" : "Reset", bus, target, lun,
1769                     ccb.ccb_h.status & CAM_STATUS_MASK);
1770                 return(1);
1771         }
1772 }
1773
1774 #ifndef MINIMALISTIC
1775 static int
1776 readdefects(struct cam_device *device, int argc, char **argv,
1777             char *combinedopt, int retry_count, int timeout)
1778 {
1779         union ccb *ccb = NULL;
1780         struct scsi_read_defect_data_10 *rdd_cdb;
1781         u_int8_t *defect_list = NULL;
1782         u_int32_t dlist_length = 65000;
1783         u_int32_t returned_length = 0;
1784         u_int32_t num_returned = 0;
1785         u_int8_t returned_format;
1786         unsigned int i;
1787         int c, error = 0;
1788         int lists_specified = 0;
1789
1790         while ((c = getopt(argc, argv, combinedopt)) != -1) {
1791                 switch(c){
1792                 case 'f':
1793                 {
1794                         char *tstr;
1795                         tstr = optarg;
1796                         while (isspace(*tstr) && (*tstr != '\0'))
1797                                 tstr++;
1798                         if (strcmp(tstr, "block") == 0)
1799                                 arglist |= CAM_ARG_FORMAT_BLOCK;
1800                         else if (strcmp(tstr, "bfi") == 0)
1801                                 arglist |= CAM_ARG_FORMAT_BFI;
1802                         else if (strcmp(tstr, "phys") == 0)
1803                                 arglist |= CAM_ARG_FORMAT_PHYS;
1804                         else {
1805                                 error = 1;
1806                                 warnx("invalid defect format %s", tstr);
1807                                 goto defect_bailout;
1808                         }
1809                         break;
1810                 }
1811                 case 'G':
1812                         arglist |= CAM_ARG_GLIST;
1813                         break;
1814                 case 'P':
1815                         arglist |= CAM_ARG_PLIST;
1816                         break;
1817                 default:
1818                         break;
1819                 }
1820         }
1821
1822         ccb = cam_getccb(device);
1823
1824         /*
1825          * Hopefully 65000 bytes is enough to hold the defect list.  If it
1826          * isn't, the disk is probably dead already.  We'd have to go with
1827          * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1828          * to hold them all.
1829          */
1830         defect_list = malloc(dlist_length);
1831         if (defect_list == NULL) {
1832                 warnx("can't malloc memory for defect list");
1833                 error = 1;
1834                 goto defect_bailout;
1835         }
1836
1837         rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1838
1839         /*
1840          * cam_getccb() zeros the CCB header only.  So we need to zero the
1841          * payload portion of the ccb.
1842          */
1843         bzero(&(&ccb->ccb_h)[1],
1844               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1845
1846         cam_fill_csio(&ccb->csio,
1847                       /*retries*/ retry_count,
1848                       /*cbfcnp*/ NULL,
1849                       /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1850                                               CAM_PASS_ERR_RECOVER : 0),
1851                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
1852                       /*data_ptr*/ defect_list,
1853                       /*dxfer_len*/ dlist_length,
1854                       /*sense_len*/ SSD_FULL_SIZE,
1855                       /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1856                       /*timeout*/ timeout ? timeout : 5000);
1857
1858         rdd_cdb->opcode = READ_DEFECT_DATA_10;
1859         if (arglist & CAM_ARG_FORMAT_BLOCK)
1860                 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1861         else if (arglist & CAM_ARG_FORMAT_BFI)
1862                 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1863         else if (arglist & CAM_ARG_FORMAT_PHYS)
1864                 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1865         else {
1866                 error = 1;
1867                 warnx("no defect list format specified");
1868                 goto defect_bailout;
1869         }
1870         if (arglist & CAM_ARG_PLIST) {
1871                 rdd_cdb->format |= SRDD10_PLIST;
1872                 lists_specified++;
1873         }
1874
1875         if (arglist & CAM_ARG_GLIST) {
1876                 rdd_cdb->format |= SRDD10_GLIST;
1877                 lists_specified++;
1878         }
1879
1880         scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1881
1882         /* Disable freezing the device queue */
1883         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1884
1885         if (cam_send_ccb(device, ccb) < 0) {
1886                 perror("error reading defect list");
1887
1888                 if (arglist & CAM_ARG_VERBOSE) {
1889                         cam_error_print(device, ccb, CAM_ESF_ALL,
1890                                         CAM_EPF_ALL, stderr);
1891                 }
1892
1893                 error = 1;
1894                 goto defect_bailout;
1895         }
1896
1897         returned_length = scsi_2btoul(((struct
1898                 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1899
1900         returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1901                         defect_list)->format;
1902
1903         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1904          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1905          && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1906                 struct scsi_sense_data *sense;
1907                 int error_code, sense_key, asc, ascq;
1908
1909                 sense = &ccb->csio.sense_data;
1910                 scsi_extract_sense_len(sense, ccb->csio.sense_len -
1911                     ccb->csio.sense_resid, &error_code, &sense_key, &asc,
1912                     &ascq, /*show_errors*/ 1);
1913
1914                 /*
1915                  * According to the SCSI spec, if the disk doesn't support
1916                  * the requested format, it will generally return a sense
1917                  * key of RECOVERED ERROR, and an additional sense code
1918                  * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1919                  * also check to make sure that the returned length is
1920                  * greater than 0, and then print out whatever format the
1921                  * disk gave us.
1922                  */
1923                 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1924                  && (asc == 0x1c) && (ascq == 0x00)
1925                  && (returned_length > 0)) {
1926                         warnx("requested defect format not available");
1927                         switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1928                         case SRDD10_BLOCK_FORMAT:
1929                                 warnx("Device returned block format");
1930                                 break;
1931                         case SRDD10_BYTES_FROM_INDEX_FORMAT:
1932                                 warnx("Device returned bytes from index"
1933                                       " format");
1934                                 break;
1935                         case SRDD10_PHYSICAL_SECTOR_FORMAT:
1936                                 warnx("Device returned physical sector format");
1937                                 break;
1938                         default:
1939                                 error = 1;
1940                                 warnx("Device returned unknown defect"
1941                                      " data format %#x", returned_format);
1942                                 goto defect_bailout;
1943                                 break; /* NOTREACHED */
1944                         }
1945                 } else {
1946                         error = 1;
1947                         warnx("Error returned from read defect data command");
1948                         if (arglist & CAM_ARG_VERBOSE)
1949                                 cam_error_print(device, ccb, CAM_ESF_ALL,
1950                                                 CAM_EPF_ALL, stderr);
1951                         goto defect_bailout;
1952                 }
1953         } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1954                 error = 1;
1955                 warnx("Error returned from read defect data command");
1956                 if (arglist & CAM_ARG_VERBOSE)
1957                         cam_error_print(device, ccb, CAM_ESF_ALL,
1958                                         CAM_EPF_ALL, stderr);
1959                 goto defect_bailout;
1960         }
1961
1962         /*
1963          * XXX KDM  I should probably clean up the printout format for the
1964          * disk defects.
1965          */
1966         switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1967                 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1968                 {
1969                         struct scsi_defect_desc_phys_sector *dlist;
1970
1971                         dlist = (struct scsi_defect_desc_phys_sector *)
1972                                 (defect_list +
1973                                 sizeof(struct scsi_read_defect_data_hdr_10));
1974
1975                         num_returned = returned_length /
1976                                 sizeof(struct scsi_defect_desc_phys_sector);
1977
1978                         fprintf(stderr, "Got %d defect", num_returned);
1979
1980                         if ((lists_specified == 0) || (num_returned == 0)) {
1981                                 fprintf(stderr, "s.\n");
1982                                 break;
1983                         } else if (num_returned == 1)
1984                                 fprintf(stderr, ":\n");
1985                         else
1986                                 fprintf(stderr, "s:\n");
1987
1988                         for (i = 0; i < num_returned; i++) {
1989                                 fprintf(stdout, "%d:%d:%d\n",
1990                                         scsi_3btoul(dlist[i].cylinder),
1991                                         dlist[i].head,
1992                                         scsi_4btoul(dlist[i].sector));
1993                         }
1994                         break;
1995                 }
1996                 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1997                 {
1998                         struct scsi_defect_desc_bytes_from_index *dlist;
1999
2000                         dlist = (struct scsi_defect_desc_bytes_from_index *)
2001                                 (defect_list +
2002                                 sizeof(struct scsi_read_defect_data_hdr_10));
2003
2004                         num_returned = returned_length /
2005                               sizeof(struct scsi_defect_desc_bytes_from_index);
2006
2007                         fprintf(stderr, "Got %d defect", num_returned);
2008
2009                         if ((lists_specified == 0) || (num_returned == 0)) {
2010                                 fprintf(stderr, "s.\n");
2011                                 break;
2012                         } else if (num_returned == 1)
2013                                 fprintf(stderr, ":\n");
2014                         else
2015                                 fprintf(stderr, "s:\n");
2016
2017                         for (i = 0; i < num_returned; i++) {
2018                                 fprintf(stdout, "%d:%d:%d\n",
2019                                         scsi_3btoul(dlist[i].cylinder),
2020                                         dlist[i].head,
2021                                         scsi_4btoul(dlist[i].bytes_from_index));
2022                         }
2023                         break;
2024                 }
2025                 case SRDDH10_BLOCK_FORMAT:
2026                 {
2027                         struct scsi_defect_desc_block *dlist;
2028
2029                         dlist = (struct scsi_defect_desc_block *)(defect_list +
2030                                 sizeof(struct scsi_read_defect_data_hdr_10));
2031
2032                         num_returned = returned_length /
2033                               sizeof(struct scsi_defect_desc_block);
2034
2035                         fprintf(stderr, "Got %d defect", num_returned);
2036
2037                         if ((lists_specified == 0) || (num_returned == 0)) {
2038                                 fprintf(stderr, "s.\n");
2039                                 break;
2040                         } else if (num_returned == 1)
2041                                 fprintf(stderr, ":\n");
2042                         else
2043                                 fprintf(stderr, "s:\n");
2044
2045                         for (i = 0; i < num_returned; i++)
2046                                 fprintf(stdout, "%u\n",
2047                                         scsi_4btoul(dlist[i].address));
2048                         break;
2049                 }
2050                 default:
2051                         fprintf(stderr, "Unknown defect format %d\n",
2052                                 returned_format & SRDDH10_DLIST_FORMAT_MASK);
2053                         error = 1;
2054                         break;
2055         }
2056 defect_bailout:
2057
2058         if (defect_list != NULL)
2059                 free(defect_list);
2060
2061         if (ccb != NULL)
2062                 cam_freeccb(ccb);
2063
2064         return(error);
2065 }
2066 #endif /* MINIMALISTIC */
2067
2068 #if 0
2069 void
2070 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2071 {
2072         union ccb *ccb;
2073
2074         ccb = cam_getccb(device);
2075
2076         cam_freeccb(ccb);
2077 }
2078 #endif
2079
2080 #ifndef MINIMALISTIC
2081 void
2082 mode_sense(struct cam_device *device, int mode_page, int page_control,
2083            int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2084 {
2085         union ccb *ccb;
2086         int retval;
2087
2088         ccb = cam_getccb(device);
2089
2090         if (ccb == NULL)
2091                 errx(1, "mode_sense: couldn't allocate CCB");
2092
2093         bzero(&(&ccb->ccb_h)[1],
2094               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2095
2096         scsi_mode_sense(&ccb->csio,
2097                         /* retries */ retry_count,
2098                         /* cbfcnp */ NULL,
2099                         /* tag_action */ MSG_SIMPLE_Q_TAG,
2100                         /* dbd */ dbd,
2101                         /* page_code */ page_control << 6,
2102                         /* page */ mode_page,
2103                         /* param_buf */ data,
2104                         /* param_len */ datalen,
2105                         /* sense_len */ SSD_FULL_SIZE,
2106                         /* timeout */ timeout ? timeout : 5000);
2107
2108         if (arglist & CAM_ARG_ERR_RECOVER)
2109                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2110
2111         /* Disable freezing the device queue */
2112         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2113
2114         if (((retval = cam_send_ccb(device, ccb)) < 0)
2115          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2116                 if (arglist & CAM_ARG_VERBOSE) {
2117                         cam_error_print(device, ccb, CAM_ESF_ALL,
2118                                         CAM_EPF_ALL, stderr);
2119                 }
2120                 cam_freeccb(ccb);
2121                 cam_close_device(device);
2122                 if (retval < 0)
2123                         err(1, "error sending mode sense command");
2124                 else
2125                         errx(1, "error sending mode sense command");
2126         }
2127
2128         cam_freeccb(ccb);
2129 }
2130
2131 void
2132 mode_select(struct cam_device *device, int save_pages, int retry_count,
2133            int timeout, u_int8_t *data, int datalen)
2134 {
2135         union ccb *ccb;
2136         int retval;
2137
2138         ccb = cam_getccb(device);
2139
2140         if (ccb == NULL)
2141                 errx(1, "mode_select: couldn't allocate CCB");
2142
2143         bzero(&(&ccb->ccb_h)[1],
2144               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2145
2146         scsi_mode_select(&ccb->csio,
2147                          /* retries */ retry_count,
2148                          /* cbfcnp */ NULL,
2149                          /* tag_action */ MSG_SIMPLE_Q_TAG,
2150                          /* scsi_page_fmt */ 1,
2151                          /* save_pages */ save_pages,
2152                          /* param_buf */ data,
2153                          /* param_len */ datalen,
2154                          /* sense_len */ SSD_FULL_SIZE,
2155                          /* timeout */ timeout ? timeout : 5000);
2156
2157         if (arglist & CAM_ARG_ERR_RECOVER)
2158                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2159
2160         /* Disable freezing the device queue */
2161         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2162
2163         if (((retval = cam_send_ccb(device, ccb)) < 0)
2164          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2165                 if (arglist & CAM_ARG_VERBOSE) {
2166                         cam_error_print(device, ccb, CAM_ESF_ALL,
2167                                         CAM_EPF_ALL, stderr);
2168                 }
2169                 cam_freeccb(ccb);
2170                 cam_close_device(device);
2171
2172                 if (retval < 0)
2173                         err(1, "error sending mode select command");
2174                 else
2175                         errx(1, "error sending mode select command");
2176
2177         }
2178
2179         cam_freeccb(ccb);
2180 }
2181
2182 void
2183 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2184          int retry_count, int timeout)
2185 {
2186         int c, mode_page = -1, page_control = 0;
2187         int binary = 0, list = 0;
2188
2189         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2190                 switch(c) {
2191                 case 'b':
2192                         binary = 1;
2193                         break;
2194                 case 'd':
2195                         arglist |= CAM_ARG_DBD;
2196                         break;
2197                 case 'e':
2198                         arglist |= CAM_ARG_MODE_EDIT;
2199                         break;
2200                 case 'l':
2201                         list = 1;
2202                         break;
2203                 case 'm':
2204                         mode_page = strtol(optarg, NULL, 0);
2205                         if (mode_page < 0)
2206                                 errx(1, "invalid mode page %d", mode_page);
2207                         break;
2208                 case 'P':
2209                         page_control = strtol(optarg, NULL, 0);
2210                         if ((page_control < 0) || (page_control > 3))
2211                                 errx(1, "invalid page control field %d",
2212                                      page_control);
2213                         arglist |= CAM_ARG_PAGE_CNTL;
2214                         break;
2215                 default:
2216                         break;
2217                 }
2218         }
2219
2220         if (mode_page == -1 && list == 0)
2221                 errx(1, "you must specify a mode page!");
2222
2223         if (list) {
2224                 mode_list(device, page_control, arglist & CAM_ARG_DBD,
2225                     retry_count, timeout);
2226         } else {
2227                 mode_edit(device, mode_page, page_control,
2228                     arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2229                     retry_count, timeout);
2230         }
2231 }
2232
2233 static int
2234 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2235         int retry_count, int timeout)
2236 {
2237         union ccb *ccb;
2238         u_int32_t flags = CAM_DIR_NONE;
2239         u_int8_t *data_ptr = NULL;
2240         u_int8_t cdb[20];
2241         u_int8_t atacmd[12];
2242         struct get_hook hook;
2243         int c, data_bytes = 0;
2244         int cdb_len = 0;
2245         int atacmd_len = 0;
2246         int dmacmd = 0;
2247         int fpdmacmd = 0;
2248         int need_res = 0;
2249         char *datastr = NULL, *tstr, *resstr = NULL;
2250         int error = 0;
2251         int fd_data = 0, fd_res = 0;
2252         int retval;
2253
2254         ccb = cam_getccb(device);
2255
2256         if (ccb == NULL) {
2257                 warnx("scsicmd: error allocating ccb");
2258                 return(1);
2259         }
2260
2261         bzero(&(&ccb->ccb_h)[1],
2262               sizeof(union ccb) - sizeof(struct ccb_hdr));
2263
2264         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2265                 switch(c) {
2266                 case 'a':
2267                         tstr = optarg;
2268                         while (isspace(*tstr) && (*tstr != '\0'))
2269                                 tstr++;
2270                         hook.argc = argc - optind;
2271                         hook.argv = argv + optind;
2272                         hook.got = 0;
2273                         atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2274                                                     iget, &hook);
2275                         /*
2276                          * Increment optind by the number of arguments the
2277                          * encoding routine processed.  After each call to
2278                          * getopt(3), optind points to the argument that
2279                          * getopt should process _next_.  In this case,
2280                          * that means it points to the first command string
2281                          * argument, if there is one.  Once we increment
2282                          * this, it should point to either the next command
2283                          * line argument, or it should be past the end of
2284                          * the list.
2285                          */
2286                         optind += hook.got;
2287                         break;
2288                 case 'c':
2289                         tstr = optarg;
2290                         while (isspace(*tstr) && (*tstr != '\0'))
2291                                 tstr++;
2292                         hook.argc = argc - optind;
2293                         hook.argv = argv + optind;
2294                         hook.got = 0;
2295                         cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2296                                                     iget, &hook);
2297                         /*
2298                          * Increment optind by the number of arguments the
2299                          * encoding routine processed.  After each call to
2300                          * getopt(3), optind points to the argument that
2301                          * getopt should process _next_.  In this case,
2302                          * that means it points to the first command string
2303                          * argument, if there is one.  Once we increment
2304                          * this, it should point to either the next command
2305                          * line argument, or it should be past the end of
2306                          * the list.
2307                          */
2308                         optind += hook.got;
2309                         break;
2310                 case 'd':
2311                         dmacmd = 1;
2312                         break;
2313                 case 'f':
2314                         fpdmacmd = 1;
2315                         break;
2316                 case 'i':
2317                         if (arglist & CAM_ARG_CMD_OUT) {
2318                                 warnx("command must either be "
2319                                       "read or write, not both");
2320                                 error = 1;
2321                                 goto scsicmd_bailout;
2322                         }
2323                         arglist |= CAM_ARG_CMD_IN;
2324                         flags = CAM_DIR_IN;
2325                         data_bytes = strtol(optarg, NULL, 0);
2326                         if (data_bytes <= 0) {
2327                                 warnx("invalid number of input bytes %d",
2328                                       data_bytes);
2329                                 error = 1;
2330                                 goto scsicmd_bailout;
2331                         }
2332                         hook.argc = argc - optind;
2333                         hook.argv = argv + optind;
2334                         hook.got = 0;
2335                         optind++;
2336                         datastr = cget(&hook, NULL);
2337                         /*
2338                          * If the user supplied "-" instead of a format, he
2339                          * wants the data to be written to stdout.
2340                          */
2341                         if ((datastr != NULL)
2342                          && (datastr[0] == '-'))
2343                                 fd_data = 1;
2344
2345                         data_ptr = (u_int8_t *)malloc(data_bytes);
2346                         if (data_ptr == NULL) {
2347                                 warnx("can't malloc memory for data_ptr");
2348                                 error = 1;
2349                                 goto scsicmd_bailout;
2350                         }
2351                         break;
2352                 case 'o':
2353                         if (arglist & CAM_ARG_CMD_IN) {
2354                                 warnx("command must either be "
2355                                       "read or write, not both");
2356                                 error = 1;
2357                                 goto scsicmd_bailout;
2358                         }
2359                         arglist |= CAM_ARG_CMD_OUT;
2360                         flags = CAM_DIR_OUT;
2361                         data_bytes = strtol(optarg, NULL, 0);
2362                         if (data_bytes <= 0) {
2363                                 warnx("invalid number of output bytes %d",
2364                                       data_bytes);
2365                                 error = 1;
2366                                 goto scsicmd_bailout;
2367                         }
2368                         hook.argc = argc - optind;
2369                         hook.argv = argv + optind;
2370                         hook.got = 0;
2371                         datastr = cget(&hook, NULL);
2372                         data_ptr = (u_int8_t *)malloc(data_bytes);
2373                         if (data_ptr == NULL) {
2374                                 warnx("can't malloc memory for data_ptr");
2375                                 error = 1;
2376                                 goto scsicmd_bailout;
2377                         }
2378                         bzero(data_ptr, data_bytes);
2379                         /*
2380                          * If the user supplied "-" instead of a format, he
2381                          * wants the data to be read from stdin.
2382                          */
2383                         if ((datastr != NULL)
2384                          && (datastr[0] == '-'))
2385                                 fd_data = 1;
2386                         else
2387                                 buff_encode_visit(data_ptr, data_bytes, datastr,
2388                                                   iget, &hook);
2389                         optind += hook.got;
2390                         break;
2391                 case 'r':
2392                         need_res = 1;
2393                         hook.argc = argc - optind;
2394                         hook.argv = argv + optind;
2395                         hook.got = 0;
2396                         resstr = cget(&hook, NULL);
2397                         if ((resstr != NULL) && (resstr[0] == '-'))
2398                                 fd_res = 1;
2399                         optind += hook.got;
2400                         break;
2401                 default:
2402                         break;
2403                 }
2404         }
2405
2406         /*
2407          * If fd_data is set, and we're writing to the device, we need to
2408          * read the data the user wants written from stdin.
2409          */
2410         if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2411                 ssize_t amt_read;
2412                 int amt_to_read = data_bytes;
2413                 u_int8_t *buf_ptr = data_ptr;
2414
2415                 for (amt_read = 0; amt_to_read > 0;
2416                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2417                         if (amt_read == -1) {
2418                                 warn("error reading data from stdin");
2419                                 error = 1;
2420                                 goto scsicmd_bailout;
2421                         }
2422                         amt_to_read -= amt_read;
2423                         buf_ptr += amt_read;
2424                 }
2425         }
2426
2427         if (arglist & CAM_ARG_ERR_RECOVER)
2428                 flags |= CAM_PASS_ERR_RECOVER;
2429
2430         /* Disable freezing the device queue */
2431         flags |= CAM_DEV_QFRZDIS;
2432
2433         if (cdb_len) {
2434                 /*
2435                  * This is taken from the SCSI-3 draft spec.
2436                  * (T10/1157D revision 0.3)
2437                  * The top 3 bits of an opcode are the group code.
2438                  * The next 5 bits are the command code.
2439                  * Group 0:  six byte commands
2440                  * Group 1:  ten byte commands
2441                  * Group 2:  ten byte commands
2442                  * Group 3:  reserved
2443                  * Group 4:  sixteen byte commands
2444                  * Group 5:  twelve byte commands
2445                  * Group 6:  vendor specific
2446                  * Group 7:  vendor specific
2447                  */
2448                 switch((cdb[0] >> 5) & 0x7) {
2449                         case 0:
2450                                 cdb_len = 6;
2451                                 break;
2452                         case 1:
2453                         case 2:
2454                                 cdb_len = 10;
2455                                 break;
2456                         case 3:
2457                         case 6:
2458                         case 7:
2459                                 /* computed by buff_encode_visit */
2460                                 break;
2461                         case 4:
2462                                 cdb_len = 16;
2463                                 break;
2464                         case 5:
2465                                 cdb_len = 12;
2466                                 break;
2467                 }
2468
2469                 /*
2470                  * We should probably use csio_build_visit or something like that
2471                  * here, but it's easier to encode arguments as you go.  The
2472                  * alternative would be skipping the CDB argument and then encoding
2473                  * it here, since we've got the data buffer argument by now.
2474                  */
2475                 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2476
2477                 cam_fill_csio(&ccb->csio,
2478                       /*retries*/ retry_count,
2479                       /*cbfcnp*/ NULL,
2480                       /*flags*/ flags,
2481                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
2482                       /*data_ptr*/ data_ptr,
2483                       /*dxfer_len*/ data_bytes,
2484                       /*sense_len*/ SSD_FULL_SIZE,
2485                       /*cdb_len*/ cdb_len,
2486                       /*timeout*/ timeout ? timeout : 5000);
2487         } else {
2488                 atacmd_len = 12;
2489                 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2490                 if (need_res)
2491                         ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2492                 if (dmacmd)
2493                         ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2494                 if (fpdmacmd)
2495                         ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2496
2497                 cam_fill_ataio(&ccb->ataio,
2498                       /*retries*/ retry_count,
2499                       /*cbfcnp*/ NULL,
2500                       /*flags*/ flags,
2501                       /*tag_action*/ 0,
2502                       /*data_ptr*/ data_ptr,
2503                       /*dxfer_len*/ data_bytes,
2504                       /*timeout*/ timeout ? timeout : 5000);
2505         }
2506
2507         if (((retval = cam_send_ccb(device, ccb)) < 0)
2508          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2509                 const char *warnstr = "error sending command";
2510
2511                 if (retval < 0)
2512                         warn(warnstr);
2513                 else
2514                         warnx(warnstr);
2515
2516                 if (arglist & CAM_ARG_VERBOSE) {
2517                         cam_error_print(device, ccb, CAM_ESF_ALL,
2518                                         CAM_EPF_ALL, stderr);
2519                 }
2520
2521                 error = 1;
2522                 goto scsicmd_bailout;
2523         }
2524
2525         if (atacmd_len && need_res) {
2526                 if (fd_res == 0) {
2527                         buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2528                                           arg_put, NULL);
2529                         fprintf(stdout, "\n");
2530                 } else {
2531                         fprintf(stdout,
2532                             "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2533                             ccb->ataio.res.status,
2534                             ccb->ataio.res.error,
2535                             ccb->ataio.res.lba_low,
2536                             ccb->ataio.res.lba_mid,
2537                             ccb->ataio.res.lba_high,
2538                             ccb->ataio.res.device,
2539                             ccb->ataio.res.lba_low_exp,
2540                             ccb->ataio.res.lba_mid_exp,
2541                             ccb->ataio.res.lba_high_exp,
2542                             ccb->ataio.res.sector_count,
2543                             ccb->ataio.res.sector_count_exp);
2544                         fflush(stdout);
2545                 }
2546         }
2547
2548         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2549          && (arglist & CAM_ARG_CMD_IN)
2550          && (data_bytes > 0)) {
2551                 if (fd_data == 0) {
2552                         buff_decode_visit(data_ptr, data_bytes, datastr,
2553                                           arg_put, NULL);
2554                         fprintf(stdout, "\n");
2555                 } else {
2556                         ssize_t amt_written;
2557                         int amt_to_write = data_bytes;
2558                         u_int8_t *buf_ptr = data_ptr;
2559
2560                         for (amt_written = 0; (amt_to_write > 0) &&
2561                              (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2562                                 amt_to_write -= amt_written;
2563                                 buf_ptr += amt_written;
2564                         }
2565                         if (amt_written == -1) {
2566                                 warn("error writing data to stdout");
2567                                 error = 1;
2568                                 goto scsicmd_bailout;
2569                         } else if ((amt_written == 0)
2570                                 && (amt_to_write > 0)) {
2571                                 warnx("only wrote %u bytes out of %u",
2572                                       data_bytes - amt_to_write, data_bytes);
2573                         }
2574                 }
2575         }
2576
2577 scsicmd_bailout:
2578
2579         if ((data_bytes > 0) && (data_ptr != NULL))
2580                 free(data_ptr);
2581
2582         cam_freeccb(ccb);
2583
2584         return(error);
2585 }
2586
2587 static int
2588 camdebug(int argc, char **argv, char *combinedopt)
2589 {
2590         int c, fd;
2591         int bus = -1, target = -1, lun = -1;
2592         char *tstr, *tmpstr = NULL;
2593         union ccb ccb;
2594         int error = 0;
2595
2596         bzero(&ccb, sizeof(union ccb));
2597
2598         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2599                 switch(c) {
2600                 case 'I':
2601                         arglist |= CAM_ARG_DEBUG_INFO;
2602                         ccb.cdbg.flags |= CAM_DEBUG_INFO;
2603                         break;
2604                 case 'P':
2605                         arglist |= CAM_ARG_DEBUG_PERIPH;
2606                         ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2607                         break;
2608                 case 'S':
2609                         arglist |= CAM_ARG_DEBUG_SUBTRACE;
2610                         ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2611                         break;
2612                 case 'T':
2613                         arglist |= CAM_ARG_DEBUG_TRACE;
2614                         ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2615                         break;
2616                 case 'X':
2617                         arglist |= CAM_ARG_DEBUG_XPT;
2618                         ccb.cdbg.flags |= CAM_DEBUG_XPT;
2619                         break;
2620                 case 'c':
2621                         arglist |= CAM_ARG_DEBUG_CDB;
2622                         ccb.cdbg.flags |= CAM_DEBUG_CDB;
2623                         break;
2624                 default:
2625                         break;
2626                 }
2627         }
2628
2629         if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2630                 warnx("error opening transport layer device %s", XPT_DEVICE);
2631                 warn("%s", XPT_DEVICE);
2632                 return(1);
2633         }
2634         argc -= optind;
2635         argv += optind;
2636
2637         if (argc <= 0) {
2638                 warnx("you must specify \"off\", \"all\" or a bus,");
2639                 warnx("bus:target, or bus:target:lun");
2640                 close(fd);
2641                 return(1);
2642         }
2643
2644         tstr = *argv;
2645
2646         while (isspace(*tstr) && (*tstr != '\0'))
2647                 tstr++;
2648
2649         if (strncmp(tstr, "off", 3) == 0) {
2650                 ccb.cdbg.flags = CAM_DEBUG_NONE;
2651                 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2652                              CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2653                              CAM_ARG_DEBUG_XPT);
2654         } else if (strncmp(tstr, "all", 3) != 0) {
2655                 tmpstr = (char *)strtok(tstr, ":");
2656                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2657                         bus = strtol(tmpstr, NULL, 0);
2658                         arglist |= CAM_ARG_BUS;
2659                         tmpstr = (char *)strtok(NULL, ":");
2660                         if ((tmpstr != NULL) && (*tmpstr != '\0')){
2661                                 target = strtol(tmpstr, NULL, 0);
2662                                 arglist |= CAM_ARG_TARGET;
2663                                 tmpstr = (char *)strtok(NULL, ":");
2664                                 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2665                                         lun = strtol(tmpstr, NULL, 0);
2666                                         arglist |= CAM_ARG_LUN;
2667                                 }
2668                         }
2669                 } else {
2670                         error = 1;
2671                         warnx("you must specify \"all\", \"off\", or a bus,");
2672                         warnx("bus:target, or bus:target:lun to debug");
2673                 }
2674         }
2675
2676         if (error == 0) {
2677
2678                 ccb.ccb_h.func_code = XPT_DEBUG;
2679                 ccb.ccb_h.path_id = bus;
2680                 ccb.ccb_h.target_id = target;
2681                 ccb.ccb_h.target_lun = lun;
2682
2683                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2684                         warn("CAMIOCOMMAND ioctl failed");
2685                         error = 1;
2686                 }
2687
2688                 if (error == 0) {
2689                         if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2690                              CAM_FUNC_NOTAVAIL) {
2691                                 warnx("CAM debugging not available");
2692                                 warnx("you need to put options CAMDEBUG in"
2693                                       " your kernel config file!");
2694                                 error = 1;
2695                         } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2696                                     CAM_REQ_CMP) {
2697                                 warnx("XPT_DEBUG CCB failed with status %#x",
2698                                       ccb.ccb_h.status);
2699                                 error = 1;
2700                         } else {
2701                                 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2702                                         fprintf(stderr,
2703                                                 "Debugging turned off\n");
2704                                 } else {
2705                                         fprintf(stderr,
2706                                                 "Debugging enabled for "
2707                                                 "%d:%d:%d\n",
2708                                                 bus, target, lun);
2709                                 }
2710                         }
2711                 }
2712                 close(fd);
2713         }
2714
2715         return(error);
2716 }
2717
2718 static int
2719 tagcontrol(struct cam_device *device, int argc, char **argv,
2720            char *combinedopt)
2721 {
2722         int c;
2723         union ccb *ccb;
2724         int numtags = -1;
2725         int retval = 0;
2726         int quiet = 0;
2727         char pathstr[1024];
2728
2729         ccb = cam_getccb(device);
2730
2731         if (ccb == NULL) {
2732                 warnx("tagcontrol: error allocating ccb");
2733                 return(1);
2734         }
2735
2736         while ((c = getopt(argc, argv, combinedopt)) != -1) {
2737                 switch(c) {
2738                 case 'N':
2739                         numtags = strtol(optarg, NULL, 0);
2740                         if (numtags < 0) {
2741                                 warnx("tag count %d is < 0", numtags);
2742                                 retval = 1;
2743                                 goto tagcontrol_bailout;
2744                         }
2745                         break;
2746                 case 'q':
2747                         quiet++;
2748                         break;
2749                 default:
2750                         break;
2751                 }
2752         }
2753
2754         cam_path_string(device, pathstr, sizeof(pathstr));
2755
2756         if (numtags >= 0) {
2757                 bzero(&(&ccb->ccb_h)[1],
2758                       sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2759                 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2760                 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
2761                 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2762                 ccb->crs.openings = numtags;
2763
2764
2765                 if (cam_send_ccb(device, ccb) < 0) {
2766                         perror("error sending XPT_REL_SIMQ CCB");
2767                         retval = 1;
2768                         goto tagcontrol_bailout;
2769                 }
2770
2771                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2772                         warnx("XPT_REL_SIMQ CCB failed");
2773                         cam_error_print(device, ccb, CAM_ESF_ALL,
2774                                         CAM_EPF_ALL, stderr);
2775                         retval = 1;
2776                         goto tagcontrol_bailout;
2777                 }
2778
2779
2780                 if (quiet == 0)
2781                         fprintf(stdout, "%stagged openings now %d\n",
2782                                 pathstr, ccb->crs.openings);
2783         }
2784
2785         bzero(&(&ccb->ccb_h)[1],
2786               sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2787
2788         ccb->ccb_h.func_code = XPT_GDEV_STATS;
2789
2790         if (cam_send_ccb(device, ccb) < 0) {
2791                 perror("error sending XPT_GDEV_STATS CCB");
2792                 retval = 1;
2793                 goto tagcontrol_bailout;
2794         }
2795
2796         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2797                 warnx("XPT_GDEV_STATS CCB failed");
2798                 cam_error_print(device, ccb, CAM_ESF_ALL,
2799                                 CAM_EPF_ALL, stderr);
2800                 retval = 1;
2801                 goto tagcontrol_bailout;
2802         }
2803
2804         if (arglist & CAM_ARG_VERBOSE) {
2805                 fprintf(stdout, "%s", pathstr);
2806                 fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2807                 fprintf(stdout, "%s", pathstr);
2808                 fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2809                 fprintf(stdout, "%s", pathstr);
2810                 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2811                 fprintf(stdout, "%s", pathstr);
2812                 fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2813                 fprintf(stdout, "%s", pathstr);
2814                 fprintf(stdout, "held          %d\n", ccb->cgds.held);
2815                 fprintf(stdout, "%s", pathstr);
2816                 fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2817                 fprintf(stdout, "%s", pathstr);
2818                 fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2819         } else {
2820                 if (quiet == 0) {
2821                         fprintf(stdout, "%s", pathstr);
2822                         fprintf(stdout, "device openings: ");
2823                 }
2824                 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2825                         ccb->cgds.dev_active);
2826         }
2827
2828 tagcontrol_bailout:
2829
2830         cam_freeccb(ccb);
2831         return(retval);
2832 }
2833
2834 static void
2835 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2836 {
2837         char pathstr[1024];
2838
2839         cam_path_string(device, pathstr, sizeof(pathstr));
2840
2841         if (cts->transport == XPORT_SPI) {
2842                 struct ccb_trans_settings_spi *spi =
2843                     &cts->xport_specific.spi;
2844
2845                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2846
2847                         fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2848                                 spi->sync_period);
2849
2850                         if (spi->sync_offset != 0) {
2851                                 u_int freq;
2852
2853                                 freq = scsi_calc_syncsrate(spi->sync_period);
2854                                 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2855                                         pathstr, freq / 1000, freq % 1000);
2856                         }
2857                 }
2858
2859                 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2860                         fprintf(stdout, "%soffset: %d\n", pathstr,
2861                             spi->sync_offset);
2862                 }
2863
2864                 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2865                         fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2866                                 (0x01 << spi->bus_width) * 8);
2867                 }
2868
2869                 if (spi->valid & CTS_SPI_VALID_DISC) {
2870                         fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2871                                 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2872                                 "enabled" : "disabled");
2873                 }
2874         }
2875         if (cts->transport == XPORT_ATA) {
2876                 struct ccb_trans_settings_ata *ata =
2877                     &cts->xport_specific.ata;
2878
2879                 if ((ata->valid & CTS_ATA_VALID_MODE) != 0) {
2880                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
2881                                 ata_mode2string(ata->mode));
2882                 }
2883                 if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2884                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2885                                 ata->atapi);
2886                 }
2887                 if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2888                         fprintf(stdout, "%sPIO transaction length: %d\n",
2889                                 pathstr, ata->bytecount);
2890                 }
2891         }
2892         if (cts->transport == XPORT_SATA) {
2893                 struct ccb_trans_settings_sata *sata =
2894                     &cts->xport_specific.sata;
2895
2896                 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2897                         fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2898                                 sata->revision);
2899                 }
2900                 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2901                         fprintf(stdout, "%sATA mode: %s\n", pathstr,
2902                                 ata_mode2string(sata->mode));
2903                 }
2904                 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2905                         fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2906                                 sata->atapi);
2907                 }
2908                 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2909                         fprintf(stdout, "%sPIO transaction length: %d\n",
2910                                 pathstr, sata->bytecount);
2911                 }
2912                 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2913                         fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2914                                 sata->pm_present);
2915                 }
2916                 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2917                         fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2918                                 sata->tags);
2919                 }
2920                 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2921                         fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2922                                 sata->caps);
2923                 }
2924         }
2925         if (cts->protocol == PROTO_SCSI) {
2926                 struct ccb_trans_settings_scsi *scsi=
2927                     &cts->proto_specific.scsi;
2928
2929                 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2930                         fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2931                                 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2932                                 "enabled" : "disabled");
2933                 }
2934         }
2935
2936 }
2937
2938 /*
2939  * Get a path inquiry CCB for the specified device.
2940  */
2941 static int
2942 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2943 {
2944         union ccb *ccb;
2945         int retval = 0;
2946
2947         ccb = cam_getccb(device);
2948         if (ccb == NULL) {
2949                 warnx("get_cpi: couldn't allocate CCB");
2950                 return(1);
2951         }
2952         bzero(&(&ccb->ccb_h)[1],
2953               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2954         ccb->ccb_h.func_code = XPT_PATH_INQ;
2955         if (cam_send_ccb(device, ccb) < 0) {
2956                 warn("get_cpi: error sending Path Inquiry CCB");
2957                 if (arglist & CAM_ARG_VERBOSE)
2958                         cam_error_print(device, ccb, CAM_ESF_ALL,
2959                                         CAM_EPF_ALL, stderr);
2960                 retval = 1;
2961                 goto get_cpi_bailout;
2962         }
2963         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2964                 if (arglist & CAM_ARG_VERBOSE)
2965                         cam_error_print(device, ccb, CAM_ESF_ALL,
2966                                         CAM_EPF_ALL, stderr);
2967                 retval = 1;
2968                 goto get_cpi_bailout;
2969         }
2970         bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2971
2972 get_cpi_bailout:
2973         cam_freeccb(ccb);
2974         return(retval);
2975 }
2976
2977 /*
2978  * Get a get device CCB for the specified device.
2979  */
2980 static int
2981 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
2982 {
2983         union ccb *ccb;
2984         int retval = 0;
2985
2986         ccb = cam_getccb(device);
2987         if (ccb == NULL) {
2988                 warnx("get_cgd: couldn't allocate CCB");
2989                 return(1);
2990         }
2991         bzero(&(&ccb->ccb_h)[1],
2992               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2993         ccb->ccb_h.func_code = XPT_GDEV_TYPE;
2994         if (cam_send_ccb(device, ccb) < 0) {
2995                 warn("get_cgd: error sending Path Inquiry CCB");
2996                 if (arglist & CAM_ARG_VERBOSE)
2997                         cam_error_print(device, ccb, CAM_ESF_ALL,
2998                                         CAM_EPF_ALL, stderr);
2999                 retval = 1;
3000                 goto get_cgd_bailout;
3001         }
3002         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3003                 if (arglist & CAM_ARG_VERBOSE)
3004                         cam_error_print(device, ccb, CAM_ESF_ALL,
3005                                         CAM_EPF_ALL, stderr);
3006                 retval = 1;
3007                 goto get_cgd_bailout;
3008         }
3009         bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3010
3011 get_cgd_bailout:
3012         cam_freeccb(ccb);
3013         return(retval);
3014 }
3015
3016 static void
3017 cpi_print(struct ccb_pathinq *cpi)
3018 {
3019         char adapter_str[1024];
3020         int i;
3021
3022         snprintf(adapter_str, sizeof(adapter_str),
3023                  "%s%d:", cpi->dev_name, cpi->unit_number);
3024
3025         fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3026                 cpi->version_num);
3027
3028         for (i = 1; i < 0xff; i = i << 1) {
3029                 const char *str;
3030
3031                 if ((i & cpi->hba_inquiry) == 0)
3032                         continue;
3033
3034                 fprintf(stdout, "%s supports ", adapter_str);
3035
3036                 switch(i) {
3037                 case PI_MDP_ABLE:
3038                         str = "MDP message";
3039                         break;
3040                 case PI_WIDE_32:
3041                         str = "32 bit wide SCSI";
3042                         break;
3043                 case PI_WIDE_16:
3044                         str = "16 bit wide SCSI";
3045                         break;
3046                 case PI_SDTR_ABLE:
3047                         str = "SDTR message";
3048                         break;
3049                 case PI_LINKED_CDB:
3050                         str = "linked CDBs";
3051                         break;
3052                 case PI_TAG_ABLE:
3053                         str = "tag queue messages";
3054                         break;
3055                 case PI_SOFT_RST:
3056                         str = "soft reset alternative";
3057                         break;
3058                 case PI_SATAPM:
3059                         str = "SATA Port Multiplier";
3060                         break;
3061                 default:
3062                         str = "unknown PI bit set";
3063                         break;
3064                 }
3065                 fprintf(stdout, "%s\n", str);
3066         }
3067
3068         for (i = 1; i < 0xff; i = i << 1) {
3069                 const char *str;
3070
3071                 if ((i & cpi->hba_misc) == 0)
3072                         continue;
3073
3074                 fprintf(stdout, "%s ", adapter_str);
3075
3076                 switch(i) {
3077                 case PIM_SCANHILO:
3078                         str = "bus scans from high ID to low ID";
3079                         break;
3080                 case PIM_NOREMOVE:
3081                         str = "removable devices not included in scan";
3082                         break;
3083                 case PIM_NOINITIATOR:
3084                         str = "initiator role not supported";
3085                         break;
3086                 case PIM_NOBUSRESET:
3087                         str = "user has disabled initial BUS RESET or"
3088                               " controller is in target/mixed mode";
3089                         break;
3090                 case PIM_NO_6_BYTE:
3091                         str = "do not send 6-byte commands";
3092                         break;
3093                 case PIM_SEQSCAN:
3094                         str = "scan bus sequentially";
3095                         break;
3096                 default:
3097                         str = "unknown PIM bit set";
3098                         break;
3099                 }
3100                 fprintf(stdout, "%s\n", str);
3101         }
3102
3103         for (i = 1; i < 0xff; i = i << 1) {
3104                 const char *str;
3105
3106                 if ((i & cpi->target_sprt) == 0)
3107                         continue;
3108
3109                 fprintf(stdout, "%s supports ", adapter_str);
3110                 switch(i) {
3111                 case PIT_PROCESSOR:
3112                         str = "target mode processor mode";
3113                         break;
3114                 case PIT_PHASE:
3115                         str = "target mode phase cog. mode";
3116                         break;
3117                 case PIT_DISCONNECT:
3118                         str = "disconnects in target mode";
3119                         break;
3120                 case PIT_TERM_IO:
3121                         str = "terminate I/O message in target mode";
3122                         break;
3123                 case PIT_GRP_6:
3124                         str = "group 6 commands in target mode";
3125                         break;
3126                 case PIT_GRP_7:
3127                         str = "group 7 commands in target mode";
3128                         break;
3129                 default:
3130                         str = "unknown PIT bit set";
3131                         break;
3132                 }
3133
3134                 fprintf(stdout, "%s\n", str);
3135         }
3136         fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3137                 cpi->hba_eng_cnt);
3138         fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3139                 cpi->max_target);
3140         fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3141                 cpi->max_lun);
3142         fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3143                 adapter_str, cpi->hpath_id);
3144         fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3145                 cpi->initiator_id);
3146         fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3147         fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3148         fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
3149             adapter_str, cpi->hba_vendor);
3150         fprintf(stdout, "%s HBA device ID: 0x%04x\n",
3151             adapter_str, cpi->hba_device);
3152         fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
3153             adapter_str, cpi->hba_subvendor);
3154         fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
3155             adapter_str, cpi->hba_subdevice);
3156         fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3157         fprintf(stdout, "%s base transfer speed: ", adapter_str);
3158         if (cpi->base_transfer_speed > 1000)
3159                 fprintf(stdout, "%d.%03dMB/sec\n",
3160                         cpi->base_transfer_speed / 1000,
3161                         cpi->base_transfer_speed % 1000);
3162         else
3163                 fprintf(stdout, "%dKB/sec\n",
3164                         (cpi->base_transfer_speed % 1000) * 1000);
3165         fprintf(stdout, "%s maximum transfer size: %u bytes\n",
3166             adapter_str, cpi->maxio);
3167 }
3168
3169 static int
3170 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3171               struct ccb_trans_settings *cts)
3172 {
3173         int retval;
3174         union ccb *ccb;
3175
3176         retval = 0;
3177         ccb = cam_getccb(device);
3178
3179         if (ccb == NULL) {
3180                 warnx("get_print_cts: error allocating ccb");
3181                 return(1);
3182         }
3183
3184         bzero(&(&ccb->ccb_h)[1],
3185               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3186
3187         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3188
3189         if (user_settings == 0)
3190                 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3191         else
3192                 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3193
3194         if (cam_send_ccb(device, ccb) < 0) {
3195                 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3196                 if (arglist & CAM_ARG_VERBOSE)
3197                         cam_error_print(device, ccb, CAM_ESF_ALL,
3198                                         CAM_EPF_ALL, stderr);
3199                 retval = 1;
3200                 goto get_print_cts_bailout;
3201         }
3202
3203         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3204                 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3205                 if (arglist & CAM_ARG_VERBOSE)
3206                         cam_error_print(device, ccb, CAM_ESF_ALL,
3207                                         CAM_EPF_ALL, stderr);
3208                 retval = 1;
3209                 goto get_print_cts_bailout;
3210         }
3211
3212         if (quiet == 0)
3213                 cts_print(device, &ccb->cts);
3214
3215         if (cts != NULL)
3216                 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3217
3218 get_print_cts_bailout:
3219
3220         cam_freeccb(ccb);
3221
3222         return(retval);
3223 }
3224
3225 static int
3226 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3227             int argc, char **argv, char *combinedopt)
3228 {
3229         int c;
3230         union ccb *ccb;
3231         int user_settings = 0;
3232         int retval = 0;
3233         int disc_enable = -1, tag_enable = -1;
3234         int mode = -1;
3235         int offset = -1;
3236         double syncrate = -1;
3237         int bus_width = -1;
3238         int quiet = 0;
3239         int change_settings = 0, send_tur = 0;
3240         struct ccb_pathinq cpi;
3241
3242         ccb = cam_getccb(device);
3243         if (ccb == NULL) {
3244                 warnx("ratecontrol: error allocating ccb");
3245                 return(1);
3246         }
3247         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3248                 switch(c){
3249                 case 'a':
3250                         send_tur = 1;
3251                         break;
3252                 case 'c':
3253                         user_settings = 0;
3254                         break;
3255                 case 'D':
3256                         if (strncasecmp(optarg, "enable", 6) == 0)
3257                                 disc_enable = 1;
3258                         else if (strncasecmp(optarg, "disable", 7) == 0)
3259                                 disc_enable = 0;
3260                         else {
3261                                 warnx("-D argument \"%s\" is unknown", optarg);
3262                                 retval = 1;
3263                                 goto ratecontrol_bailout;
3264                         }
3265                         change_settings = 1;
3266                         break;
3267                 case 'M':
3268                         mode = ata_string2mode(optarg);
3269                         if (mode < 0) {
3270                                 warnx("unknown mode '%s'", optarg);
3271                                 retval = 1;
3272                                 goto ratecontrol_bailout;
3273                         }
3274                         change_settings = 1;
3275                         break;
3276                 case 'O':
3277                         offset = strtol(optarg, NULL, 0);
3278                         if (offset < 0) {
3279                                 warnx("offset value %d is < 0", offset);
3280                                 retval = 1;
3281                                 goto ratecontrol_bailout;
3282                         }
3283                         change_settings = 1;
3284                         break;
3285                 case 'q':
3286                         quiet++;
3287                         break;
3288                 case 'R':
3289                         syncrate = atof(optarg);
3290                         if (syncrate < 0) {
3291                                 warnx("sync rate %f is < 0", syncrate);
3292                                 retval = 1;
3293                                 goto ratecontrol_bailout;
3294                         }
3295                         change_settings = 1;
3296                         break;
3297                 case 'T':
3298                         if (strncasecmp(optarg, "enable", 6) == 0)
3299                                 tag_enable = 1;
3300                         else if (strncasecmp(optarg, "disable", 7) == 0)
3301                                 tag_enable = 0;
3302                         else {
3303                                 warnx("-T argument \"%s\" is unknown", optarg);
3304                                 retval = 1;
3305                                 goto ratecontrol_bailout;
3306                         }
3307                         change_settings = 1;
3308                         break;
3309                 case 'U':
3310                         user_settings = 1;
3311                         break;
3312                 case 'W':
3313                         bus_width = strtol(optarg, NULL, 0);
3314                         if (bus_width < 0) {
3315                                 warnx("bus width %d is < 0", bus_width);
3316                                 retval = 1;
3317                                 goto ratecontrol_bailout;
3318                         }
3319                         change_settings = 1;
3320                         break;
3321                 default:
3322                         break;
3323                 }
3324         }
3325         bzero(&(&ccb->ccb_h)[1],
3326               sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3327         /*
3328          * Grab path inquiry information, so we can determine whether
3329          * or not the initiator is capable of the things that the user
3330          * requests.
3331          */
3332         ccb->ccb_h.func_code = XPT_PATH_INQ;
3333         if (cam_send_ccb(device, ccb) < 0) {
3334                 perror("error sending XPT_PATH_INQ CCB");
3335                 if (arglist & CAM_ARG_VERBOSE) {
3336                         cam_error_print(device, ccb, CAM_ESF_ALL,
3337                                         CAM_EPF_ALL, stderr);
3338                 }
3339                 retval = 1;
3340                 goto ratecontrol_bailout;
3341         }
3342         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3343                 warnx("XPT_PATH_INQ CCB failed");
3344                 if (arglist & CAM_ARG_VERBOSE) {
3345                         cam_error_print(device, ccb, CAM_ESF_ALL,
3346                                         CAM_EPF_ALL, stderr);
3347                 }
3348                 retval = 1;
3349                 goto ratecontrol_bailout;
3350         }
3351         bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3352         bzero(&(&ccb->ccb_h)[1],
3353               sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3354         if (quiet == 0) {
3355                 fprintf(stdout, "%s parameters:\n",
3356                     user_settings ? "User" : "Current");
3357         }
3358         retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3359         if (retval != 0)
3360                 goto ratecontrol_bailout;
3361
3362         if (arglist & CAM_ARG_VERBOSE)
3363                 cpi_print(&cpi);
3364
3365         if (change_settings) {
3366                 int didsettings = 0;
3367                 struct ccb_trans_settings_spi *spi = NULL;
3368                 struct ccb_trans_settings_ata *ata = NULL;
3369                 struct ccb_trans_settings_sata *sata = NULL;
3370                 struct ccb_trans_settings_scsi *scsi = NULL;
3371
3372                 if (ccb->cts.transport == XPORT_SPI)
3373                         spi = &ccb->cts.xport_specific.spi;
3374                 if (ccb->cts.transport == XPORT_ATA)
3375                         ata = &ccb->cts.xport_specific.ata;
3376                 if (ccb->cts.transport == XPORT_SATA)
3377                         sata = &ccb->cts.xport_specific.sata;
3378                 if (ccb->cts.protocol == PROTO_SCSI)
3379                         scsi = &ccb->cts.proto_specific.scsi;
3380                 ccb->cts.xport_specific.valid = 0;
3381                 ccb->cts.proto_specific.valid = 0;
3382                 if (spi && disc_enable != -1) {
3383                         spi->valid |= CTS_SPI_VALID_DISC;
3384                         if (disc_enable == 0)
3385                                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3386                         else
3387                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3388                 }
3389                 if (scsi && tag_enable != -1) {
3390                         if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3391                                 warnx("HBA does not support tagged queueing, "
3392                                       "so you cannot modify tag settings");
3393                                 retval = 1;
3394                                 goto ratecontrol_bailout;
3395                         }
3396                         scsi->valid |= CTS_SCSI_VALID_TQ;
3397                         if (tag_enable == 0)
3398                                 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3399                         else
3400                                 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3401                         didsettings++;
3402                 }
3403                 if (spi && offset != -1) {
3404                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3405                                 warnx("HBA is not capable of changing offset");
3406                                 retval = 1;
3407                                 goto ratecontrol_bailout;
3408                         }
3409                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3410                         spi->sync_offset = offset;
3411                         didsettings++;
3412                 }
3413                 if (spi && syncrate != -1) {
3414                         int prelim_sync_period;
3415                         u_int freq;
3416
3417                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3418                                 warnx("HBA is not capable of changing "
3419                                       "transfer rates");
3420                                 retval = 1;
3421                                 goto ratecontrol_bailout;
3422                         }
3423                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3424                         /*
3425                          * The sync rate the user gives us is in MHz.
3426                          * We need to translate it into KHz for this
3427                          * calculation.
3428                          */
3429                         syncrate *= 1000;
3430                         /*
3431                          * Next, we calculate a "preliminary" sync period
3432                          * in tenths of a nanosecond.
3433                          */
3434                         if (syncrate == 0)
3435                                 prelim_sync_period = 0;
3436                         else
3437                                 prelim_sync_period = 10000000 / syncrate;
3438                         spi->sync_period =
3439                                 scsi_calc_syncparam(prelim_sync_period);
3440                         freq = scsi_calc_syncsrate(spi->sync_period);
3441                         didsettings++;
3442                 }
3443                 if (sata && syncrate != -1) {
3444                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3445                                 warnx("HBA is not capable of changing "
3446                                       "transfer rates");
3447                                 retval = 1;
3448                                 goto ratecontrol_bailout;
3449                         }
3450                         sata->revision = ata_speed2revision(syncrate * 100);
3451                         if (sata->revision < 0) {
3452                                 warnx("Invalid rate %f", syncrate);
3453                                 retval = 1;
3454                                 goto ratecontrol_bailout;
3455                         }
3456                         sata->valid |= CTS_SATA_VALID_REVISION;
3457                         didsettings++;
3458                 }
3459                 if ((ata || sata) && mode != -1) {
3460                         if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3461                                 warnx("HBA is not capable of changing "
3462                                       "transfer rates");
3463                                 retval = 1;
3464                                 goto ratecontrol_bailout;
3465                         }
3466                         if (ata) {
3467                                 ata->mode = mode;
3468                                 ata->valid |= CTS_ATA_VALID_MODE;
3469                         } else {
3470                                 sata->mode = mode;
3471                                 sata->valid |= CTS_SATA_VALID_MODE;
3472                         }
3473                         didsettings++;
3474                 }
3475                 /*
3476                  * The bus_width argument goes like this:
3477                  * 0 == 8 bit
3478                  * 1 == 16 bit
3479                  * 2 == 32 bit
3480                  * Therefore, if you shift the number of bits given on the
3481                  * command line right by 4, you should get the correct
3482                  * number.
3483                  */
3484                 if (spi && bus_width != -1) {
3485                         /*
3486                          * We might as well validate things here with a
3487                          * decipherable error message, rather than what
3488                          * will probably be an indecipherable error message
3489                          * by the time it gets back to us.
3490                          */
3491                         if ((bus_width == 16)
3492                          && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3493                                 warnx("HBA does not support 16 bit bus width");
3494                                 retval = 1;
3495                                 goto ratecontrol_bailout;
3496                         } else if ((bus_width == 32)
3497                                 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3498                                 warnx("HBA does not support 32 bit bus width");
3499                                 retval = 1;
3500                                 goto ratecontrol_bailout;
3501                         } else if ((bus_width != 8)
3502                                 && (bus_width != 16)
3503                                 && (bus_width != 32)) {
3504                                 warnx("Invalid bus width %d", bus_width);
3505                                 retval = 1;
3506                                 goto ratecontrol_bailout;
3507                         }
3508                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3509                         spi->bus_width = bus_width >> 4;
3510                         didsettings++;
3511                 }
3512                 if  (didsettings == 0) {
3513                         goto ratecontrol_bailout;
3514                 }
3515                 if  (!user_settings && (ata || sata)) {
3516                         warnx("You can modify only user settings for ATA/SATA");
3517                         retval = 1;
3518                         goto ratecontrol_bailout;
3519                 }
3520                 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3521                 if (cam_send_ccb(device, ccb) < 0) {
3522                         perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3523                         if (arglist & CAM_ARG_VERBOSE) {
3524                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3525                                                 CAM_EPF_ALL, stderr);
3526                         }
3527                         retval = 1;
3528                         goto ratecontrol_bailout;
3529                 }
3530                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3531                         warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3532                         if (arglist & CAM_ARG_VERBOSE) {
3533                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3534                                                 CAM_EPF_ALL, stderr);
3535                         }
3536                         retval = 1;
3537                         goto ratecontrol_bailout;
3538                 }
3539         }
3540         if (send_tur) {
3541                 retval = testunitready(device, retry_count, timeout,
3542                                        (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3543                 /*
3544                  * If the TUR didn't succeed, just bail.
3545                  */
3546                 if (retval != 0) {
3547                         if (quiet == 0)
3548                                 fprintf(stderr, "Test Unit Ready failed\n");
3549                         goto ratecontrol_bailout;
3550                 }
3551                 /*
3552                  * If the user wants things quiet, there's no sense in
3553                  * getting the transfer settings, if we're not going
3554                  * to print them.
3555                  */
3556                 if (quiet != 0)
3557                         goto ratecontrol_bailout;
3558                 fprintf(stdout, "New parameters:\n");
3559                 retval = get_print_cts(device, user_settings, 0, NULL);
3560         }
3561
3562 ratecontrol_bailout:
3563         cam_freeccb(ccb);
3564         return(retval);
3565 }
3566
3567 static int
3568 scsiformat(struct cam_device *device, int argc, char **argv,
3569            char *combinedopt, int retry_count, int timeout)
3570 {
3571         union ccb *ccb;
3572         int c;
3573         int ycount = 0, quiet = 0;
3574         int error = 0, response = 0, retval = 0;
3575         int use_timeout = 10800 * 1000;
3576         int immediate = 1;
3577         struct format_defect_list_header fh;
3578         u_int8_t *data_ptr = NULL;
3579         u_int32_t dxfer_len = 0;
3580         u_int8_t byte2 = 0;
3581         int num_warnings = 0;
3582         int reportonly = 0;
3583
3584         ccb = cam_getccb(device);
3585
3586         if (ccb == NULL) {
3587                 warnx("scsiformat: error allocating ccb");
3588                 return(1);
3589         }
3590
3591         bzero(&(&ccb->ccb_h)[1],
3592               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3593
3594         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3595                 switch(c) {
3596                 case 'q':
3597                         quiet++;
3598                         break;
3599                 case 'r':
3600                         reportonly = 1;
3601                         break;
3602                 case 'w':
3603                         immediate = 0;
3604                         break;
3605                 case 'y':
3606                         ycount++;
3607                         break;
3608                 }
3609         }
3610
3611         if (reportonly)
3612                 goto doreport;
3613
3614         if (quiet == 0) {
3615                 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3616                         "following device:\n");
3617
3618                 error = scsidoinquiry(device, argc, argv, combinedopt,
3619                                       retry_count, timeout);
3620
3621                 if (error != 0) {
3622                         warnx("scsiformat: error sending inquiry");
3623                         goto scsiformat_bailout;
3624                 }
3625         }
3626
3627         if (ycount == 0) {
3628
3629                 do {
3630                         char str[1024];
3631
3632                         fprintf(stdout, "Are you SURE you want to do "
3633                                 "this? (yes/no) ");
3634
3635                         if (fgets(str, sizeof(str), stdin) != NULL) {
3636
3637                                 if (strncasecmp(str, "yes", 3) == 0)
3638                                         response = 1;
3639                                 else if (strncasecmp(str, "no", 2) == 0)
3640                                         response = -1;
3641                                 else {
3642                                         fprintf(stdout, "Please answer"
3643                                                 " \"yes\" or \"no\"\n");
3644                                 }
3645                         }
3646                 } while (response == 0);
3647
3648                 if (response == -1) {
3649                         error = 1;
3650                         goto scsiformat_bailout;
3651                 }
3652         }
3653
3654         if (timeout != 0)
3655                 use_timeout = timeout;
3656
3657         if (quiet == 0) {
3658                 fprintf(stdout, "Current format timeout is %d seconds\n",
3659                         use_timeout / 1000);
3660         }
3661
3662         /*
3663          * If the user hasn't disabled questions and didn't specify a
3664          * timeout on the command line, ask them if they want the current
3665          * timeout.
3666          */
3667         if ((ycount == 0)
3668          && (timeout == 0)) {
3669                 char str[1024];
3670                 int new_timeout = 0;
3671
3672                 fprintf(stdout, "Enter new timeout in seconds or press\n"
3673                         "return to keep the current timeout [%d] ",
3674                         use_timeout / 1000);
3675
3676                 if (fgets(str, sizeof(str), stdin) != NULL) {
3677                         if (str[0] != '\0')
3678                                 new_timeout = atoi(str);
3679                 }
3680
3681                 if (new_timeout != 0) {
3682                         use_timeout = new_timeout * 1000;
3683                         fprintf(stdout, "Using new timeout value %d\n",
3684                                 use_timeout / 1000);
3685                 }
3686         }
3687
3688         /*
3689          * Keep this outside the if block below to silence any unused
3690          * variable warnings.
3691          */
3692         bzero(&fh, sizeof(fh));
3693
3694         /*
3695          * If we're in immediate mode, we've got to include the format
3696          * header
3697          */
3698         if (immediate != 0) {
3699                 fh.byte2 = FU_DLH_IMMED;
3700                 data_ptr = (u_int8_t *)&fh;
3701                 dxfer_len = sizeof(fh);
3702                 byte2 = FU_FMT_DATA;
3703         } else if (quiet == 0) {
3704                 fprintf(stdout, "Formatting...");
3705                 fflush(stdout);
3706         }
3707
3708         scsi_format_unit(&ccb->csio,
3709                          /* retries */ retry_count,
3710                          /* cbfcnp */ NULL,
3711                          /* tag_action */ MSG_SIMPLE_Q_TAG,
3712                          /* byte2 */ byte2,
3713                          /* ileave */ 0,
3714                          /* data_ptr */ data_ptr,
3715                          /* dxfer_len */ dxfer_len,
3716                          /* sense_len */ SSD_FULL_SIZE,
3717                          /* timeout */ use_timeout);
3718
3719         /* Disable freezing the device queue */
3720         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3721
3722         if (arglist & CAM_ARG_ERR_RECOVER)
3723                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3724
3725         if (((retval = cam_send_ccb(device, ccb)) < 0)
3726          || ((immediate == 0)
3727            && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3728                 const char errstr[] = "error sending format command";
3729
3730                 if (retval < 0)
3731                         warn(errstr);
3732                 else
3733                         warnx(errstr);
3734
3735                 if (arglist & CAM_ARG_VERBOSE) {
3736                         cam_error_print(device, ccb, CAM_ESF_ALL,
3737                                         CAM_EPF_ALL, stderr);
3738                 }
3739                 error = 1;
3740                 goto scsiformat_bailout;
3741         }
3742
3743         /*
3744          * If we ran in non-immediate mode, we already checked for errors
3745          * above and printed out any necessary information.  If we're in
3746          * immediate mode, we need to loop through and get status
3747          * information periodically.
3748          */
3749         if (immediate == 0) {
3750                 if (quiet == 0) {
3751                         fprintf(stdout, "Format Complete\n");
3752                 }
3753                 goto scsiformat_bailout;
3754         }
3755
3756 doreport:
3757         do {
3758                 cam_status status;
3759
3760                 bzero(&(&ccb->ccb_h)[1],
3761                       sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3762
3763                 /*
3764                  * There's really no need to do error recovery or
3765                  * retries here, since we're just going to sit in a
3766                  * loop and wait for the device to finish formatting.
3767                  */
3768                 scsi_test_unit_ready(&ccb->csio,
3769                                      /* retries */ 0,
3770                                      /* cbfcnp */ NULL,
3771                                      /* tag_action */ MSG_SIMPLE_Q_TAG,
3772                                      /* sense_len */ SSD_FULL_SIZE,
3773                                      /* timeout */ 5000);
3774
3775                 /* Disable freezing the device queue */
3776                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3777
3778                 retval = cam_send_ccb(device, ccb);
3779
3780                 /*
3781                  * If we get an error from the ioctl, bail out.  SCSI
3782                  * errors are expected.
3783                  */
3784                 if (retval < 0) {
3785                         warn("error sending CAMIOCOMMAND ioctl");
3786                         if (arglist & CAM_ARG_VERBOSE) {
3787                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3788                                                 CAM_EPF_ALL, stderr);
3789                         }
3790                         error = 1;
3791                         goto scsiformat_bailout;
3792                 }
3793
3794                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3795
3796                 if ((status != CAM_REQ_CMP)
3797                  && (status == CAM_SCSI_STATUS_ERROR)
3798                  && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3799                         struct scsi_sense_data *sense;
3800                         int error_code, sense_key, asc, ascq;
3801
3802                         sense = &ccb->csio.sense_data;
3803                         scsi_extract_sense_len(sense, ccb->csio.sense_len -
3804                             ccb->csio.sense_resid, &error_code, &sense_key,
3805                             &asc, &ascq, /*show_errors*/ 1);
3806
3807                         /*
3808                          * According to the SCSI-2 and SCSI-3 specs, a
3809                          * drive that is in the middle of a format should
3810                          * return NOT READY with an ASC of "logical unit
3811                          * not ready, format in progress".  The sense key
3812                          * specific bytes will then be a progress indicator.
3813                          */
3814                         if ((sense_key == SSD_KEY_NOT_READY)
3815                          && (asc == 0x04) && (ascq == 0x04)) {
3816                                 uint8_t sks[3];
3817
3818                                 if ((scsi_get_sks(sense, ccb->csio.sense_len -
3819                                      ccb->csio.sense_resid, sks) == 0)
3820                                  && (quiet == 0)) {
3821                                         int val;
3822                                         u_int64_t percentage;
3823
3824                                         val = scsi_2btoul(&sks[1]);
3825                                         percentage = 10000 * val;
3826
3827                                         fprintf(stdout,
3828                                                 "\rFormatting:  %ju.%02u %% "
3829                                                 "(%d/%d) done",
3830                                                 (uintmax_t)(percentage /
3831                                                 (0x10000 * 100)),
3832                                                 (unsigned)((percentage /
3833                                                 0x10000) % 100),
3834                                                 val, 0x10000);
3835                                         fflush(stdout);
3836                                 } else if ((quiet == 0)
3837                                         && (++num_warnings <= 1)) {
3838                                         warnx("Unexpected SCSI Sense Key "
3839                                               "Specific value returned "
3840                                               "during format:");
3841                                         scsi_sense_print(device, &ccb->csio,
3842                                                          stderr);
3843                                         warnx("Unable to print status "
3844                                               "information, but format will "
3845                                               "proceed.");
3846                                         warnx("will exit when format is "
3847                                               "complete");
3848                                 }
3849                                 sleep(1);
3850                         } else {
3851                                 warnx("Unexpected SCSI error during format");
3852                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3853                                                 CAM_EPF_ALL, stderr);
3854                                 error = 1;
3855                                 goto scsiformat_bailout;
3856                         }
3857
3858                 } else if (status != CAM_REQ_CMP) {
3859                         warnx("Unexpected CAM status %#x", status);
3860                         if (arglist & CAM_ARG_VERBOSE)
3861                                 cam_error_print(device, ccb, CAM_ESF_ALL,
3862                                                 CAM_EPF_ALL, stderr);
3863                         error = 1;
3864                         goto scsiformat_bailout;
3865                 }
3866
3867         } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3868
3869         if (quiet == 0)
3870                 fprintf(stdout, "\nFormat Complete\n");
3871
3872 scsiformat_bailout:
3873
3874         cam_freeccb(ccb);
3875
3876         return(error);
3877 }
3878
3879 static int
3880 scsireportluns(struct cam_device *device, int argc, char **argv,
3881                char *combinedopt, int retry_count, int timeout)
3882 {
3883         union ccb *ccb;
3884         int c, countonly, lunsonly;
3885         struct scsi_report_luns_data *lundata;
3886         int alloc_len;
3887         uint8_t report_type;
3888         uint32_t list_len, i, j;
3889         int retval;
3890
3891         retval = 0;
3892         lundata = NULL;
3893         report_type = RPL_REPORT_DEFAULT;
3894         ccb = cam_getccb(device);
3895
3896         if (ccb == NULL) {
3897                 warnx("%s: error allocating ccb", __func__);
3898                 return (1);
3899         }
3900
3901         bzero(&(&ccb->ccb_h)[1],
3902               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3903
3904         countonly = 0;
3905         lunsonly = 0;
3906
3907         while ((c = getopt(argc, argv, combinedopt)) != -1) {
3908                 switch (c) {
3909                 case 'c':
3910                         countonly++;
3911                         break;
3912                 case 'l':
3913                         lunsonly++;
3914                         break;
3915                 case 'r':
3916                         if (strcasecmp(optarg, "default") == 0)
3917                                 report_type = RPL_REPORT_DEFAULT;
3918                         else if (strcasecmp(optarg, "wellknown") == 0)
3919                                 report_type = RPL_REPORT_WELLKNOWN;
3920                         else if (strcasecmp(optarg, "all") == 0)
3921                                 report_type = RPL_REPORT_ALL;
3922                         else {
3923                                 warnx("%s: invalid report type \"%s\"",
3924                                       __func__, optarg);
3925                                 retval = 1;
3926                                 goto bailout;
3927                         }
3928                         break;
3929                 default:
3930                         break;
3931                 }
3932         }
3933
3934         if ((countonly != 0)
3935          && (lunsonly != 0)) {
3936                 warnx("%s: you can only specify one of -c or -l", __func__);
3937                 retval = 1;
3938                 goto bailout;
3939         }
3940         /*
3941          * According to SPC-4, the allocation length must be at least 16
3942          * bytes -- enough for the header and one LUN.
3943          */
3944         alloc_len = sizeof(*lundata) + 8;
3945
3946 retry:
3947
3948         lundata = malloc(alloc_len);
3949
3950         if (lundata == NULL) {
3951                 warn("%s: error mallocing %d bytes", __func__, alloc_len);
3952                 retval = 1;
3953                 goto bailout;
3954         }
3955
3956         scsi_report_luns(&ccb->csio,
3957                          /*retries*/ retry_count,
3958                          /*cbfcnp*/ NULL,
3959                          /*tag_action*/ MSG_SIMPLE_Q_TAG,
3960                          /*select_report*/ report_type,
3961                          /*rpl_buf*/ lundata,
3962                          /*alloc_len*/ alloc_len,
3963                          /*sense_len*/ SSD_FULL_SIZE,
3964                          /*timeout*/ timeout ? timeout : 5000);
3965
3966         /* Disable freezing the device queue */
3967         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3968
3969         if (arglist & CAM_ARG_ERR_RECOVER)
3970                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3971
3972         if (cam_send_ccb(device, ccb) < 0) {
3973                 warn("error sending REPORT LUNS command");
3974
3975                 if (arglist & CAM_ARG_VERBOSE)
3976                         cam_error_print(device, ccb, CAM_ESF_ALL,
3977                                         CAM_EPF_ALL, stderr);
3978
3979                 retval = 1;
3980                 goto bailout;
3981         }
3982
3983         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3984                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3985                 retval = 1;
3986                 goto bailout;
3987         }
3988
3989
3990         list_len = scsi_4btoul(lundata->length);
3991
3992         /*
3993          * If we need to list the LUNs, and our allocation
3994          * length was too short, reallocate and retry.
3995          */
3996         if ((countonly == 0)
3997          && (list_len > (alloc_len - sizeof(*lundata)))) {
3998                 alloc_len = list_len + sizeof(*lundata);
3999                 free(lundata);
4000                 goto retry;
4001         }
4002
4003         if (lunsonly == 0)
4004                 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
4005                         ((list_len / 8) > 1) ? "s" : "");
4006
4007         if (countonly != 0)
4008                 goto bailout;
4009
4010         for (i = 0; i < (list_len / 8); i++) {
4011                 int no_more;
4012
4013                 no_more = 0;
4014                 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4015                         if (j != 0)
4016                                 fprintf(stdout, ",");
4017                         switch (lundata->luns[i].lundata[j] &
4018                                 RPL_LUNDATA_ATYP_MASK) {
4019                         case RPL_LUNDATA_ATYP_PERIPH:
4020                                 if ((lundata->luns[i].lundata[j] &
4021                                     RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4022                                         fprintf(stdout, "%d:",
4023                                                 lundata->luns[i].lundata[j] &
4024                                                 RPL_LUNDATA_PERIPH_BUS_MASK);
4025                                 else if ((j == 0)
4026                                       && ((lundata->luns[i].lundata[j+2] &
4027                                           RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4028                                         no_more = 1;
4029
4030                                 fprintf(stdout, "%d",
4031                                         lundata->luns[i].lundata[j+1]);
4032                                 break;
4033                         case RPL_LUNDATA_ATYP_FLAT: {
4034                                 uint8_t tmplun[2];
4035                                 tmplun[0] = lundata->luns[i].lundata[j] &
4036                                         RPL_LUNDATA_FLAT_LUN_MASK;
4037                                 tmplun[1] = lundata->luns[i].lundata[j+1];
4038
4039                                 fprintf(stdout, "%d", scsi_2btoul(tmplun));
4040                                 no_more = 1;
4041                                 break;
4042                         }
4043                         case RPL_LUNDATA_ATYP_LUN:
4044                                 fprintf(stdout, "%d:%d:%d",
4045                                         (lundata->luns[i].lundata[j+1] &
4046                                         RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4047                                         lundata->luns[i].lundata[j] &
4048                                         RPL_LUNDATA_LUN_TARG_MASK,
4049                                         lundata->luns[i].lundata[j+1] &
4050                                         RPL_LUNDATA_LUN_LUN_MASK);
4051                                 break;
4052                         case RPL_LUNDATA_ATYP_EXTLUN: {
4053                                 int field_len, field_len_code, eam_code;
4054
4055                                 eam_code = lundata->luns[i].lundata[j] &
4056                                         RPL_LUNDATA_EXT_EAM_MASK;
4057                                 field_len_code = (lundata->luns[i].lundata[j] &
4058                                         RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4059                                 field_len = field_len_code * 2;
4060
4061                                 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4062                                  && (field_len_code == 0x00)) {
4063                                         fprintf(stdout, "%d",
4064                                                 lundata->luns[i].lundata[j+1]);
4065                                 } else if ((eam_code ==
4066                                             RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4067                                         && (field_len_code == 0x03)) {
4068                                         uint8_t tmp_lun[8];
4069
4070                                         /*
4071                                          * This format takes up all 8 bytes.
4072                                          * If we aren't starting at offset 0,
4073                                          * that's a bug.
4074                                          */
4075                                         if (j != 0) {
4076                                                 fprintf(stdout, "Invalid "
4077                                                         "offset %d for "
4078                                                         "Extended LUN not "
4079                                                         "specified format", j);
4080                                                 no_more = 1;
4081                                                 break;
4082                                         }
4083                                         bzero(tmp_lun, sizeof(tmp_lun));
4084                                         bcopy(&lundata->luns[i].lundata[j+1],
4085                                               &tmp_lun[1], sizeof(tmp_lun) - 1);
4086                                         fprintf(stdout, "%#jx",
4087                                                (intmax_t)scsi_8btou64(tmp_lun));
4088                                         no_more = 1;
4089                                 } else {
4090                                         fprintf(stderr, "Unknown Extended LUN"
4091                                                 "Address method %#x, length "
4092                                                 "code %#x", eam_code,
4093                                                 field_len_code);
4094                                         no_more = 1;
4095                                 }
4096                                 break;
4097                         }
4098                         default:
4099                                 fprintf(stderr, "Unknown LUN address method "
4100                                         "%#x\n", lundata->luns[i].lundata[0] &
4101                                         RPL_LUNDATA_ATYP_MASK);
4102                                 break;
4103                         }
4104                         /*
4105                          * For the flat addressing method, there are no
4106                          * other levels after it.
4107                          */
4108                         if (no_more != 0)
4109                                 break;
4110                 }
4111                 fprintf(stdout, "\n");
4112         }
4113
4114 bailout:
4115
4116         cam_freeccb(ccb);
4117
4118         free(lundata);
4119
4120         return (retval);
4121 }
4122
4123 static int
4124 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4125                  char *combinedopt, int retry_count, int timeout)
4126 {
4127         union ccb *ccb;
4128         int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4129         struct scsi_read_capacity_data rcap;
4130         struct scsi_read_capacity_data_long rcaplong;
4131         uint64_t maxsector;
4132         uint32_t block_len;
4133         int retval;
4134         int c;
4135
4136         blocksizeonly = 0;
4137         humanize = 0;
4138         numblocks = 0;
4139         quiet = 0;
4140         sizeonly = 0;
4141         baseten = 0;
4142         retval = 0;
4143
4144         ccb = cam_getccb(device);
4145
4146         if (ccb == NULL) {
4147                 warnx("%s: error allocating ccb", __func__);
4148                 return (1);
4149         }
4150
4151         bzero(&(&ccb->ccb_h)[1],
4152               sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4153
4154         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4155                 switch (c) {
4156                 case 'b':
4157                         blocksizeonly++;
4158                         break;
4159                 case 'h':
4160                         humanize++;
4161                         baseten = 0;
4162                         break;
4163                 case 'H':
4164                         humanize++;
4165                         baseten++;
4166                         break;
4167                 case 'N':
4168                         numblocks++;
4169                         break;
4170                 case 'q':
4171                         quiet++;
4172                         break;
4173                 case 's':
4174                         sizeonly++;
4175                         break;
4176                 default:
4177                         break;
4178                 }
4179         }
4180
4181         if ((blocksizeonly != 0)
4182          && (numblocks != 0)) {
4183                 warnx("%s: you can only specify one of -b or -N", __func__);
4184                 retval = 1;
4185                 goto bailout;
4186         }
4187
4188         if ((blocksizeonly != 0)
4189          && (sizeonly != 0)) {
4190                 warnx("%s: you can only specify one of -b or -s", __func__);
4191                 retval = 1;
4192                 goto bailout;
4193         }
4194
4195         if ((humanize != 0)
4196          && (quiet != 0)) {
4197                 warnx("%s: you can only specify one of -h/-H or -q", __func__);
4198                 retval = 1;
4199                 goto bailout;
4200         }
4201
4202         if ((humanize != 0)
4203          && (blocksizeonly != 0)) {
4204                 warnx("%s: you can only specify one of -h/-H or -b", __func__);
4205                 retval = 1;
4206                 goto bailout;
4207         }
4208
4209         scsi_read_capacity(&ccb->csio,
4210                            /*retries*/ retry_count,
4211                            /*cbfcnp*/ NULL,
4212                            /*tag_action*/ MSG_SIMPLE_Q_TAG,
4213                            &rcap,
4214                            SSD_FULL_SIZE,
4215                            /*timeout*/ timeout ? timeout : 5000);
4216
4217         /* Disable freezing the device queue */
4218         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4219
4220         if (arglist & CAM_ARG_ERR_RECOVER)
4221                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4222
4223         if (cam_send_ccb(device, ccb) < 0) {
4224                 warn("error sending READ CAPACITY command");
4225
4226                 if (arglist & CAM_ARG_VERBOSE)
4227                         cam_error_print(device, ccb, CAM_ESF_ALL,
4228                                         CAM_EPF_ALL, stderr);
4229
4230                 retval = 1;
4231                 goto bailout;
4232         }
4233
4234         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4235                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4236                 retval = 1;
4237                 goto bailout;
4238         }
4239
4240         maxsector = scsi_4btoul(rcap.addr);
4241         block_len = scsi_4btoul(rcap.length);
4242
4243         /*
4244          * A last block of 2^32-1 means that the true capacity is over 2TB,
4245          * and we need to issue the long READ CAPACITY to get the real
4246          * capacity.  Otherwise, we're all set.
4247          */
4248         if (maxsector != 0xffffffff)
4249                 goto do_print;
4250
4251         scsi_read_capacity_16(&ccb->csio,
4252                               /*retries*/ retry_count,
4253                               /*cbfcnp*/ NULL,
4254                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
4255                               /*lba*/ 0,
4256                               /*reladdr*/ 0,
4257                               /*pmi*/ 0,
4258                               &rcaplong,
4259                               /*sense_len*/ SSD_FULL_SIZE,
4260                               /*timeout*/ timeout ? timeout : 5000);
4261
4262         /* Disable freezing the device queue */
4263         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4264
4265         if (arglist & CAM_ARG_ERR_RECOVER)
4266                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4267
4268         if (cam_send_ccb(device, ccb) < 0) {
4269                 warn("error sending READ CAPACITY (16) command");
4270
4271                 if (arglist & CAM_ARG_VERBOSE)
4272                         cam_error_print(device, ccb, CAM_ESF_ALL,
4273                                         CAM_EPF_ALL, stderr);
4274
4275                 retval = 1;
4276                 goto bailout;
4277         }
4278
4279         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4280                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4281                 retval = 1;
4282                 goto bailout;
4283         }
4284
4285         maxsector = scsi_8btou64(rcaplong.addr);
4286         block_len = scsi_4btoul(rcaplong.length);
4287
4288 do_print:
4289         if (blocksizeonly == 0) {
4290                 /*
4291                  * Humanize implies !quiet, and also implies numblocks.
4292                  */
4293                 if (humanize != 0) {
4294                         char tmpstr[6];
4295                         int64_t tmpbytes;
4296                         int ret;
4297
4298                         tmpbytes = (maxsector + 1) * block_len;
4299                         ret = humanize_number(tmpstr, sizeof(tmpstr),
4300                                               tmpbytes, "", HN_AUTOSCALE,
4301                                               HN_B | HN_DECIMAL |
4302                                               ((baseten != 0) ?
4303                                               HN_DIVISOR_1000 : 0));
4304                         if (ret == -1) {
4305                                 warnx("%s: humanize_number failed!", __func__);
4306                                 retval = 1;
4307                                 goto bailout;
4308                         }
4309                         fprintf(stdout, "Device Size: %s%s", tmpstr,
4310                                 (sizeonly == 0) ?  ", " : "\n");
4311                 } else if (numblocks != 0) {
4312                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4313                                 "Blocks: " : "", (uintmax_t)maxsector + 1,
4314                                 (sizeonly == 0) ? ", " : "\n");
4315                 } else {
4316                         fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4317                                 "Last Block: " : "", (uintmax_t)maxsector,
4318                                 (sizeonly == 0) ? ", " : "\n");
4319                 }
4320         }
4321         if (sizeonly == 0)
4322                 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4323                         "Block Length: " : "", block_len, (quiet == 0) ?
4324                         " bytes" : "");
4325 bailout:
4326         cam_freeccb(ccb);
4327
4328         return (retval);
4329 }
4330
4331 static int
4332 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4333        int retry_count, int timeout)
4334 {
4335         int c, error;
4336         union ccb *ccb;
4337         uint8_t *smp_request = NULL, *smp_response = NULL;
4338         int request_size = 0, response_size = 0;
4339         int fd_request = 0, fd_response = 0;
4340         char *datastr = NULL;
4341         struct get_hook hook;
4342         int retval;
4343         int flags = 0;
4344
4345         /*
4346          * Note that at the moment we don't support sending SMP CCBs to
4347          * devices that aren't probed by CAM.
4348          */
4349         ccb = cam_getccb(device);
4350         if (ccb == NULL) {
4351                 warnx("%s: error allocating CCB", __func__);
4352                 return (1);
4353         }
4354
4355         bzero(&(&ccb->ccb_h)[1],
4356               sizeof(union ccb) - sizeof(struct ccb_hdr));
4357
4358         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4359                 switch (c) {
4360                 case 'R':
4361                         arglist |= CAM_ARG_CMD_IN;
4362                         response_size = strtol(optarg, NULL, 0);
4363                         if (response_size <= 0) {
4364                                 warnx("invalid number of response bytes %d",
4365                                       response_size);
4366                                 error = 1;
4367                                 goto smpcmd_bailout;
4368                         }
4369                         hook.argc = argc - optind;
4370                         hook.argv = argv + optind;
4371                         hook.got = 0;
4372                         optind++;
4373                         datastr = cget(&hook, NULL);
4374                         /*
4375                          * If the user supplied "-" instead of a format, he
4376                          * wants the data to be written to stdout.
4377                          */
4378                         if ((datastr != NULL)
4379                          && (datastr[0] == '-'))
4380                                 fd_response = 1;
4381
4382                         smp_response = (u_int8_t *)malloc(response_size);
4383                         if (smp_response == NULL) {
4384                                 warn("can't malloc memory for SMP response");
4385                                 error = 1;
4386                                 goto smpcmd_bailout;
4387                         }
4388                         break;
4389                 case 'r':
4390                         arglist |= CAM_ARG_CMD_OUT;
4391                         request_size = strtol(optarg, NULL, 0);
4392                         if (request_size <= 0) {
4393                                 warnx("invalid number of request bytes %d",
4394                                       request_size);
4395                                 error = 1;
4396                                 goto smpcmd_bailout;
4397                         }
4398                         hook.argc = argc - optind;
4399                         hook.argv = argv + optind;
4400                         hook.got = 0;
4401                         datastr = cget(&hook, NULL);
4402                         smp_request = (u_int8_t *)malloc(request_size);
4403                         if (smp_request == NULL) {
4404                                 warn("can't malloc memory for SMP request");
4405                                 error = 1;
4406                                 goto smpcmd_bailout;
4407                         }
4408                         bzero(smp_request, request_size);
4409                         /*
4410                          * If the user supplied "-" instead of a format, he
4411                          * wants the data to be read from stdin.
4412                          */
4413                         if ((datastr != NULL)
4414                          && (datastr[0] == '-'))
4415                                 fd_request = 1;
4416                         else
4417                                 buff_encode_visit(smp_request, request_size,
4418                                                   datastr,
4419                                                   iget, &hook);
4420                         optind += hook.got;
4421                         break;
4422                 default:
4423                         break;
4424                 }
4425         }
4426
4427         /*
4428          * If fd_data is set, and we're writing to the device, we need to
4429          * read the data the user wants written from stdin.
4430          */
4431         if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4432                 ssize_t amt_read;
4433                 int amt_to_read = request_size;
4434                 u_int8_t *buf_ptr = smp_request;
4435
4436                 for (amt_read = 0; amt_to_read > 0;
4437                      amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4438                         if (amt_read == -1) {
4439                                 warn("error reading data from stdin");
4440                                 error = 1;
4441                                 goto smpcmd_bailout;
4442                         }
4443                         amt_to_read -= amt_read;
4444                         buf_ptr += amt_read;
4445                 }
4446         }
4447
4448         if (((arglist & CAM_ARG_CMD_IN) == 0)
4449          || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
4450                 warnx("%s: need both the request (-r) and response (-R) "
4451                       "arguments", __func__);
4452                 error = 1;
4453                 goto smpcmd_bailout;
4454         }
4455
4456         flags |= CAM_DEV_QFRZDIS;
4457
4458         cam_fill_smpio(&ccb->smpio,
4459                        /*retries*/ retry_count,
4460                        /*cbfcnp*/ NULL,
4461                        /*flags*/ flags,
4462                        /*smp_request*/ smp_request,
4463                        /*smp_request_len*/ request_size,
4464                        /*smp_response*/ smp_response,
4465                        /*smp_response_len*/ response_size,
4466                        /*timeout*/ timeout ? timeout : 5000);
4467
4468         ccb->smpio.flags = SMP_FLAG_NONE;
4469
4470         if (((retval = cam_send_ccb(device, ccb)) < 0)
4471          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4472                 const char *warnstr = "error sending command";
4473
4474                 if (retval < 0)
4475                         warn(warnstr);
4476                 else
4477                         warnx(warnstr);
4478
4479                 if (arglist & CAM_ARG_VERBOSE) {
4480                         cam_error_print(device, ccb, CAM_ESF_ALL,
4481                                         CAM_EPF_ALL, stderr);
4482                 }
4483         }
4484
4485         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4486          && (response_size > 0)) {
4487                 if (fd_response == 0) {
4488                         buff_decode_visit(smp_response, response_size,
4489                                           datastr, arg_put, NULL);
4490                         fprintf(stdout, "\n");
4491                 } else {
4492                         ssize_t amt_written;
4493                         int amt_to_write = response_size;
4494                         u_int8_t *buf_ptr = smp_response;
4495
4496                         for (amt_written = 0; (amt_to_write > 0) &&
4497                              (amt_written = write(STDOUT_FILENO, buf_ptr,
4498                                                   amt_to_write)) > 0;){
4499                                 amt_to_write -= amt_written;
4500                                 buf_ptr += amt_written;
4501                         }
4502                         if (amt_written == -1) {
4503                                 warn("error writing data to stdout");
4504                                 error = 1;
4505                                 goto smpcmd_bailout;
4506                         } else if ((amt_written == 0)
4507                                 && (amt_to_write > 0)) {
4508                                 warnx("only wrote %u bytes out of %u",
4509                                       response_size - amt_to_write, 
4510                                       response_size);
4511                         }
4512                 }
4513         }
4514 smpcmd_bailout:
4515         if (ccb != NULL)
4516                 cam_freeccb(ccb);
4517
4518         if (smp_request != NULL)
4519                 free(smp_request);
4520
4521         if (smp_response != NULL)
4522                 free(smp_response);
4523
4524         return (error);
4525 }
4526
4527 static int
4528 smpreportgeneral(struct cam_device *device, int argc, char **argv,
4529                  char *combinedopt, int retry_count, int timeout)
4530 {
4531         union ccb *ccb;
4532         struct smp_report_general_request *request = NULL;
4533         struct smp_report_general_response *response = NULL;
4534         struct sbuf *sb = NULL;
4535         int error = 0;
4536         int c, long_response = 0;
4537         int retval;
4538
4539         /*
4540          * Note that at the moment we don't support sending SMP CCBs to
4541          * devices that aren't probed by CAM.
4542          */
4543         ccb = cam_getccb(device);
4544         if (ccb == NULL) {
4545                 warnx("%s: error allocating CCB", __func__);
4546                 return (1);
4547         }
4548
4549         bzero(&(&ccb->ccb_h)[1],
4550               sizeof(union ccb) - sizeof(struct ccb_hdr));
4551
4552         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4553                 switch (c) {
4554                 case 'l':
4555                         long_response = 1;
4556                         break;
4557                 default:
4558                         break;
4559                 }
4560         }
4561         request = malloc(sizeof(*request));
4562         if (request == NULL) {
4563                 warn("%s: unable to allocate %zd bytes", __func__,
4564                      sizeof(*request));
4565                 error = 1;
4566                 goto bailout;
4567         }
4568
4569         response = malloc(sizeof(*response));
4570         if (response == NULL) {
4571                 warn("%s: unable to allocate %zd bytes", __func__,
4572                      sizeof(*response));
4573                 error = 1;
4574                 goto bailout;
4575         }
4576
4577 try_long:
4578         smp_report_general(&ccb->smpio,
4579                            retry_count,
4580                            /*cbfcnp*/ NULL,
4581                            request,
4582                            /*request_len*/ sizeof(*request),
4583                            (uint8_t *)response,
4584                            /*response_len*/ sizeof(*response),
4585                            /*long_response*/ long_response,
4586                            timeout);
4587
4588         if (((retval = cam_send_ccb(device, ccb)) < 0)
4589          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4590                 const char *warnstr = "error sending command";
4591
4592                 if (retval < 0)
4593                         warn(warnstr);
4594                 else
4595                         warnx(warnstr);
4596
4597                 if (arglist & CAM_ARG_VERBOSE) {
4598                         cam_error_print(device, ccb, CAM_ESF_ALL,
4599                                         CAM_EPF_ALL, stderr);
4600                 }
4601                 error = 1;
4602                 goto bailout;
4603         }
4604
4605         /*
4606          * If the device supports the long response bit, try again and see
4607          * if we can get all of the data.
4608          */
4609         if ((response->long_response & SMP_RG_LONG_RESPONSE)
4610          && (long_response == 0)) {
4611                 ccb->ccb_h.status = CAM_REQ_INPROG;
4612                 bzero(&(&ccb->ccb_h)[1],
4613                       sizeof(union ccb) - sizeof(struct ccb_hdr));
4614                 long_response = 1;
4615                 goto try_long;
4616         }
4617
4618         /*
4619          * XXX KDM detect and decode SMP errors here.
4620          */
4621         sb = sbuf_new_auto();
4622         if (sb == NULL) {
4623                 warnx("%s: error allocating sbuf", __func__);
4624                 goto bailout;
4625         }
4626
4627         smp_report_general_sbuf(response, sizeof(*response), sb);
4628
4629         sbuf_finish(sb);
4630
4631         printf("%s", sbuf_data(sb));
4632
4633 bailout:
4634         if (ccb != NULL)
4635                 cam_freeccb(ccb);
4636
4637         if (request != NULL)
4638                 free(request);
4639
4640         if (response != NULL)
4641                 free(response);
4642
4643         if (sb != NULL)
4644                 sbuf_delete(sb);
4645
4646         return (error);
4647 }
4648
4649 struct camcontrol_opts phy_ops[] = {
4650         {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
4651         {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
4652         {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
4653         {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
4654         {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
4655         {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
4656         {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
4657         {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
4658         {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
4659         {NULL, 0, 0, NULL}
4660 };
4661
4662 static int
4663 smpphycontrol(struct cam_device *device, int argc, char **argv,
4664               char *combinedopt, int retry_count, int timeout)
4665 {
4666         union ccb *ccb;
4667         struct smp_phy_control_request *request = NULL;
4668         struct smp_phy_control_response *response = NULL;
4669         int long_response = 0;
4670         int retval = 0;
4671         int phy = -1;
4672         uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
4673         int phy_op_set = 0;
4674         uint64_t attached_dev_name = 0;
4675         int dev_name_set = 0;
4676         uint32_t min_plr = 0, max_plr = 0;
4677         uint32_t pp_timeout_val = 0;
4678         int slumber_partial = 0;
4679         int set_pp_timeout_val = 0;
4680         int c;
4681
4682         /*
4683          * Note that at the moment we don't support sending SMP CCBs to
4684          * devices that aren't probed by CAM.
4685          */
4686         ccb = cam_getccb(device);
4687         if (ccb == NULL) {
4688                 warnx("%s: error allocating CCB", __func__);
4689                 return (1);
4690         }
4691
4692         bzero(&(&ccb->ccb_h)[1],
4693               sizeof(union ccb) - sizeof(struct ccb_hdr));
4694
4695         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4696                 switch (c) {
4697                 case 'a':
4698                 case 'A':
4699                 case 's':
4700                 case 'S': {
4701                         int enable = -1;
4702
4703                         if (strcasecmp(optarg, "enable") == 0)
4704                                 enable = 1;
4705                         else if (strcasecmp(optarg, "disable") == 0)
4706                                 enable = 2;
4707                         else {
4708                                 warnx("%s: Invalid argument %s", __func__,
4709                                       optarg);
4710                                 retval = 1;
4711                                 goto bailout;
4712                         }
4713                         switch (c) {
4714                         case 's':
4715                                 slumber_partial |= enable <<
4716                                                    SMP_PC_SAS_SLUMBER_SHIFT;
4717                                 break;
4718                         case 'S':
4719                                 slumber_partial |= enable <<
4720                                                    SMP_PC_SAS_PARTIAL_SHIFT;
4721                                 break;
4722                         case 'a':
4723                                 slumber_partial |= enable <<
4724                                                    SMP_PC_SATA_SLUMBER_SHIFT;
4725                                 break;
4726                         case 'A':
4727                                 slumber_partial |= enable <<
4728                                                    SMP_PC_SATA_PARTIAL_SHIFT;
4729                                 break;
4730                         default:
4731                                 warnx("%s: programmer error", __func__);
4732                                 retval = 1;
4733                                 goto bailout;
4734                                 break; /*NOTREACHED*/
4735                         }
4736                         break;
4737                 }
4738                 case 'd':
4739                         attached_dev_name = (uintmax_t)strtoumax(optarg,
4740                                                                  NULL,0);
4741                         dev_name_set = 1;
4742                         break;
4743                 case 'l':
4744                         long_response = 1;
4745                         break;
4746                 case 'm':
4747                         /*
4748                          * We don't do extensive checking here, so this
4749                          * will continue to work when new speeds come out.
4750                          */
4751                         min_plr = strtoul(optarg, NULL, 0);
4752                         if ((min_plr == 0)
4753                          || (min_plr > 0xf)) {
4754                                 warnx("%s: invalid link rate %x",
4755                                       __func__, min_plr);
4756                                 retval = 1;
4757                                 goto bailout;
4758                         }
4759                         break;
4760                 case 'M':
4761                         /*
4762                          * We don't do extensive checking here, so this
4763                          * will continue to work when new speeds come out.
4764                          */
4765                         max_plr = strtoul(optarg, NULL, 0);
4766                         if ((max_plr == 0)
4767                          || (max_plr > 0xf)) {
4768                                 warnx("%s: invalid link rate %x",
4769                                       __func__, max_plr);
4770                                 retval = 1;
4771                                 goto bailout;
4772                         }
4773                         break;
4774                 case 'o': {
4775                         camcontrol_optret optreturn;
4776                         cam_argmask argnums;
4777                         const char *subopt;
4778
4779                         if (phy_op_set != 0) {
4780                                 warnx("%s: only one phy operation argument "
4781                                       "(-o) allowed", __func__);
4782                                 retval = 1;
4783                                 goto bailout;
4784                         }
4785
4786                         phy_op_set = 1;
4787
4788                         /*
4789                          * Allow the user to specify the phy operation
4790                          * numerically, as well as with a name.  This will
4791                          * future-proof it a bit, so options that are added
4792                          * in future specs can be used.
4793                          */
4794                         if (isdigit(optarg[0])) {
4795                                 phy_operation = strtoul(optarg, NULL, 0);
4796                                 if ((phy_operation == 0)
4797                                  || (phy_operation > 0xff)) {
4798                                         warnx("%s: invalid phy operation %#x",
4799                                               __func__, phy_operation);
4800                                         retval = 1;
4801                                         goto bailout;
4802                                 }
4803                                 break;
4804                         }
4805                         optreturn = getoption(phy_ops, optarg, &phy_operation,
4806                                               &argnums, &subopt);
4807
4808                         if (optreturn == CC_OR_AMBIGUOUS) {
4809                                 warnx("%s: ambiguous option %s", __func__,
4810                                       optarg);
4811                                 usage(0);
4812                                 retval = 1;
4813                                 goto bailout;
4814                         } else if (optreturn == CC_OR_NOT_FOUND) {
4815                                 warnx("%s: option %s not found", __func__,
4816                                       optarg);
4817                                 usage(0);
4818                                 retval = 1;
4819                                 goto bailout;
4820                         }
4821                         break;
4822                 }
4823                 case 'p':
4824                         phy = atoi(optarg);
4825                         break;
4826                 case 'T':
4827                         pp_timeout_val = strtoul(optarg, NULL, 0);
4828                         if (pp_timeout_val > 15) {
4829                                 warnx("%s: invalid partial pathway timeout "
4830                                       "value %u, need a value less than 16",
4831                                       __func__, pp_timeout_val);
4832                                 retval = 1;
4833                                 goto bailout;
4834                         }
4835                         set_pp_timeout_val = 1;
4836                         break;
4837                 default:
4838                         break;
4839                 }
4840         }
4841
4842         if (phy == -1) {
4843                 warnx("%s: a PHY (-p phy) argument is required",__func__);
4844                 retval = 1;
4845                 goto bailout;
4846         }
4847
4848         if (((dev_name_set != 0)
4849           && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
4850          || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
4851           && (dev_name_set == 0))) {
4852                 warnx("%s: -d name and -o setdevname arguments both "
4853                       "required to set device name", __func__);
4854                 retval = 1;
4855                 goto bailout;
4856         }
4857
4858         request = malloc(sizeof(*request));
4859         if (request == NULL) {
4860                 warn("%s: unable to allocate %zd bytes", __func__,
4861                      sizeof(*request));
4862                 retval = 1;
4863                 goto bailout;
4864         }
4865
4866         response = malloc(sizeof(*response));
4867         if (response == NULL) {
4868                 warn("%s: unable to allocate %zd bytes", __func__,
4869                      sizeof(*request));
4870                 retval = 1;
4871                 goto bailout;
4872         }
4873
4874         smp_phy_control(&ccb->smpio,
4875                         retry_count,
4876                         /*cbfcnp*/ NULL,
4877                         request,
4878                         sizeof(*request),
4879                         (uint8_t *)response,
4880                         sizeof(*response),
4881                         long_response,
4882                         /*expected_exp_change_count*/ 0,
4883                         phy,
4884                         phy_operation,
4885                         (set_pp_timeout_val != 0) ? 1 : 0,
4886                         attached_dev_name,
4887                         min_plr,
4888                         max_plr,
4889                         slumber_partial,
4890                         pp_timeout_val,
4891                         timeout);
4892
4893         if (((retval = cam_send_ccb(device, ccb)) < 0)
4894          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4895                 const char *warnstr = "error sending command";
4896
4897                 if (retval < 0)
4898                         warn(warnstr);
4899                 else
4900                         warnx(warnstr);
4901
4902                 if (arglist & CAM_ARG_VERBOSE) {
4903                         /*
4904                          * Use CAM_EPF_NORMAL so we only get one line of
4905                          * SMP command decoding.
4906                          */
4907                         cam_error_print(device, ccb, CAM_ESF_ALL,
4908                                         CAM_EPF_NORMAL, stderr);
4909                 }
4910                 retval = 1;
4911                 goto bailout;
4912         }
4913
4914         /* XXX KDM print out something here for success? */
4915 bailout:
4916         if (ccb != NULL)
4917                 cam_freeccb(ccb);
4918
4919         if (request != NULL)
4920                 free(request);
4921
4922         if (response != NULL)
4923                 free(response);
4924
4925         return (retval);
4926 }
4927
4928 static int
4929 smpmaninfo(struct cam_device *device, int argc, char **argv,
4930            char *combinedopt, int retry_count, int timeout)
4931 {
4932         union ccb *ccb;
4933         struct smp_report_manuf_info_request request;
4934         struct smp_report_manuf_info_response response;
4935         struct sbuf *sb = NULL;
4936         int long_response = 0;
4937         int retval = 0;
4938         int c;
4939
4940         /*
4941          * Note that at the moment we don't support sending SMP CCBs to
4942          * devices that aren't probed by CAM.
4943          */
4944         ccb = cam_getccb(device);
4945         if (ccb == NULL) {
4946                 warnx("%s: error allocating CCB", __func__);
4947                 return (1);
4948         }
4949
4950         bzero(&(&ccb->ccb_h)[1],
4951               sizeof(union ccb) - sizeof(struct ccb_hdr));
4952
4953         while ((c = getopt(argc, argv, combinedopt)) != -1) {
4954                 switch (c) {
4955                 case 'l':
4956                         long_response = 1;
4957                         break;
4958                 default:
4959                         break;
4960                 }
4961         }
4962         bzero(&request, sizeof(request));
4963         bzero(&response, sizeof(response));
4964
4965         smp_report_manuf_info(&ccb->smpio,
4966                               retry_count,
4967                               /*cbfcnp*/ NULL,
4968                               &request,
4969                               sizeof(request),
4970                               (uint8_t *)&response,
4971                               sizeof(response),
4972                               long_response,
4973                               timeout);
4974
4975         if (((retval = cam_send_ccb(device, ccb)) < 0)
4976          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4977                 const char *warnstr = "error sending command";
4978
4979                 if (retval < 0)
4980                         warn(warnstr);
4981                 else
4982                         warnx(warnstr);
4983
4984                 if (arglist & CAM_ARG_VERBOSE) {
4985                         cam_error_print(device, ccb, CAM_ESF_ALL,
4986                                         CAM_EPF_ALL, stderr);
4987                 }
4988                 retval = 1;
4989                 goto bailout;
4990         }
4991
4992         sb = sbuf_new_auto();
4993         if (sb == NULL) {
4994                 warnx("%s: error allocating sbuf", __func__);
4995                 goto bailout;
4996         }
4997
4998         smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
4999
5000         sbuf_finish(sb);
5001
5002         printf("%s", sbuf_data(sb));
5003
5004 bailout:
5005
5006         if (ccb != NULL)
5007                 cam_freeccb(ccb);
5008
5009         if (sb != NULL)
5010                 sbuf_delete(sb);
5011
5012         return (retval);
5013 }
5014
5015 static int
5016 getdevid(struct cam_devitem *item)
5017 {
5018         int retval = 0;
5019         union ccb *ccb = NULL;
5020
5021         struct cam_device *dev;
5022
5023         dev = cam_open_btl(item->dev_match.path_id,
5024                            item->dev_match.target_id,
5025                            item->dev_match.target_lun, O_RDWR, NULL);
5026
5027         if (dev == NULL) {
5028                 warnx("%s", cam_errbuf);
5029                 retval = 1;
5030                 goto bailout;
5031         }
5032
5033         item->device_id_len = 0;
5034
5035         ccb = cam_getccb(dev);
5036         if (ccb == NULL) {
5037                 warnx("%s: error allocating CCB", __func__);
5038                 retval = 1;
5039                 goto bailout;
5040         }
5041
5042         bzero(&(&ccb->ccb_h)[1],
5043               sizeof(union ccb) - sizeof(struct ccb_hdr));
5044
5045         /*
5046          * On the first try, we just probe for the size of the data, and
5047          * then allocate that much memory and try again.
5048          */
5049 retry:
5050         ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
5051         ccb->ccb_h.flags = CAM_DIR_IN;
5052         ccb->cdai.flags = 0;
5053         ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
5054         ccb->cdai.bufsiz = item->device_id_len;
5055         if (item->device_id_len != 0)
5056                 ccb->cdai.buf = (uint8_t *)item->device_id;
5057
5058         if (cam_send_ccb(dev, ccb) < 0) {
5059                 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
5060                 retval = 1;
5061                 goto bailout;
5062         }
5063
5064         if (ccb->ccb_h.status != CAM_REQ_CMP) {
5065                 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
5066                 retval = 1;
5067                 goto bailout;
5068         }
5069
5070         if (item->device_id_len == 0) {
5071                 /*
5072                  * This is our first time through.  Allocate the buffer,
5073                  * and then go back to get the data.
5074                  */
5075                 if (ccb->cdai.provsiz == 0) {
5076                         warnx("%s: invalid .provsiz field returned with "
5077                              "XPT_GDEV_ADVINFO CCB", __func__);
5078                         retval = 1;
5079                         goto bailout;
5080                 }
5081                 item->device_id_len = ccb->cdai.provsiz;
5082                 item->device_id = malloc(item->device_id_len);
5083                 if (item->device_id == NULL) {
5084                         warn("%s: unable to allocate %d bytes", __func__,
5085                              item->device_id_len);
5086                         retval = 1;
5087                         goto bailout;
5088                 }
5089                 ccb->ccb_h.status = CAM_REQ_INPROG;
5090                 goto retry;
5091         }
5092
5093 bailout:
5094         if (dev != NULL)
5095                 cam_close_device(dev);
5096
5097         if (ccb != NULL)
5098                 cam_freeccb(ccb);
5099
5100         return (retval);
5101 }
5102
5103 /*
5104  * XXX KDM merge this code with getdevtree()?
5105  */
5106 static int
5107 buildbusdevlist(struct cam_devlist *devlist)
5108 {
5109         union ccb ccb;
5110         int bufsize, fd = -1;
5111         struct dev_match_pattern *patterns;
5112         struct cam_devitem *item = NULL;
5113         int skip_device = 0;
5114         int retval = 0;
5115
5116         if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
5117                 warn("couldn't open %s", XPT_DEVICE);
5118                 return(1);
5119         }
5120
5121         bzero(&ccb, sizeof(union ccb));
5122
5123         ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
5124         ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
5125         ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
5126
5127         ccb.ccb_h.func_code = XPT_DEV_MATCH;
5128         bufsize = sizeof(struct dev_match_result) * 100;
5129         ccb.cdm.match_buf_len = bufsize;
5130         ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
5131         if (ccb.cdm.matches == NULL) {
5132                 warnx("can't malloc memory for matches");
5133                 close(fd);
5134                 return(1);
5135         }
5136         ccb.cdm.num_matches = 0;
5137         ccb.cdm.num_patterns = 2;
5138         ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
5139                 ccb.cdm.num_patterns;
5140
5141         patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
5142         if (patterns == NULL) {
5143                 warnx("can't malloc memory for patterns");
5144                 retval = 1;
5145                 goto bailout;
5146         }
5147
5148         ccb.cdm.patterns = patterns;
5149         bzero(patterns, ccb.cdm.pattern_buf_len);
5150
5151         patterns[0].type = DEV_MATCH_DEVICE;
5152         patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
5153         patterns[0].pattern.device_pattern.path_id = devlist->path_id;
5154         patterns[1].type = DEV_MATCH_PERIPH;
5155         patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
5156         patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
5157
5158         /*
5159          * We do the ioctl multiple times if necessary, in case there are
5160          * more than 100 nodes in the EDT.
5161          */
5162         do {
5163                 unsigned int i;
5164
5165                 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
5166                         warn("error sending CAMIOCOMMAND ioctl");
5167                         retval = 1;
5168                         goto bailout;
5169                 }
5170
5171                 if ((ccb.ccb_h.status != CAM_REQ_CMP)
5172                  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
5173                     && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
5174                         warnx("got CAM error %#x, CDM error %d\n",
5175                               ccb.ccb_h.status, ccb.cdm.status);
5176                         retval = 1;
5177                         goto bailout;
5178                 }
5179
5180                 for (i = 0; i < ccb.cdm.num_matches; i++) {
5181                         switch (ccb.cdm.matches[i].type) {
5182                         case DEV_MATCH_DEVICE: {
5183                                 struct device_match_result *dev_result;
5184
5185                                 dev_result = 
5186                                      &ccb.cdm.matches[i].result.device_result;
5187
5188                                 if (dev_result->flags &
5189                                     DEV_RESULT_UNCONFIGURED) {
5190                                         skip_device = 1;
5191                                         break;
5192                                 } else
5193                                         skip_device = 0;
5194
5195                                 item = malloc(sizeof(*item));
5196                                 if (item == NULL) {
5197                                         warn("%s: unable to allocate %zd bytes",
5198                                              __func__, sizeof(*item));
5199                                         retval = 1;
5200                                         goto bailout;
5201                                 }
5202                                 bzero(item, sizeof(*item));
5203                                 bcopy(dev_result, &item->dev_match,
5204                                       sizeof(*dev_result));
5205                                 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
5206                                                    links);
5207
5208                                 if (getdevid(item) != 0) {
5209                                         retval = 1;
5210                                         goto bailout;
5211                                 }
5212                                 break;
5213                         }
5214                         case DEV_MATCH_PERIPH: {
5215                                 struct periph_match_result *periph_result;
5216
5217                                 periph_result =
5218                                       &ccb.cdm.matches[i].result.periph_result;
5219
5220                                 if (skip_device != 0)
5221                                         break;
5222                                 item->num_periphs++;
5223                                 item->periph_matches = realloc(
5224                                         item->periph_matches,
5225                                         item->num_periphs *
5226                                         sizeof(struct periph_match_result));
5227                                 if (item->periph_matches == NULL) {
5228                                         warn("%s: error allocating periph "
5229                                              "list", __func__);
5230                                         retval = 1;
5231                                         goto bailout;
5232                                 }
5233                                 bcopy(periph_result, &item->periph_matches[
5234                                       item->num_periphs - 1],
5235                                       sizeof(*periph_result));
5236                                 break;
5237                         }
5238                         default:
5239                                 fprintf(stderr, "%s: unexpected match "
5240                                         "type %d\n", __func__,
5241                                         ccb.cdm.matches[i].type);
5242                                 retval = 1;
5243                                 goto bailout;
5244                                 break; /*NOTREACHED*/
5245                         }
5246                 }
5247         } while ((ccb.ccb_h.status == CAM_REQ_CMP)
5248                 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
5249 bailout:
5250
5251         if (fd != -1)
5252                 close(fd);
5253
5254         free(patterns);
5255
5256         free(ccb.cdm.matches);
5257
5258         if (retval != 0)
5259                 freebusdevlist(devlist);
5260
5261         return (retval);
5262 }
5263
5264 static void
5265 freebusdevlist(struct cam_devlist *devlist)
5266 {
5267         struct cam_devitem *item, *item2;
5268
5269         STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
5270                 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
5271                               links);
5272                 free(item->device_id);
5273                 free(item->periph_matches);
5274                 free(item);
5275         }
5276 }
5277
5278 static struct cam_devitem *
5279 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
5280 {
5281         struct cam_devitem *item;
5282
5283         STAILQ_FOREACH(item, &devlist->dev_queue, links) {
5284                 uint8_t *item_addr;
5285
5286                 /*
5287                  * XXX KDM look for LUN IDs as well?
5288                  */
5289                 item_addr = scsi_get_devid(item->device_id,
5290                                            item->device_id_len,
5291                                            scsi_devid_is_sas_target);
5292                 if (item_addr == NULL)
5293                         continue;
5294
5295                 if (scsi_8btou64(item_addr) == sasaddr)
5296                         return (item);
5297         }
5298
5299         return (NULL);
5300 }
5301
5302 static int
5303 smpphylist(struct cam_device *device, int argc, char **argv,
5304            char *combinedopt, int retry_count, int timeout)
5305 {
5306         struct smp_report_general_request *rgrequest = NULL;
5307         struct smp_report_general_response *rgresponse = NULL;
5308         struct smp_discover_request *disrequest = NULL;
5309         struct smp_discover_response *disresponse = NULL;
5310         struct cam_devlist devlist;
5311         union ccb *ccb;
5312         int long_response = 0;
5313         int num_phys = 0;
5314         int quiet = 0;
5315         int retval;
5316         int i, c;
5317
5318         /*
5319          * Note that at the moment we don't support sending SMP CCBs to
5320          * devices that aren't probed by CAM.
5321          */
5322         ccb = cam_getccb(device);
5323         if (ccb == NULL) {
5324                 warnx("%s: error allocating CCB", __func__);
5325                 return (1);
5326         }
5327
5328         bzero(&(&ccb->ccb_h)[1],
5329               sizeof(union ccb) - sizeof(struct ccb_hdr));
5330
5331         rgrequest = malloc(sizeof(*rgrequest));
5332         if (rgrequest == NULL) {
5333                 warn("%s: unable to allocate %zd bytes", __func__,
5334                      sizeof(*rgrequest));
5335                 retval = 1;
5336                 goto bailout;
5337         }
5338
5339         rgresponse = malloc(sizeof(*rgresponse));
5340         if (rgresponse == NULL) {
5341                 warn("%s: unable to allocate %zd bytes", __func__,
5342                      sizeof(*rgresponse));
5343                 retval = 1;
5344                 goto bailout;
5345         }
5346
5347         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5348                 switch (c) {
5349                 case 'l':
5350                         long_response = 1;
5351                         break;
5352                 case 'q':
5353                         quiet = 1;
5354                         break;
5355                 default:
5356                         break;
5357                 }
5358         }
5359
5360         smp_report_general(&ccb->smpio,
5361                            retry_count,
5362                            /*cbfcnp*/ NULL,
5363                            rgrequest,
5364                            /*request_len*/ sizeof(*rgrequest),
5365                            (uint8_t *)rgresponse,
5366                            /*response_len*/ sizeof(*rgresponse),
5367                            /*long_response*/ long_response,
5368                            timeout);
5369
5370         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5371
5372         if (((retval = cam_send_ccb(device, ccb)) < 0)
5373          || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5374                 const char *warnstr = "error sending command";
5375
5376                 if (retval < 0)
5377                         warn(warnstr);
5378                 else
5379                         warnx(warnstr);
5380
5381                 if (arglist & CAM_ARG_VERBOSE) {
5382                         cam_error_print(device, ccb, CAM_ESF_ALL,
5383                                         CAM_EPF_ALL, stderr);
5384                 }
5385                 retval = 1;
5386                 goto bailout;
5387         }
5388
5389         num_phys = rgresponse->num_phys;
5390
5391         if (num_phys == 0) {
5392                 if (quiet == 0)
5393                         fprintf(stdout, "%s: No Phys reported\n", __func__);
5394                 retval = 1;
5395                 goto bailout;
5396         }
5397
5398         STAILQ_INIT(&devlist.dev_queue);
5399         devlist.path_id = device->path_id;
5400
5401         retval = buildbusdevlist(&devlist);
5402         if (retval != 0)
5403                 goto bailout;
5404
5405         if (quiet == 0) {
5406                 fprintf(stdout, "%d PHYs:\n", num_phys);
5407                 fprintf(stdout, "PHY  Attached SAS Address\n");
5408         }
5409
5410         disrequest = malloc(sizeof(*disrequest));
5411         if (disrequest == NULL) {
5412                 warn("%s: unable to allocate %zd bytes", __func__,
5413                      sizeof(*disrequest));
5414                 retval = 1;
5415                 goto bailout;
5416         }
5417
5418         disresponse = malloc(sizeof(*disresponse));
5419         if (disresponse == NULL) {
5420                 warn("%s: unable to allocate %zd bytes", __func__,
5421                      sizeof(*disresponse));
5422                 retval = 1;
5423                 goto bailout;
5424         }
5425
5426         for (i = 0; i < num_phys; i++) {
5427                 struct cam_devitem *item;
5428                 struct device_match_result *dev_match;
5429                 char vendor[16], product[48], revision[16];
5430                 char tmpstr[256];
5431                 int j;
5432
5433                 bzero(&(&ccb->ccb_h)[1],
5434                       sizeof(union ccb) - sizeof(struct ccb_hdr));
5435
5436                 ccb->ccb_h.status = CAM_REQ_INPROG;
5437                 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5438
5439                 smp_discover(&ccb->smpio,
5440                              retry_count,
5441                              /*cbfcnp*/ NULL,
5442                              disrequest,
5443                              sizeof(*disrequest),
5444                              (uint8_t *)disresponse,
5445                              sizeof(*disresponse),
5446                              long_response,
5447                              /*ignore_zone_group*/ 0,
5448                              /*phy*/ i,
5449                              timeout);
5450
5451                 if (((retval = cam_send_ccb(device, ccb)) < 0)
5452                  || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
5453                   && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
5454                         const char *warnstr = "error sending command";
5455
5456                         if (retval < 0)
5457                                 warn(warnstr);
5458                         else
5459                                 warnx(warnstr);
5460
5461                         if (arglist & CAM_ARG_VERBOSE) {
5462                                 cam_error_print(device, ccb, CAM_ESF_ALL,
5463                                                 CAM_EPF_ALL, stderr);
5464                         }
5465                         retval = 1;
5466                         goto bailout;
5467                 }
5468
5469                 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
5470                         if (quiet == 0)
5471                                 fprintf(stdout, "%3d  <vacant>\n", i);
5472                         continue;
5473                 }
5474
5475                 item = findsasdevice(&devlist,
5476                         scsi_8btou64(disresponse->attached_sas_address));
5477
5478                 if ((quiet == 0)
5479                  || (item != NULL)) {
5480                         fprintf(stdout, "%3d  0x%016jx", i,
5481                                 (uintmax_t)scsi_8btou64(
5482                                 disresponse->attached_sas_address));
5483                         if (item == NULL) {
5484                                 fprintf(stdout, "\n");
5485                                 continue;
5486                         }
5487                 } else if (quiet != 0)
5488                         continue;
5489
5490                 dev_match = &item->dev_match;
5491
5492                 if (dev_match->protocol == PROTO_SCSI) {
5493                         cam_strvis(vendor, dev_match->inq_data.vendor,
5494                                    sizeof(dev_match->inq_data.vendor),
5495                                    sizeof(vendor));
5496                         cam_strvis(product, dev_match->inq_data.product,
5497                                    sizeof(dev_match->inq_data.product),
5498                                    sizeof(product));
5499                         cam_strvis(revision, dev_match->inq_data.revision,
5500                                    sizeof(dev_match->inq_data.revision),
5501                                    sizeof(revision));
5502                         sprintf(tmpstr, "<%s %s %s>", vendor, product,
5503                                 revision);
5504                 } else if ((dev_match->protocol == PROTO_ATA)
5505                         || (dev_match->protocol == PROTO_SATAPM)) {
5506                         cam_strvis(product, dev_match->ident_data.model,
5507                                    sizeof(dev_match->ident_data.model),
5508                                    sizeof(product));
5509                         cam_strvis(revision, dev_match->ident_data.revision,
5510                                    sizeof(dev_match->ident_data.revision),
5511                                    sizeof(revision));
5512                         sprintf(tmpstr, "<%s %s>", product, revision);
5513                 } else {
5514                         sprintf(tmpstr, "<>");
5515                 }
5516                 fprintf(stdout, "   %-33s ", tmpstr);
5517
5518                 /*
5519                  * If we have 0 periphs, that's a bug...
5520                  */
5521                 if (item->num_periphs == 0) {
5522                         fprintf(stdout, "\n");
5523                         continue;
5524                 }
5525
5526                 fprintf(stdout, "(");
5527                 for (j = 0; j < item->num_periphs; j++) {
5528                         if (j > 0)
5529                                 fprintf(stdout, ",");
5530
5531                         fprintf(stdout, "%s%d",
5532                                 item->periph_matches[j].periph_name,
5533                                 item->periph_matches[j].unit_number);
5534                                 
5535                 }
5536                 fprintf(stdout, ")\n");
5537         }
5538 bailout:
5539         if (ccb != NULL)
5540                 cam_freeccb(ccb);
5541
5542         free(rgrequest);
5543
5544         free(rgresponse);
5545
5546         free(disrequest);
5547
5548         free(disresponse);
5549
5550         freebusdevlist(&devlist);
5551
5552         return (retval);
5553 }
5554
5555 static int
5556 atapm(struct cam_device *device, int argc, char **argv,
5557                  char *combinedopt, int retry_count, int timeout)
5558 {
5559         union ccb *ccb;
5560         int retval = 0;
5561         int t = -1;
5562         int c;
5563         u_char cmd, sc;
5564
5565         ccb = cam_getccb(device);
5566
5567         if (ccb == NULL) {
5568                 warnx("%s: error allocating ccb", __func__);
5569                 return (1);
5570         }
5571
5572         while ((c = getopt(argc, argv, combinedopt)) != -1) {
5573                 switch (c) {
5574                 case 't':
5575                         t = atoi(optarg);
5576                         break;
5577                 default:
5578                         break;
5579                 }
5580         }
5581         if (strcmp(argv[1], "idle") == 0) {
5582                 if (t == -1)
5583                         cmd = ATA_IDLE_IMMEDIATE;
5584                 else
5585                         cmd = ATA_IDLE_CMD;
5586         } else if (strcmp(argv[1], "standby") == 0) {
5587                 if (t == -1)
5588                         cmd = ATA_STANDBY_IMMEDIATE;
5589                 else
5590                         cmd = ATA_STANDBY_CMD;
5591         } else {
5592                 cmd = ATA_SLEEP;
5593                 t = -1;
5594         }
5595
5596         if (t < 0)
5597                 sc = 0;
5598         else if (t <= (240 * 5))
5599                 sc = (t + 4) / 5;
5600         else if (t <= (252 * 5))
5601                 /* special encoding for 21 minutes */
5602                 sc = 252;
5603         else if (t <= (11 * 30 * 60))
5604                 sc = (t - 1) / (30 * 60) + 241;
5605         else
5606                 sc = 253;
5607
5608         cam_fill_ataio(&ccb->ataio,
5609                       retry_count,
5610                       NULL,
5611                       /*flags*/CAM_DIR_NONE,
5612                       MSG_SIMPLE_Q_TAG,
5613                       /*data_ptr*/NULL,
5614                       /*dxfer_len*/0,
5615                       timeout ? timeout : 30 * 1000);
5616         ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
5617
5618         /* Disable freezing the device queue */
5619         ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5620
5621         if (arglist & CAM_ARG_ERR_RECOVER)
5622                 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5623
5624         if (cam_send_ccb(device, ccb) < 0) {
5625                 warn("error sending command");
5626
5627                 if (arglist & CAM_ARG_VERBOSE)
5628                         cam_error_print(device, ccb, CAM_ESF_ALL,
5629                                         CAM_EPF_ALL, stderr);
5630
5631                 retval = 1;
5632                 goto bailout;
5633         }
5634
5635         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5636                 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5637                 retval = 1;
5638                 goto bailout;
5639         }
5640 bailout:
5641         cam_freeccb(ccb);
5642         return (retval);
5643 }
5644
5645 #endif /* MINIMALISTIC */
5646
5647 void
5648 usage(int verbose)
5649 {
5650         fprintf(verbose ? stdout : stderr,
5651 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
5652 "        camcontrol devlist    [-v]\n"
5653 #ifndef MINIMALISTIC
5654 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
5655 "        camcontrol tur        [dev_id][generic args]\n"
5656 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
5657 "        camcontrol identify   [dev_id][generic args] [-v]\n"
5658 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
5659 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
5660 "                              [-q] [-s]\n"
5661 "        camcontrol start      [dev_id][generic args]\n"
5662 "        camcontrol stop       [dev_id][generic args]\n"
5663 "        camcontrol load       [dev_id][generic args]\n"
5664 "        camcontrol eject      [dev_id][generic args]\n"
5665 #endif /* MINIMALISTIC */
5666 "        camcontrol rescan     <all | bus[:target:lun]>\n"
5667 "        camcontrol reset      <all | bus[:target:lun]>\n"
5668 #ifndef MINIMALISTIC
5669 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
5670 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
5671 "                              [-P pagectl][-e | -b][-d]\n"
5672 "        camcontrol cmd        [dev_id][generic args]\n"
5673 "                              <-a cmd [args] | -c cmd [args]>\n"
5674 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
5675 "        camcontrol smpcmd     [dev_id][generic args]\n"
5676 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
5677 "        camcontrol smprg      [dev_id][generic args][-l]\n"
5678 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
5679 "                              [-o operation][-d name][-m rate][-M rate]\n"
5680 "                              [-T pp_timeout][-a enable|disable]\n"
5681 "                              [-A enable|disable][-s enable|disable]\n"
5682 "                              [-S enable|disable]\n"
5683 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
5684 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
5685 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
5686 "                              <all|bus[:target[:lun]]|off>\n"
5687 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
5688 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
5689 "                              [-D <enable|disable>][-M mode][-O offset]\n"
5690 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
5691 "                              [-U][-W bus_width]\n"
5692 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
5693 "        camcontrol idle       [dev_id][generic args][-t time]\n"
5694 "        camcontrol standby    [dev_id][generic args][-t time]\n"
5695 "        camcontrol sleep      [dev_id][generic args]\n"
5696 #endif /* MINIMALISTIC */
5697 "        camcontrol help\n");
5698         if (!verbose)
5699                 return;
5700 #ifndef MINIMALISTIC
5701         fprintf(stdout,
5702 "Specify one of the following options:\n"
5703 "devlist     list all CAM devices\n"
5704 "periphlist  list all CAM peripheral drivers attached to a device\n"
5705 "tur         send a test unit ready to the named device\n"
5706 "inquiry     send a SCSI inquiry command to the named device\n"
5707 "identify    send a ATA identify command to the named device\n"
5708 "reportluns  send a SCSI report luns command to the device\n"
5709 "readcap     send a SCSI read capacity command to the device\n"
5710 "start       send a Start Unit command to the device\n"
5711 "stop        send a Stop Unit command to the device\n"
5712 "load        send a Start Unit command to the device with the load bit set\n"
5713 "eject       send a Stop Unit command to the device with the eject bit set\n"
5714 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
5715 "reset       reset all busses, the given bus, or bus:target:lun\n"
5716 "defects     read the defect list of the specified device\n"
5717 "modepage    display or edit (-e) the given mode page\n"
5718 "cmd         send the given SCSI command, may need -i or -o as well\n"
5719 "smpcmd      send the given SMP command, requires -o and -i\n"
5720 "smprg       send the SMP Report General command\n"
5721 "smppc       send the SMP PHY Control command, requires -p\n"
5722 "smpphylist  display phys attached to a SAS expander\n"
5723 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
5724 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
5725 "tags        report or set the number of transaction slots for a device\n"
5726 "negotiate   report or set device negotiation parameters\n"
5727 "format      send the SCSI FORMAT UNIT command to the named device\n"
5728 "idle        send the ATA IDLE command to the named device\n"
5729 "standby     send the ATA STANDBY command to the named device\n"
5730 "sleep       send the ATA SLEEP command to the named device\n"
5731 "help        this message\n"
5732 "Device Identifiers:\n"
5733 "bus:target        specify the bus and target, lun defaults to 0\n"
5734 "bus:target:lun    specify the bus, target and lun\n"
5735 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
5736 "Generic arguments:\n"
5737 "-v                be verbose, print out sense information\n"
5738 "-t timeout        command timeout in seconds, overrides default timeout\n"
5739 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
5740 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
5741 "-E                have the kernel attempt to perform SCSI error recovery\n"
5742 "-C count          specify the SCSI command retry count (needs -E to work)\n"
5743 "modepage arguments:\n"
5744 "-l                list all available mode pages\n"
5745 "-m page           specify the mode page to view or edit\n"
5746 "-e                edit the specified mode page\n"
5747 "-b                force view to binary mode\n"
5748 "-d                disable block descriptors for mode sense\n"
5749 "-P pgctl          page control field 0-3\n"
5750 "defects arguments:\n"
5751 "-f format         specify defect list format (block, bfi or phys)\n"
5752 "-G                get the grown defect list\n"
5753 "-P                get the permanant defect list\n"
5754 "inquiry arguments:\n"
5755 "-D                get the standard inquiry data\n"
5756 "-S                get the serial number\n"
5757 "-R                get the transfer rate, etc.\n"
5758 "reportluns arguments:\n"
5759 "-c                only report a count of available LUNs\n"
5760 "-l                only print out luns, and not a count\n"
5761 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
5762 "readcap arguments\n"
5763 "-b                only report the blocksize\n"
5764 "-h                human readable device size, base 2\n"
5765 "-H                human readable device size, base 10\n"
5766 "-N                print the number of blocks instead of last block\n"
5767 "-q                quiet, print numbers only\n"
5768 "-s                only report the last block/device size\n"
5769 "cmd arguments:\n"
5770 "-c cdb [args]     specify the SCSI CDB\n"
5771 "-i len fmt        specify input data and input data format\n"
5772 "-o len fmt [args] specify output data and output data fmt\n"
5773 "smpcmd arguments:\n"
5774 "-r len fmt [args] specify the SMP command to be sent\n"
5775 "-R len fmt [args] specify SMP response format\n"
5776 "smprg arguments:\n"
5777 "-l                specify the long response format\n"
5778 "smppc arguments:\n"
5779 "-p phy            specify the PHY to operate on\n"
5780 "-l                specify the long request/response format\n"
5781 "-o operation      specify the phy control operation\n"
5782 "-d name           set the attached device name\n"
5783 "-m rate           set the minimum physical link rate\n"
5784 "-M rate           set the maximum physical link rate\n"
5785 "-T pp_timeout     set the partial pathway timeout value\n"
5786 "-a enable|disable enable or disable SATA slumber\n"
5787 "-A enable|disable enable or disable SATA partial phy power\n"
5788 "-s enable|disable enable or disable SAS slumber\n"
5789 "-S enable|disable enable or disable SAS partial phy power\n"
5790 "smpphylist arguments:\n"
5791 "-l                specify the long response format\n"
5792 "-q                only print phys with attached devices\n"
5793 "smpmaninfo arguments:\n"
5794 "-l                specify the long response format\n"
5795 "debug arguments:\n"
5796 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
5797 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
5798 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
5799 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
5800 "tags arguments:\n"
5801 "-N tags           specify the number of tags to use for this device\n"
5802 "-q                be quiet, don't report the number of tags\n"
5803 "-v                report a number of tag-related parameters\n"
5804 "negotiate arguments:\n"
5805 "-a                send a test unit ready after negotiation\n"
5806 "-c                report/set current negotiation settings\n"
5807 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
5808 "-M mode           set ATA mode\n"
5809 "-O offset         set command delay offset\n"
5810 "-q                be quiet, don't report anything\n"
5811 "-R syncrate       synchronization rate in MHz\n"
5812 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
5813 "-U                report/set user negotiation settings\n"
5814 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
5815 "-v                also print a Path Inquiry CCB for the controller\n"
5816 "format arguments:\n"
5817 "-q                be quiet, don't print status messages\n"
5818 "-r                run in report only mode\n"
5819 "-w                don't send immediate format command\n"
5820 "-y                don't ask any questions\n"
5821 "idle/standby arguments:\n"
5822 "-t <arg>          number of seconds before respective state.\n");
5823 #endif /* MINIMALISTIC */
5824 }
5825
5826 int
5827 main(int argc, char **argv)
5828 {
5829         int c;
5830         char *device = NULL;
5831         int unit = 0;
5832         struct cam_device *cam_dev = NULL;
5833         int timeout = 0, retry_count = 1;
5834         camcontrol_optret optreturn;
5835         char *tstr;
5836         const char *mainopt = "C:En:t:u:v";
5837         const char *subopt = NULL;
5838         char combinedopt[256];
5839         int error = 0, optstart = 2;
5840         int devopen = 1;
5841 #ifndef MINIMALISTIC
5842         int bus, target, lun;
5843 #endif /* MINIMALISTIC */
5844
5845         cmdlist = CAM_CMD_NONE;
5846         arglist = CAM_ARG_NONE;
5847
5848         if (argc < 2) {
5849                 usage(0);
5850                 exit(1);
5851         }
5852
5853         /*
5854          * Get the base option.
5855          */
5856         optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
5857
5858         if (optreturn == CC_OR_AMBIGUOUS) {
5859                 warnx("ambiguous option %s", argv[1]);
5860                 usage(0);
5861                 exit(1);
5862         } else if (optreturn == CC_OR_NOT_FOUND) {
5863                 warnx("option %s not found", argv[1]);
5864                 usage(0);
5865                 exit(1);
5866         }
5867
5868         /*
5869          * Ahh, getopt(3) is a pain.
5870          *
5871          * This is a gross hack.  There really aren't many other good
5872          * options (excuse the pun) for parsing options in a situation like
5873          * this.  getopt is kinda braindead, so you end up having to run
5874          * through the options twice, and give each invocation of getopt
5875          * the option string for the other invocation.
5876          *
5877          * You would think that you could just have two groups of options.
5878          * The first group would get parsed by the first invocation of
5879          * getopt, and the second group would get parsed by the second
5880          * invocation of getopt.  It doesn't quite work out that way.  When
5881          * the first invocation of getopt finishes, it leaves optind pointing
5882          * to the argument _after_ the first argument in the second group.
5883          * So when the second invocation of getopt comes around, it doesn't
5884          * recognize the first argument it gets and then bails out.
5885          *
5886          * A nice alternative would be to have a flag for getopt that says
5887          * "just keep parsing arguments even when you encounter an unknown
5888          * argument", but there isn't one.  So there's no real clean way to
5889          * easily parse two sets of arguments without having one invocation
5890          * of getopt know about the other.
5891          *
5892          * Without this hack, the first invocation of getopt would work as
5893          * long as the generic arguments are first, but the second invocation
5894          * (in the subfunction) would fail in one of two ways.  In the case
5895          * where you don't set optreset, it would fail because optind may be
5896          * pointing to the argument after the one it should be pointing at.
5897          * In the case where you do set optreset, and reset optind, it would
5898          * fail because getopt would run into the first set of options, which
5899          * it doesn't understand.
5900          *
5901          * All of this would "sort of" work if you could somehow figure out
5902          * whether optind had been incremented one option too far.  The
5903          * mechanics of that, however, are more daunting than just giving
5904          * both invocations all of the expect options for either invocation.
5905          *
5906          * Needless to say, I wouldn't mind if someone invented a better
5907          * (non-GPL!) command line parsing interface than getopt.  I
5908          * wouldn't mind if someone added more knobs to getopt to make it
5909          * work better.  Who knows, I may talk myself into doing it someday,
5910          * if the standards weenies let me.  As it is, it just leads to
5911          * hackery like this and causes people to avoid it in some cases.
5912          *
5913          * KDM, September 8th, 1998
5914          */
5915         if (subopt != NULL)
5916                 sprintf(combinedopt, "%s%s", mainopt, subopt);
5917         else
5918                 sprintf(combinedopt, "%s", mainopt);
5919
5920         /*
5921          * For these options we do not parse optional device arguments and
5922          * we do not open a passthrough device.
5923          */
5924         if ((cmdlist == CAM_CMD_RESCAN)
5925          || (cmdlist == CAM_CMD_RESET)
5926          || (cmdlist == CAM_CMD_DEVTREE)
5927          || (cmdlist == CAM_CMD_USAGE)
5928          || (cmdlist == CAM_CMD_DEBUG))
5929                 devopen = 0;
5930
5931 #ifndef MINIMALISTIC
5932         if ((devopen == 1)
5933          && (argc > 2 && argv[2][0] != '-')) {
5934                 char name[30];
5935                 int rv;
5936
5937                 if (isdigit(argv[2][0])) {
5938                         /* device specified as bus:target[:lun] */
5939                         rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
5940                         if (rv < 2)
5941                                 errx(1, "numeric device specification must "
5942                                      "be either bus:target, or "
5943                                      "bus:target:lun");
5944                         /* default to 0 if lun was not specified */
5945                         if ((arglist & CAM_ARG_LUN) == 0) {
5946                                 lun = 0;
5947                                 arglist |= CAM_ARG_LUN;
5948                         }
5949                         optstart++;
5950                 } else {
5951                         if (cam_get_device(argv[2], name, sizeof name, &unit)
5952                             == -1)
5953                                 errx(1, "%s", cam_errbuf);
5954                         device = strdup(name);
5955                         arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
5956                         optstart++;
5957                 }
5958         }
5959 #endif /* MINIMALISTIC */
5960         /*
5961          * Start getopt processing at argv[2/3], since we've already
5962          * accepted argv[1..2] as the command name, and as a possible
5963          * device name.
5964          */
5965         optind = optstart;
5966
5967         /*
5968          * Now we run through the argument list looking for generic
5969          * options, and ignoring options that possibly belong to
5970          * subfunctions.
5971          */
5972         while ((c = getopt(argc, argv, combinedopt))!= -1){
5973                 switch(c) {
5974                         case 'C':
5975                                 retry_count = strtol(optarg, NULL, 0);
5976                                 if (retry_count < 0)
5977                                         errx(1, "retry count %d is < 0",
5978                                              retry_count);
5979                                 arglist |= CAM_ARG_RETRIES;
5980                                 break;
5981                         case 'E':
5982                                 arglist |= CAM_ARG_ERR_RECOVER;
5983                                 break;
5984                         case 'n':
5985                                 arglist |= CAM_ARG_DEVICE;
5986                                 tstr = optarg;
5987                                 while (isspace(*tstr) && (*tstr != '\0'))
5988                                         tstr++;
5989                                 device = (char *)strdup(tstr);
5990                                 break;
5991                         case 't':
5992                                 timeout = strtol(optarg, NULL, 0);
5993                                 if (timeout < 0)
5994                                         errx(1, "invalid timeout %d", timeout);
5995                                 /* Convert the timeout from seconds to ms */
5996                                 timeout *= 1000;
5997                                 arglist |= CAM_ARG_TIMEOUT;
5998                                 break;
5999                         case 'u':
6000                                 arglist |= CAM_ARG_UNIT;
6001                                 unit = strtol(optarg, NULL, 0);
6002                                 break;
6003                         case 'v':
6004                                 arglist |= CAM_ARG_VERBOSE;
6005                                 break;
6006                         default:
6007                                 break;
6008                 }
6009         }
6010
6011 #ifndef MINIMALISTIC
6012         /*
6013          * For most commands we'll want to open the passthrough device
6014          * associated with the specified device.  In the case of the rescan
6015          * commands, we don't use a passthrough device at all, just the
6016          * transport layer device.
6017          */
6018         if (devopen == 1) {
6019                 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
6020                  && (((arglist & CAM_ARG_DEVICE) == 0)
6021                   || ((arglist & CAM_ARG_UNIT) == 0))) {
6022                         errx(1, "subcommand \"%s\" requires a valid device "
6023                              "identifier", argv[1]);
6024                 }
6025
6026                 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
6027                                 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
6028                                 cam_open_spec_device(device,unit,O_RDWR,NULL)))
6029                      == NULL)
6030                         errx(1,"%s", cam_errbuf);
6031         }
6032 #endif /* MINIMALISTIC */
6033
6034         /*
6035          * Reset optind to 2, and reset getopt, so these routines can parse
6036          * the arguments again.
6037          */
6038         optind = optstart;
6039         optreset = 1;
6040
6041         switch(cmdlist) {
6042 #ifndef MINIMALISTIC
6043                 case CAM_CMD_DEVLIST:
6044                         error = getdevlist(cam_dev);
6045                         break;
6046 #endif /* MINIMALISTIC */
6047                 case CAM_CMD_DEVTREE:
6048                         error = getdevtree();
6049                         break;
6050 #ifndef MINIMALISTIC
6051                 case CAM_CMD_TUR:
6052                         error = testunitready(cam_dev, retry_count, timeout, 0);
6053                         break;
6054                 case CAM_CMD_INQUIRY:
6055                         error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
6056                                               retry_count, timeout);
6057                         break;
6058                 case CAM_CMD_IDENTIFY:
6059                         error = ataidentify(cam_dev, retry_count, timeout);
6060                         break;
6061                 case CAM_CMD_STARTSTOP:
6062                         error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
6063                                           arglist & CAM_ARG_EJECT, retry_count,
6064                                           timeout);
6065                         break;
6066 #endif /* MINIMALISTIC */
6067                 case CAM_CMD_RESCAN:
6068                         error = dorescan_or_reset(argc, argv, 1);
6069                         break;
6070                 case CAM_CMD_RESET:
6071                         error = dorescan_or_reset(argc, argv, 0);
6072                         break;
6073 #ifndef MINIMALISTIC
6074                 case CAM_CMD_READ_DEFECTS:
6075                         error = readdefects(cam_dev, argc, argv, combinedopt,
6076                                             retry_count, timeout);
6077                         break;
6078                 case CAM_CMD_MODE_PAGE:
6079                         modepage(cam_dev, argc, argv, combinedopt,
6080                                  retry_count, timeout);
6081                         break;
6082                 case CAM_CMD_SCSI_CMD:
6083                         error = scsicmd(cam_dev, argc, argv, combinedopt,
6084                                         retry_count, timeout);
6085                         break;
6086                 case CAM_CMD_SMP_CMD:
6087                         error = smpcmd(cam_dev, argc, argv, combinedopt,
6088                                        retry_count, timeout);
6089                         break;
6090                 case CAM_CMD_SMP_RG:
6091                         error = smpreportgeneral(cam_dev, argc, argv,
6092                                                  combinedopt, retry_count,
6093                                                  timeout);
6094                         break;
6095                 case CAM_CMD_SMP_PC:
6096                         error = smpphycontrol(cam_dev, argc, argv, combinedopt, 
6097                                               retry_count, timeout);
6098                         break;
6099                 case CAM_CMD_SMP_PHYLIST:
6100                         error = smpphylist(cam_dev, argc, argv, combinedopt,
6101                                            retry_count, timeout);
6102                         break;
6103                 case CAM_CMD_SMP_MANINFO:
6104                         error = smpmaninfo(cam_dev, argc, argv, combinedopt,
6105                                            retry_count, timeout);
6106                         break;
6107                 case CAM_CMD_DEBUG:
6108                         error = camdebug(argc, argv, combinedopt);
6109                         break;
6110                 case CAM_CMD_TAG:
6111                         error = tagcontrol(cam_dev, argc, argv, combinedopt);
6112                         break;
6113                 case CAM_CMD_RATE:
6114                         error = ratecontrol(cam_dev, retry_count, timeout,
6115                                             argc, argv, combinedopt);
6116                         break;
6117                 case CAM_CMD_FORMAT:
6118                         error = scsiformat(cam_dev, argc, argv,
6119                                            combinedopt, retry_count, timeout);
6120                         break;
6121                 case CAM_CMD_REPORTLUNS:
6122                         error = scsireportluns(cam_dev, argc, argv,
6123                                                combinedopt, retry_count,
6124                                                timeout);
6125                         break;
6126                 case CAM_CMD_READCAP:
6127                         error = scsireadcapacity(cam_dev, argc, argv,
6128                                                  combinedopt, retry_count,
6129                                                  timeout);
6130                         break;
6131                 case CAM_CMD_IDLE:
6132                 case CAM_CMD_STANDBY:
6133                 case CAM_CMD_SLEEP:
6134                         error = atapm(cam_dev, argc, argv,
6135                                                  combinedopt, retry_count,
6136                                                  timeout);
6137                         break;
6138 #endif /* MINIMALISTIC */
6139                 case CAM_CMD_USAGE:
6140                         usage(1);
6141                         break;
6142                 default:
6143                         usage(0);
6144                         error = 1;
6145                         break;
6146         }
6147
6148         if (cam_dev != NULL)
6149                 cam_close_device(cam_dev);
6150
6151         exit(error);
6152 }