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