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