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