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