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