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