xref: /freebsd/sbin/camcontrol/camcontrol.c (revision e28a4053)
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 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <ctype.h>
43 #include <err.h>
44 #include <libutil.h>
45 
46 #include <cam/cam.h>
47 #include <cam/cam_debug.h>
48 #include <cam/cam_ccb.h>
49 #include <cam/scsi/scsi_all.h>
50 #include <cam/scsi/scsi_da.h>
51 #include <cam/scsi/scsi_pass.h>
52 #include <cam/scsi/scsi_message.h>
53 #include <cam/ata/ata_all.h>
54 #include <camlib.h>
55 #include "camcontrol.h"
56 
57 typedef enum {
58 	CAM_CMD_NONE		= 0x00000000,
59 	CAM_CMD_DEVLIST		= 0x00000001,
60 	CAM_CMD_TUR		= 0x00000002,
61 	CAM_CMD_INQUIRY		= 0x00000003,
62 	CAM_CMD_STARTSTOP	= 0x00000004,
63 	CAM_CMD_RESCAN		= 0x00000005,
64 	CAM_CMD_READ_DEFECTS	= 0x00000006,
65 	CAM_CMD_MODE_PAGE	= 0x00000007,
66 	CAM_CMD_SCSI_CMD	= 0x00000008,
67 	CAM_CMD_DEVTREE		= 0x00000009,
68 	CAM_CMD_USAGE		= 0x0000000a,
69 	CAM_CMD_DEBUG		= 0x0000000b,
70 	CAM_CMD_RESET		= 0x0000000c,
71 	CAM_CMD_FORMAT		= 0x0000000d,
72 	CAM_CMD_TAG		= 0x0000000e,
73 	CAM_CMD_RATE		= 0x0000000f,
74 	CAM_CMD_DETACH		= 0x00000010,
75 	CAM_CMD_REPORTLUNS	= 0x00000011,
76 	CAM_CMD_READCAP		= 0x00000012,
77 	CAM_CMD_IDENTIFY	= 0x00000013,
78 	CAM_CMD_IDLE		= 0x00000014,
79 	CAM_CMD_STANDBY		= 0x00000015,
80 	CAM_CMD_SLEEP		= 0x00000016
81 } cam_cmdmask;
82 
83 typedef enum {
84 	CAM_ARG_NONE		= 0x00000000,
85 	CAM_ARG_VERBOSE		= 0x00000001,
86 	CAM_ARG_DEVICE		= 0x00000002,
87 	CAM_ARG_BUS		= 0x00000004,
88 	CAM_ARG_TARGET		= 0x00000008,
89 	CAM_ARG_LUN		= 0x00000010,
90 	CAM_ARG_EJECT		= 0x00000020,
91 	CAM_ARG_UNIT		= 0x00000040,
92 	CAM_ARG_FORMAT_BLOCK	= 0x00000080,
93 	CAM_ARG_FORMAT_BFI	= 0x00000100,
94 	CAM_ARG_FORMAT_PHYS	= 0x00000200,
95 	CAM_ARG_PLIST		= 0x00000400,
96 	CAM_ARG_GLIST		= 0x00000800,
97 	CAM_ARG_GET_SERIAL	= 0x00001000,
98 	CAM_ARG_GET_STDINQ	= 0x00002000,
99 	CAM_ARG_GET_XFERRATE	= 0x00004000,
100 	CAM_ARG_INQ_MASK	= 0x00007000,
101 	CAM_ARG_MODE_EDIT	= 0x00008000,
102 	CAM_ARG_PAGE_CNTL	= 0x00010000,
103 	CAM_ARG_TIMEOUT		= 0x00020000,
104 	CAM_ARG_CMD_IN		= 0x00040000,
105 	CAM_ARG_CMD_OUT		= 0x00080000,
106 	CAM_ARG_DBD		= 0x00100000,
107 	CAM_ARG_ERR_RECOVER	= 0x00200000,
108 	CAM_ARG_RETRIES		= 0x00400000,
109 	CAM_ARG_START_UNIT	= 0x00800000,
110 	CAM_ARG_DEBUG_INFO	= 0x01000000,
111 	CAM_ARG_DEBUG_TRACE	= 0x02000000,
112 	CAM_ARG_DEBUG_SUBTRACE	= 0x04000000,
113 	CAM_ARG_DEBUG_CDB	= 0x08000000,
114 	CAM_ARG_DEBUG_XPT	= 0x10000000,
115 	CAM_ARG_DEBUG_PERIPH	= 0x20000000,
116 } cam_argmask;
117 
118 struct camcontrol_opts {
119 	const char	*optname;
120 	cam_cmdmask	cmdnum;
121 	cam_argmask	argnum;
122 	const char	*subopt;
123 };
124 
125 #ifndef MINIMALISTIC
126 static const char scsicmd_opts[] = "a:c:dfi:o:r";
127 static const char readdefect_opts[] = "f:GP";
128 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
129 #endif
130 
131 struct camcontrol_opts option_table[] = {
132 #ifndef MINIMALISTIC
133 	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
134 	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
135 	{"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
136 	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
137 	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
138 	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
139 	{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
140 	{"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
141 	{"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
142 #endif /* MINIMALISTIC */
143 	{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
144 	{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
145 #ifndef MINIMALISTIC
146 	{"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
147 	{"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
148 	{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
149 	{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
150 #endif /* MINIMALISTIC */
151 	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
152 #ifndef MINIMALISTIC
153 	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
154 	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
155 	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
156 	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
157 	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
158 	{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
159 	{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
160 	{"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
161 	{"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
162 	{"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
163 #endif /* MINIMALISTIC */
164 	{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
165 	{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
166 	{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
167 	{NULL, 0, 0, NULL}
168 };
169 
170 typedef enum {
171 	CC_OR_NOT_FOUND,
172 	CC_OR_AMBIGUOUS,
173 	CC_OR_FOUND
174 } camcontrol_optret;
175 
176 cam_cmdmask cmdlist;
177 cam_argmask arglist;
178 
179 
180 camcontrol_optret getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
181 			    const char **subopt);
182 #ifndef MINIMALISTIC
183 static int getdevlist(struct cam_device *device);
184 #endif /* MINIMALISTIC */
185 static int getdevtree(void);
186 #ifndef MINIMALISTIC
187 static int testunitready(struct cam_device *device, int retry_count,
188 			 int timeout, int quiet);
189 static int scsistart(struct cam_device *device, int startstop, int loadeject,
190 		     int retry_count, int timeout);
191 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
192 			 char *combinedopt, int retry_count, int timeout);
193 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
194 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
195 static int camxferrate(struct cam_device *device);
196 #endif /* MINIMALISTIC */
197 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
198 		     cam_argmask *arglst);
199 static int dorescan_or_reset(int argc, char **argv, int rescan);
200 static int rescan_or_reset_bus(int bus, int rescan);
201 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
202 #ifndef MINIMALISTIC
203 static int readdefects(struct cam_device *device, int argc, char **argv,
204 		       char *combinedopt, int retry_count, int timeout);
205 static void modepage(struct cam_device *device, int argc, char **argv,
206 		     char *combinedopt, int retry_count, int timeout);
207 static int scsicmd(struct cam_device *device, int argc, char **argv,
208 		   char *combinedopt, int retry_count, int timeout);
209 static int tagcontrol(struct cam_device *device, int argc, char **argv,
210 		      char *combinedopt);
211 static void cts_print(struct cam_device *device,
212 		      struct ccb_trans_settings *cts);
213 static void cpi_print(struct ccb_pathinq *cpi);
214 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
215 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
216 static int get_print_cts(struct cam_device *device, int user_settings,
217 			 int quiet, struct ccb_trans_settings *cts);
218 static int ratecontrol(struct cam_device *device, int retry_count,
219 		       int timeout, int argc, char **argv, char *combinedopt);
220 static int scsiformat(struct cam_device *device, int argc, char **argv,
221 		      char *combinedopt, int retry_count, int timeout);
222 static int scsireportluns(struct cam_device *device, int argc, char **argv,
223 			  char *combinedopt, int retry_count, int timeout);
224 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
225 			    char *combinedopt, int retry_count, int timeout);
226 static int atapm(struct cam_device *device, int argc, char **argv,
227 			    char *combinedopt, int retry_count, int timeout);
228 #endif /* MINIMALISTIC */
229 #ifndef min
230 #define min(a,b) (((a)<(b))?(a):(b))
231 #endif
232 #ifndef max
233 #define max(a,b) (((a)>(b))?(a):(b))
234 #endif
235 
236 camcontrol_optret
237 getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
238 	  const char **subopt)
239 {
240 	struct camcontrol_opts *opts;
241 	int num_matches = 0;
242 
243 	for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
244 	     opts++) {
245 		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
246 			*cmdnum = opts->cmdnum;
247 			*argnum = opts->argnum;
248 			*subopt = opts->subopt;
249 			if (++num_matches > 1)
250 				return(CC_OR_AMBIGUOUS);
251 		}
252 	}
253 
254 	if (num_matches > 0)
255 		return(CC_OR_FOUND);
256 	else
257 		return(CC_OR_NOT_FOUND);
258 }
259 
260 #ifndef MINIMALISTIC
261 static int
262 getdevlist(struct cam_device *device)
263 {
264 	union ccb *ccb;
265 	char status[32];
266 	int error = 0;
267 
268 	ccb = cam_getccb(device);
269 
270 	ccb->ccb_h.func_code = XPT_GDEVLIST;
271 	ccb->ccb_h.flags = CAM_DIR_NONE;
272 	ccb->ccb_h.retry_count = 1;
273 	ccb->cgdl.index = 0;
274 	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
275 	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
276 		if (cam_send_ccb(device, ccb) < 0) {
277 			perror("error getting device list");
278 			cam_freeccb(ccb);
279 			return(1);
280 		}
281 
282 		status[0] = '\0';
283 
284 		switch (ccb->cgdl.status) {
285 			case CAM_GDEVLIST_MORE_DEVS:
286 				strcpy(status, "MORE");
287 				break;
288 			case CAM_GDEVLIST_LAST_DEVICE:
289 				strcpy(status, "LAST");
290 				break;
291 			case CAM_GDEVLIST_LIST_CHANGED:
292 				strcpy(status, "CHANGED");
293 				break;
294 			case CAM_GDEVLIST_ERROR:
295 				strcpy(status, "ERROR");
296 				error = 1;
297 				break;
298 		}
299 
300 		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
301 			ccb->cgdl.periph_name,
302 			ccb->cgdl.unit_number,
303 			ccb->cgdl.generation,
304 			ccb->cgdl.index,
305 			status);
306 
307 		/*
308 		 * If the list has changed, we need to start over from the
309 		 * beginning.
310 		 */
311 		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
312 			ccb->cgdl.index = 0;
313 	}
314 
315 	cam_freeccb(ccb);
316 
317 	return(error);
318 }
319 #endif /* MINIMALISTIC */
320 
321 static int
322 getdevtree(void)
323 {
324 	union ccb ccb;
325 	int bufsize, fd;
326 	unsigned int i;
327 	int need_close = 0;
328 	int error = 0;
329 	int skip_device = 0;
330 
331 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
332 		warn("couldn't open %s", XPT_DEVICE);
333 		return(1);
334 	}
335 
336 	bzero(&ccb, sizeof(union ccb));
337 
338 	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
339 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
340 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
341 
342 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
343 	bufsize = sizeof(struct dev_match_result) * 100;
344 	ccb.cdm.match_buf_len = bufsize;
345 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
346 	if (ccb.cdm.matches == NULL) {
347 		warnx("can't malloc memory for matches");
348 		close(fd);
349 		return(1);
350 	}
351 	ccb.cdm.num_matches = 0;
352 
353 	/*
354 	 * We fetch all nodes, since we display most of them in the default
355 	 * case, and all in the verbose case.
356 	 */
357 	ccb.cdm.num_patterns = 0;
358 	ccb.cdm.pattern_buf_len = 0;
359 
360 	/*
361 	 * We do the ioctl multiple times if necessary, in case there are
362 	 * more than 100 nodes in the EDT.
363 	 */
364 	do {
365 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
366 			warn("error sending CAMIOCOMMAND ioctl");
367 			error = 1;
368 			break;
369 		}
370 
371 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
372 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
373 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
374 			warnx("got CAM error %#x, CDM error %d\n",
375 			      ccb.ccb_h.status, ccb.cdm.status);
376 			error = 1;
377 			break;
378 		}
379 
380 		for (i = 0; i < ccb.cdm.num_matches; i++) {
381 			switch (ccb.cdm.matches[i].type) {
382 			case DEV_MATCH_BUS: {
383 				struct bus_match_result *bus_result;
384 
385 				/*
386 				 * Only print the bus information if the
387 				 * user turns on the verbose flag.
388 				 */
389 				if ((arglist & CAM_ARG_VERBOSE) == 0)
390 					break;
391 
392 				bus_result =
393 					&ccb.cdm.matches[i].result.bus_result;
394 
395 				if (need_close) {
396 					fprintf(stdout, ")\n");
397 					need_close = 0;
398 				}
399 
400 				fprintf(stdout, "scbus%d on %s%d bus %d:\n",
401 					bus_result->path_id,
402 					bus_result->dev_name,
403 					bus_result->unit_number,
404 					bus_result->bus_id);
405 				break;
406 			}
407 			case DEV_MATCH_DEVICE: {
408 				struct device_match_result *dev_result;
409 				char vendor[16], product[48], revision[16];
410 				char tmpstr[256];
411 
412 				dev_result =
413 				     &ccb.cdm.matches[i].result.device_result;
414 
415 				if ((dev_result->flags
416 				     & DEV_RESULT_UNCONFIGURED)
417 				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
418 					skip_device = 1;
419 					break;
420 				} else
421 					skip_device = 0;
422 
423 				if (dev_result->protocol == PROTO_SCSI) {
424 				    cam_strvis(vendor, dev_result->inq_data.vendor,
425 					   sizeof(dev_result->inq_data.vendor),
426 					   sizeof(vendor));
427 				    cam_strvis(product,
428 					   dev_result->inq_data.product,
429 					   sizeof(dev_result->inq_data.product),
430 					   sizeof(product));
431 				    cam_strvis(revision,
432 					   dev_result->inq_data.revision,
433 					  sizeof(dev_result->inq_data.revision),
434 					   sizeof(revision));
435 				    sprintf(tmpstr, "<%s %s %s>", vendor, product,
436 					revision);
437 				} else if (dev_result->protocol == PROTO_ATA ||
438 				    dev_result->protocol == PROTO_SATAPM) {
439 				    cam_strvis(product,
440 					   dev_result->ident_data.model,
441 					   sizeof(dev_result->ident_data.model),
442 					   sizeof(product));
443 				    cam_strvis(revision,
444 					   dev_result->ident_data.revision,
445 					  sizeof(dev_result->ident_data.revision),
446 					   sizeof(revision));
447 				    sprintf(tmpstr, "<%s %s>", product,
448 					revision);
449 				} else {
450 				    sprintf(tmpstr, "<>");
451 				}
452 				if (need_close) {
453 					fprintf(stdout, ")\n");
454 					need_close = 0;
455 				}
456 
457 				fprintf(stdout, "%-33s  at scbus%d "
458 					"target %d lun %d (",
459 					tmpstr,
460 					dev_result->path_id,
461 					dev_result->target_id,
462 					dev_result->target_lun);
463 
464 				need_close = 1;
465 
466 				break;
467 			}
468 			case DEV_MATCH_PERIPH: {
469 				struct periph_match_result *periph_result;
470 
471 				periph_result =
472 				      &ccb.cdm.matches[i].result.periph_result;
473 
474 				if (skip_device != 0)
475 					break;
476 
477 				if (need_close > 1)
478 					fprintf(stdout, ",");
479 
480 				fprintf(stdout, "%s%d",
481 					periph_result->periph_name,
482 					periph_result->unit_number);
483 
484 				need_close++;
485 				break;
486 			}
487 			default:
488 				fprintf(stdout, "unknown match type\n");
489 				break;
490 			}
491 		}
492 
493 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
494 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
495 
496 	if (need_close)
497 		fprintf(stdout, ")\n");
498 
499 	close(fd);
500 
501 	return(error);
502 }
503 
504 #ifndef MINIMALISTIC
505 static int
506 testunitready(struct cam_device *device, int retry_count, int timeout,
507 	      int quiet)
508 {
509 	int error = 0;
510 	union ccb *ccb;
511 
512 	ccb = cam_getccb(device);
513 
514 	scsi_test_unit_ready(&ccb->csio,
515 			     /* retries */ retry_count,
516 			     /* cbfcnp */ NULL,
517 			     /* tag_action */ MSG_SIMPLE_Q_TAG,
518 			     /* sense_len */ SSD_FULL_SIZE,
519 			     /* timeout */ timeout ? timeout : 5000);
520 
521 	/* Disable freezing the device queue */
522 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
523 
524 	if (arglist & CAM_ARG_ERR_RECOVER)
525 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
526 
527 	if (cam_send_ccb(device, ccb) < 0) {
528 		if (quiet == 0)
529 			perror("error sending test unit ready");
530 
531 		if (arglist & CAM_ARG_VERBOSE) {
532 			cam_error_print(device, ccb, CAM_ESF_ALL,
533 					CAM_EPF_ALL, stderr);
534 		}
535 
536 		cam_freeccb(ccb);
537 		return(1);
538 	}
539 
540 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
541 		if (quiet == 0)
542 			fprintf(stdout, "Unit is ready\n");
543 	} else {
544 		if (quiet == 0)
545 			fprintf(stdout, "Unit is not ready\n");
546 		error = 1;
547 
548 		if (arglist & CAM_ARG_VERBOSE) {
549 			cam_error_print(device, ccb, CAM_ESF_ALL,
550 					CAM_EPF_ALL, stderr);
551 		}
552 	}
553 
554 	cam_freeccb(ccb);
555 
556 	return(error);
557 }
558 
559 static int
560 scsistart(struct cam_device *device, int startstop, int loadeject,
561 	  int retry_count, int timeout)
562 {
563 	union ccb *ccb;
564 	int error = 0;
565 
566 	ccb = cam_getccb(device);
567 
568 	/*
569 	 * If we're stopping, send an ordered tag so the drive in question
570 	 * will finish any previously queued writes before stopping.  If
571 	 * the device isn't capable of tagged queueing, or if tagged
572 	 * queueing is turned off, the tag action is a no-op.
573 	 */
574 	scsi_start_stop(&ccb->csio,
575 			/* retries */ retry_count,
576 			/* cbfcnp */ NULL,
577 			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
578 						     MSG_ORDERED_Q_TAG,
579 			/* start/stop */ startstop,
580 			/* load_eject */ loadeject,
581 			/* immediate */ 0,
582 			/* sense_len */ SSD_FULL_SIZE,
583 			/* timeout */ timeout ? timeout : 120000);
584 
585 	/* Disable freezing the device queue */
586 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
587 
588 	if (arglist & CAM_ARG_ERR_RECOVER)
589 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
590 
591 	if (cam_send_ccb(device, ccb) < 0) {
592 		perror("error sending start unit");
593 
594 		if (arglist & CAM_ARG_VERBOSE) {
595 			cam_error_print(device, ccb, CAM_ESF_ALL,
596 					CAM_EPF_ALL, stderr);
597 		}
598 
599 		cam_freeccb(ccb);
600 		return(1);
601 	}
602 
603 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
604 		if (startstop) {
605 			fprintf(stdout, "Unit started successfully");
606 			if (loadeject)
607 				fprintf(stdout,", Media loaded\n");
608 			else
609 				fprintf(stdout,"\n");
610 		} else {
611 			fprintf(stdout, "Unit stopped successfully");
612 			if (loadeject)
613 				fprintf(stdout, ", Media ejected\n");
614 			else
615 				fprintf(stdout, "\n");
616 		}
617 	else {
618 		error = 1;
619 		if (startstop)
620 			fprintf(stdout,
621 				"Error received from start unit command\n");
622 		else
623 			fprintf(stdout,
624 				"Error received from stop unit command\n");
625 
626 		if (arglist & CAM_ARG_VERBOSE) {
627 			cam_error_print(device, ccb, CAM_ESF_ALL,
628 					CAM_EPF_ALL, stderr);
629 		}
630 	}
631 
632 	cam_freeccb(ccb);
633 
634 	return(error);
635 }
636 
637 static int
638 scsidoinquiry(struct cam_device *device, int argc, char **argv,
639 	      char *combinedopt, int retry_count, int timeout)
640 {
641 	int c;
642 	int error = 0;
643 
644 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
645 		switch(c) {
646 		case 'D':
647 			arglist |= CAM_ARG_GET_STDINQ;
648 			break;
649 		case 'R':
650 			arglist |= CAM_ARG_GET_XFERRATE;
651 			break;
652 		case 'S':
653 			arglist |= CAM_ARG_GET_SERIAL;
654 			break;
655 		default:
656 			break;
657 		}
658 	}
659 
660 	/*
661 	 * If the user didn't specify any inquiry options, he wants all of
662 	 * them.
663 	 */
664 	if ((arglist & CAM_ARG_INQ_MASK) == 0)
665 		arglist |= CAM_ARG_INQ_MASK;
666 
667 	if (arglist & CAM_ARG_GET_STDINQ)
668 		error = scsiinquiry(device, retry_count, timeout);
669 
670 	if (error != 0)
671 		return(error);
672 
673 	if (arglist & CAM_ARG_GET_SERIAL)
674 		scsiserial(device, retry_count, timeout);
675 
676 	if (error != 0)
677 		return(error);
678 
679 	if (arglist & CAM_ARG_GET_XFERRATE)
680 		error = camxferrate(device);
681 
682 	return(error);
683 }
684 
685 static int
686 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
687 {
688 	union ccb *ccb;
689 	struct scsi_inquiry_data *inq_buf;
690 	int error = 0;
691 
692 	ccb = cam_getccb(device);
693 
694 	if (ccb == NULL) {
695 		warnx("couldn't allocate CCB");
696 		return(1);
697 	}
698 
699 	/* cam_getccb cleans up the header, caller has to zero the payload */
700 	bzero(&(&ccb->ccb_h)[1],
701 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
702 
703 	inq_buf = (struct scsi_inquiry_data *)malloc(
704 		sizeof(struct scsi_inquiry_data));
705 
706 	if (inq_buf == NULL) {
707 		cam_freeccb(ccb);
708 		warnx("can't malloc memory for inquiry\n");
709 		return(1);
710 	}
711 	bzero(inq_buf, sizeof(*inq_buf));
712 
713 	/*
714 	 * Note that although the size of the inquiry buffer is the full
715 	 * 256 bytes specified in the SCSI spec, we only tell the device
716 	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
717 	 * two reasons for this:
718 	 *
719 	 *  - The SCSI spec says that when a length field is only 1 byte,
720 	 *    a value of 0 will be interpreted as 256.  Therefore
721 	 *    scsi_inquiry() will convert an inq_len (which is passed in as
722 	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
723 	 *    to 0.  Evidently, very few devices meet the spec in that
724 	 *    regard.  Some devices, like many Seagate disks, take the 0 as
725 	 *    0, and don't return any data.  One Pioneer DVD-R drive
726 	 *    returns more data than the command asked for.
727 	 *
728 	 *    So, since there are numerous devices that just don't work
729 	 *    right with the full inquiry size, we don't send the full size.
730 	 *
731 	 *  - The second reason not to use the full inquiry data length is
732 	 *    that we don't need it here.  The only reason we issue a
733 	 *    standard inquiry is to get the vendor name, device name,
734 	 *    and revision so scsi_print_inquiry() can print them.
735 	 *
736 	 * If, at some point in the future, more inquiry data is needed for
737 	 * some reason, this code should use a procedure similar to the
738 	 * probe code.  i.e., issue a short inquiry, and determine from
739 	 * the additional length passed back from the device how much
740 	 * inquiry data the device supports.  Once the amount the device
741 	 * supports is determined, issue an inquiry for that amount and no
742 	 * more.
743 	 *
744 	 * KDM, 2/18/2000
745 	 */
746 	scsi_inquiry(&ccb->csio,
747 		     /* retries */ retry_count,
748 		     /* cbfcnp */ NULL,
749 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
750 		     /* inq_buf */ (u_int8_t *)inq_buf,
751 		     /* inq_len */ SHORT_INQUIRY_LENGTH,
752 		     /* evpd */ 0,
753 		     /* page_code */ 0,
754 		     /* sense_len */ SSD_FULL_SIZE,
755 		     /* timeout */ timeout ? timeout : 5000);
756 
757 	/* Disable freezing the device queue */
758 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
759 
760 	if (arglist & CAM_ARG_ERR_RECOVER)
761 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
762 
763 	if (cam_send_ccb(device, ccb) < 0) {
764 		perror("error sending SCSI inquiry");
765 
766 		if (arglist & CAM_ARG_VERBOSE) {
767 			cam_error_print(device, ccb, CAM_ESF_ALL,
768 					CAM_EPF_ALL, stderr);
769 		}
770 
771 		cam_freeccb(ccb);
772 		return(1);
773 	}
774 
775 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
776 		error = 1;
777 
778 		if (arglist & CAM_ARG_VERBOSE) {
779 			cam_error_print(device, ccb, CAM_ESF_ALL,
780 					CAM_EPF_ALL, stderr);
781 		}
782 	}
783 
784 	cam_freeccb(ccb);
785 
786 	if (error != 0) {
787 		free(inq_buf);
788 		return(error);
789 	}
790 
791 	fprintf(stdout, "%s%d: ", device->device_name,
792 		device->dev_unit_num);
793 	scsi_print_inquiry(inq_buf);
794 
795 	free(inq_buf);
796 
797 	return(0);
798 }
799 
800 static int
801 scsiserial(struct cam_device *device, int retry_count, int timeout)
802 {
803 	union ccb *ccb;
804 	struct scsi_vpd_unit_serial_number *serial_buf;
805 	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
806 	int error = 0;
807 
808 	ccb = cam_getccb(device);
809 
810 	if (ccb == NULL) {
811 		warnx("couldn't allocate CCB");
812 		return(1);
813 	}
814 
815 	/* cam_getccb cleans up the header, caller has to zero the payload */
816 	bzero(&(&ccb->ccb_h)[1],
817 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
818 
819 	serial_buf = (struct scsi_vpd_unit_serial_number *)
820 		malloc(sizeof(*serial_buf));
821 
822 	if (serial_buf == NULL) {
823 		cam_freeccb(ccb);
824 		warnx("can't malloc memory for serial number");
825 		return(1);
826 	}
827 
828 	scsi_inquiry(&ccb->csio,
829 		     /*retries*/ retry_count,
830 		     /*cbfcnp*/ NULL,
831 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
832 		     /* inq_buf */ (u_int8_t *)serial_buf,
833 		     /* inq_len */ sizeof(*serial_buf),
834 		     /* evpd */ 1,
835 		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
836 		     /* sense_len */ SSD_FULL_SIZE,
837 		     /* timeout */ timeout ? timeout : 5000);
838 
839 	/* Disable freezing the device queue */
840 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
841 
842 	if (arglist & CAM_ARG_ERR_RECOVER)
843 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
844 
845 	if (cam_send_ccb(device, ccb) < 0) {
846 		warn("error getting serial number");
847 
848 		if (arglist & CAM_ARG_VERBOSE) {
849 			cam_error_print(device, ccb, CAM_ESF_ALL,
850 					CAM_EPF_ALL, stderr);
851 		}
852 
853 		cam_freeccb(ccb);
854 		free(serial_buf);
855 		return(1);
856 	}
857 
858 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
859 		error = 1;
860 
861 		if (arglist & CAM_ARG_VERBOSE) {
862 			cam_error_print(device, ccb, CAM_ESF_ALL,
863 					CAM_EPF_ALL, stderr);
864 		}
865 	}
866 
867 	cam_freeccb(ccb);
868 
869 	if (error != 0) {
870 		free(serial_buf);
871 		return(error);
872 	}
873 
874 	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
875 	serial_num[serial_buf->length] = '\0';
876 
877 	if ((arglist & CAM_ARG_GET_STDINQ)
878 	 || (arglist & CAM_ARG_GET_XFERRATE))
879 		fprintf(stdout, "%s%d: Serial Number ",
880 			device->device_name, device->dev_unit_num);
881 
882 	fprintf(stdout, "%.60s\n", serial_num);
883 
884 	free(serial_buf);
885 
886 	return(0);
887 }
888 
889 static int
890 camxferrate(struct cam_device *device)
891 {
892 	struct ccb_pathinq cpi;
893 	u_int32_t freq = 0;
894 	u_int32_t speed = 0;
895 	union ccb *ccb;
896 	u_int mb;
897 	int retval = 0;
898 
899 	if ((retval = get_cpi(device, &cpi)) != 0)
900 		return (1);
901 
902 	ccb = cam_getccb(device);
903 
904 	if (ccb == NULL) {
905 		warnx("couldn't allocate CCB");
906 		return(1);
907 	}
908 
909 	bzero(&(&ccb->ccb_h)[1],
910 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
911 
912 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
913 	ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
914 
915 	if (((retval = cam_send_ccb(device, ccb)) < 0)
916 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
917 		const char error_string[] = "error getting transfer settings";
918 
919 		if (retval < 0)
920 			warn(error_string);
921 		else
922 			warnx(error_string);
923 
924 		if (arglist & CAM_ARG_VERBOSE)
925 			cam_error_print(device, ccb, CAM_ESF_ALL,
926 					CAM_EPF_ALL, stderr);
927 
928 		retval = 1;
929 
930 		goto xferrate_bailout;
931 
932 	}
933 
934 	speed = cpi.base_transfer_speed;
935 	freq = 0;
936 	if (ccb->cts.transport == XPORT_SPI) {
937 		struct ccb_trans_settings_spi *spi =
938 		    &ccb->cts.xport_specific.spi;
939 
940 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
941 			freq = scsi_calc_syncsrate(spi->sync_period);
942 			speed = freq;
943 		}
944 		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
945 			speed *= (0x01 << spi->bus_width);
946 		}
947 	} else if (ccb->cts.transport == XPORT_FC) {
948 		struct ccb_trans_settings_fc *fc =
949 		    &ccb->cts.xport_specific.fc;
950 
951 		if (fc->valid & CTS_FC_VALID_SPEED)
952 			speed = fc->bitrate;
953 	} else if (ccb->cts.transport == XPORT_SAS) {
954 		struct ccb_trans_settings_sas *sas =
955 		    &ccb->cts.xport_specific.sas;
956 
957 		if (sas->valid & CTS_SAS_VALID_SPEED)
958 			speed = sas->bitrate;
959 	} else if (ccb->cts.transport == XPORT_ATA) {
960 		struct ccb_trans_settings_ata *ata =
961 		    &ccb->cts.xport_specific.ata;
962 
963 		if (ata->valid & CTS_ATA_VALID_MODE)
964 			speed = ata_mode2speed(ata->mode);
965 	} else if (ccb->cts.transport == XPORT_SATA) {
966 		struct	ccb_trans_settings_sata *sata =
967 		    &ccb->cts.xport_specific.sata;
968 
969 		if (sata->valid & CTS_SATA_VALID_REVISION)
970 			speed = ata_revision2speed(sata->revision);
971 	}
972 
973 	mb = speed / 1000;
974 	if (mb > 0) {
975 		fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
976 			device->device_name, device->dev_unit_num,
977 			mb, speed % 1000);
978 	} else {
979 		fprintf(stdout, "%s%d: %dKB/s transfers",
980 			device->device_name, device->dev_unit_num,
981 			speed);
982 	}
983 
984 	if (ccb->cts.transport == XPORT_SPI) {
985 		struct ccb_trans_settings_spi *spi =
986 		    &ccb->cts.xport_specific.spi;
987 
988 		if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
989 		 && (spi->sync_offset != 0))
990 			fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
991 				freq % 1000, spi->sync_offset);
992 
993 		if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
994 		 && (spi->bus_width > 0)) {
995 			if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
996 			 && (spi->sync_offset != 0)) {
997 				fprintf(stdout, ", ");
998 			} else {
999 				fprintf(stdout, " (");
1000 			}
1001 			fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1002 		} else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1003 		 && (spi->sync_offset != 0)) {
1004 			fprintf(stdout, ")");
1005 		}
1006 	} else if (ccb->cts.transport == XPORT_ATA) {
1007 		struct ccb_trans_settings_ata *ata =
1008 		    &ccb->cts.xport_specific.ata;
1009 
1010 		printf(" (");
1011 		if (ata->valid & CTS_ATA_VALID_MODE)
1012 			printf("%s, ", ata_mode2string(ata->mode));
1013 		if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0)
1014 			printf("ATAPI %dbytes, ", ata->atapi);
1015 		if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
1016 			printf("PIO %dbytes", ata->bytecount);
1017 		printf(")");
1018 	} else if (ccb->cts.transport == XPORT_SATA) {
1019 		struct ccb_trans_settings_sata *sata =
1020 		    &ccb->cts.xport_specific.sata;
1021 
1022 		printf(" (");
1023 		if (sata->valid & CTS_SATA_VALID_REVISION)
1024 			printf("SATA %d.x, ", sata->revision);
1025 		else
1026 			printf("SATA, ");
1027 		if (sata->valid & CTS_SATA_VALID_MODE)
1028 			printf("%s, ", ata_mode2string(sata->mode));
1029 		if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1030 			printf("ATAPI %dbytes, ", sata->atapi);
1031 		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1032 			printf("PIO %dbytes", sata->bytecount);
1033 		printf(")");
1034 	}
1035 
1036 	if (ccb->cts.protocol == PROTO_SCSI) {
1037 		struct ccb_trans_settings_scsi *scsi =
1038 		    &ccb->cts.proto_specific.scsi;
1039 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
1040 			if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1041 				fprintf(stdout, ", Command Queueing Enabled");
1042 			}
1043 		}
1044 	}
1045 
1046         fprintf(stdout, "\n");
1047 
1048 xferrate_bailout:
1049 
1050 	cam_freeccb(ccb);
1051 
1052 	return(retval);
1053 }
1054 
1055 static void
1056 atacapprint(struct ata_params *parm)
1057 {
1058 	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1059 				((u_int32_t)parm->lba_size_2 << 16);
1060 
1061 	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1062 				((u_int64_t)parm->lba_size48_2 << 16) |
1063 				((u_int64_t)parm->lba_size48_3 << 32) |
1064 				((u_int64_t)parm->lba_size48_4 << 48);
1065 
1066 	printf("\n");
1067 	printf("protocol              ");
1068 	printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1069 	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1070 		if (parm->satacapabilities & ATA_SATA_GEN3)
1071 			printf(" SATA 3.x\n");
1072 		else if (parm->satacapabilities & ATA_SATA_GEN2)
1073 			printf(" SATA 2.x\n");
1074 		else if (parm->satacapabilities & ATA_SATA_GEN1)
1075 			printf(" SATA 1.x\n");
1076 		else
1077 			printf(" SATA\n");
1078 	}
1079 	else
1080 		printf("\n");
1081 	printf("device model          %.40s\n", parm->model);
1082 	printf("firmware revision     %.8s\n", parm->revision);
1083 	printf("serial number         %.20s\n", parm->serial);
1084 	if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1085 		printf("WWN                   %02x%02x%02x%02x\n",
1086 		    parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1087 	}
1088 	if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1089 		printf("media serial number   %.30s\n",
1090 		    parm->media_serial);
1091 	}
1092 
1093 	printf("cylinders             %d\n", parm->cylinders);
1094 	printf("heads                 %d\n", parm->heads);
1095 	printf("sectors/track         %d\n", parm->sectors);
1096 	printf("sector size           logical %u, physical %lu, offset %lu\n",
1097 	    ata_logical_sector_size(parm),
1098 	    (unsigned long)ata_physical_sector_size(parm),
1099 	    (unsigned long)ata_logical_sector_offset(parm));
1100 
1101 	if (parm->config == ATA_PROTO_CFA ||
1102 	    (parm->support.command2 & ATA_SUPPORT_CFA))
1103 		printf("CFA supported\n");
1104 
1105 	printf("LBA%ssupported         ",
1106 		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1107 	if (lbasize)
1108 		printf("%d sectors\n", lbasize);
1109 	else
1110 		printf("\n");
1111 
1112 	printf("LBA48%ssupported       ",
1113 		parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1114 	if (lbasize48)
1115 		printf("%ju sectors\n", (uintmax_t)lbasize48);
1116 	else
1117 		printf("\n");
1118 
1119 	printf("PIO supported         PIO");
1120 	switch (ata_max_pmode(parm)) {
1121 	case ATA_PIO4:
1122 		printf("4");
1123 		break;
1124 	case ATA_PIO3:
1125 		printf("3");
1126 		break;
1127 	case ATA_PIO2:
1128 		printf("2");
1129 		break;
1130 	case ATA_PIO1:
1131 		printf("1");
1132 		break;
1133 	default:
1134 		printf("0");
1135 	}
1136 	if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1137 		printf(" w/o IORDY");
1138 	printf("\n");
1139 
1140 	printf("DMA%ssupported         ",
1141 		parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1142 	if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1143 		if (parm->mwdmamodes & 0xff) {
1144 			printf("WDMA");
1145 			if (parm->mwdmamodes & 0x04)
1146 				printf("2");
1147 			else if (parm->mwdmamodes & 0x02)
1148 				printf("1");
1149 			else if (parm->mwdmamodes & 0x01)
1150 				printf("0");
1151 			printf(" ");
1152 		}
1153 		if ((parm->atavalid & ATA_FLAG_88) &&
1154 		    (parm->udmamodes & 0xff)) {
1155 			printf("UDMA");
1156 			if (parm->udmamodes & 0x40)
1157 				printf("6");
1158 			else if (parm->udmamodes & 0x20)
1159 				printf("5");
1160 			else if (parm->udmamodes & 0x10)
1161 				printf("4");
1162 			else if (parm->udmamodes & 0x08)
1163 				printf("3");
1164 			else if (parm->udmamodes & 0x04)
1165 				printf("2");
1166 			else if (parm->udmamodes & 0x02)
1167 				printf("1");
1168 			else if (parm->udmamodes & 0x01)
1169 				printf("0");
1170 			printf(" ");
1171 		}
1172 	}
1173 	printf("\n");
1174 
1175 	if (parm->media_rotation_rate == 1) {
1176 		printf("media RPM             non-rotating\n");
1177 	} else if (parm->media_rotation_rate >= 0x0401 &&
1178 	    parm->media_rotation_rate <= 0xFFFE) {
1179 		printf("media RPM             %d\n",
1180 			parm->media_rotation_rate);
1181 	}
1182 
1183 	printf("\nFeature                      "
1184 		"Support  Enabled   Value           Vendor\n");
1185 	printf("read ahead                     %s	%s\n",
1186 		parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1187 		parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1188 	printf("write cache                    %s	%s\n",
1189 		parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1190 		parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1191 	printf("flush cache                    %s	%s\n",
1192 		parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1193 		parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1194 	printf("overlap                        %s\n",
1195 		parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1196 	printf("Tagged Command Queuing (TCQ)   %s	%s",
1197 		parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1198 		parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1199 		if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1200 			printf("	%d tags\n",
1201 			    ATA_QUEUE_LEN(parm->queue) + 1);
1202 		} else
1203 			printf("\n");
1204 	printf("Native Command Queuing (NCQ)   ");
1205 	if (parm->satacapabilities != 0xffff &&
1206 	    (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1207 		printf("yes		%d tags\n",
1208 		    ATA_QUEUE_LEN(parm->queue) + 1);
1209 	} else
1210 		printf("no\n");
1211 	printf("SMART                          %s	%s\n",
1212 		parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1213 		parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1214 	printf("microcode download             %s	%s\n",
1215 		parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1216 		parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1217 	printf("security                       %s	%s\n",
1218 		parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1219 		parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1220 	printf("power management               %s	%s\n",
1221 		parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1222 		parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1223 	printf("advanced power management      %s	%s",
1224 		parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1225 		parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1226 		if (parm->support.command2 & ATA_SUPPORT_APM) {
1227 			printf("	%d/0x%02X\n",
1228 			    parm->apm_value, parm->apm_value);
1229 		} else
1230 			printf("\n");
1231 	printf("automatic acoustic management  %s	%s",
1232 		parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1233 		parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1234 		if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1235 			printf("	%d/0x%02X	%d/0x%02X\n",
1236 			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1237 			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1238 			    ATA_ACOUSTIC_VENDOR(parm->acoustic),
1239 			    ATA_ACOUSTIC_VENDOR(parm->acoustic));
1240 		} else
1241 			printf("\n");
1242 	printf("media status notification      %s	%s\n",
1243 		parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1244 		parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1245 	printf("power-up in Standby            %s	%s\n",
1246 		parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1247 		parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1248 	printf("write-read-verify              %s	%s",
1249 		parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1250 		parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1251 		if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1252 			printf("	%d/0x%x\n",
1253 			    parm->wrv_mode, parm->wrv_mode);
1254 		} else
1255 			printf("\n");
1256 	printf("unload                         %s	%s\n",
1257 		parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1258 		parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1259 	printf("free-fall                      %s	%s\n",
1260 		parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1261 		parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1262 	printf("data set management (TRIM)     %s\n",
1263 		parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1264 }
1265 
1266 static int
1267 ataidentify(struct cam_device *device, int retry_count, int timeout)
1268 {
1269 	union ccb *ccb;
1270 	struct ata_params *ident_buf;
1271 	struct ccb_getdev cgd;
1272 	u_int i, error = 0;
1273 	int16_t *ptr;
1274 
1275 	if (get_cgd(device, &cgd) != 0) {
1276 		warnx("couldn't get CGD");
1277 		return(1);
1278 	}
1279 	ccb = cam_getccb(device);
1280 
1281 	if (ccb == NULL) {
1282 		warnx("couldn't allocate CCB");
1283 		return(1);
1284 	}
1285 
1286 	/* cam_getccb cleans up the header, caller has to zero the payload */
1287 	bzero(&(&ccb->ccb_h)[1],
1288 	      sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1289 
1290 	ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1291 
1292 	if (ptr == NULL) {
1293 		cam_freeccb(ccb);
1294 		warnx("can't malloc memory for identify\n");
1295 		return(1);
1296 	}
1297 	bzero(ptr, sizeof(struct ata_params));
1298 
1299 	cam_fill_ataio(&ccb->ataio,
1300 		      retry_count,
1301 		      NULL,
1302 		      /*flags*/CAM_DIR_IN,
1303 		      MSG_SIMPLE_Q_TAG,
1304 		      /*data_ptr*/(u_int8_t *)ptr,
1305 		      /*dxfer_len*/sizeof(struct ata_params),
1306 		      timeout ? timeout : 30 * 1000);
1307 	if (cgd.protocol == PROTO_ATA)
1308 		ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1309 	else
1310 		ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1311 
1312 	/* Disable freezing the device queue */
1313 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1314 
1315 	if (arglist & CAM_ARG_ERR_RECOVER)
1316 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1317 
1318 	if (cam_send_ccb(device, ccb) < 0) {
1319 		perror("error sending ATA identify");
1320 
1321 		if (arglist & CAM_ARG_VERBOSE) {
1322 			cam_error_print(device, ccb, CAM_ESF_ALL,
1323 					CAM_EPF_ALL, stderr);
1324 		}
1325 
1326 		free(ptr);
1327 		cam_freeccb(ccb);
1328 		return(1);
1329 	}
1330 
1331 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1332 		error = 1;
1333 
1334 		if (arglist & CAM_ARG_VERBOSE) {
1335 			cam_error_print(device, ccb, CAM_ESF_ALL,
1336 					CAM_EPF_ALL, stderr);
1337 		}
1338 	}
1339 
1340 	cam_freeccb(ccb);
1341 
1342 	if (error != 0) {
1343 		free(ptr);
1344 		return(error);
1345 	}
1346 
1347 	for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1348 		ptr[i] = le16toh(ptr[i]);
1349 	if (arglist & CAM_ARG_VERBOSE) {
1350 		fprintf(stdout, "%s%d: Raw identify data:\n",
1351 		    device->device_name, device->dev_unit_num);
1352 		for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1353 			if ((i % 8) == 0)
1354 			    fprintf(stdout, " %3d: ", i);
1355 			fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1356 			if ((i % 8) == 7)
1357 			    fprintf(stdout, "\n");
1358 		}
1359 	}
1360 	ident_buf = (struct ata_params *)ptr;
1361 	if (strncmp(ident_buf->model, "FX", 2) &&
1362 	    strncmp(ident_buf->model, "NEC", 3) &&
1363 	    strncmp(ident_buf->model, "Pioneer", 7) &&
1364 	    strncmp(ident_buf->model, "SHARP", 5)) {
1365 		ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1366 		ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1367 		ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1368 		ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1369 	}
1370 	ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1371 	ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1372 	ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1373 	ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1374 	ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1375 	ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1376 	ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1377 	ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1378 	    sizeof(ident_buf->media_serial));
1379 
1380 	fprintf(stdout, "%s%d: ", device->device_name,
1381 		device->dev_unit_num);
1382 	ata_print_ident(ident_buf);
1383 	camxferrate(device);
1384 	atacapprint(ident_buf);
1385 
1386 	free(ident_buf);
1387 
1388 	return(0);
1389 }
1390 #endif /* MINIMALISTIC */
1391 
1392 /*
1393  * Parse out a bus, or a bus, target and lun in the following
1394  * format:
1395  * bus
1396  * bus:target
1397  * bus:target:lun
1398  *
1399  * Returns the number of parsed components, or 0.
1400  */
1401 static int
1402 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1403 {
1404 	char *tmpstr;
1405 	int convs = 0;
1406 
1407 	while (isspace(*tstr) && (*tstr != '\0'))
1408 		tstr++;
1409 
1410 	tmpstr = (char *)strtok(tstr, ":");
1411 	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1412 		*bus = strtol(tmpstr, NULL, 0);
1413 		*arglst |= CAM_ARG_BUS;
1414 		convs++;
1415 		tmpstr = (char *)strtok(NULL, ":");
1416 		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1417 			*target = strtol(tmpstr, NULL, 0);
1418 			*arglst |= CAM_ARG_TARGET;
1419 			convs++;
1420 			tmpstr = (char *)strtok(NULL, ":");
1421 			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1422 				*lun = strtol(tmpstr, NULL, 0);
1423 				*arglst |= CAM_ARG_LUN;
1424 				convs++;
1425 			}
1426 		}
1427 	}
1428 
1429 	return convs;
1430 }
1431 
1432 static int
1433 dorescan_or_reset(int argc, char **argv, int rescan)
1434 {
1435 	static const char must[] =
1436 		"you must specify \"all\", a bus, or a bus:target:lun to %s";
1437 	int rv, error = 0;
1438 	int bus = -1, target = -1, lun = -1;
1439 	char *tstr;
1440 
1441 	if (argc < 3) {
1442 		warnx(must, rescan? "rescan" : "reset");
1443 		return(1);
1444 	}
1445 
1446 	tstr = argv[optind];
1447 	while (isspace(*tstr) && (*tstr != '\0'))
1448 		tstr++;
1449 	if (strncasecmp(tstr, "all", strlen("all")) == 0)
1450 		arglist |= CAM_ARG_BUS;
1451 	else {
1452 		rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1453 		if (rv != 1 && rv != 3) {
1454 			warnx(must, rescan? "rescan" : "reset");
1455 			return(1);
1456 		}
1457 	}
1458 
1459 	if ((arglist & CAM_ARG_BUS)
1460 	    && (arglist & CAM_ARG_TARGET)
1461 	    && (arglist & CAM_ARG_LUN))
1462 		error = scanlun_or_reset_dev(bus, target, lun, rescan);
1463 	else
1464 		error = rescan_or_reset_bus(bus, rescan);
1465 
1466 	return(error);
1467 }
1468 
1469 static int
1470 rescan_or_reset_bus(int bus, int rescan)
1471 {
1472 	union ccb ccb, matchccb;
1473 	int fd, retval;
1474 	int bufsize;
1475 
1476 	retval = 0;
1477 
1478 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1479 		warnx("error opening transport layer device %s", XPT_DEVICE);
1480 		warn("%s", XPT_DEVICE);
1481 		return(1);
1482 	}
1483 
1484 	if (bus != -1) {
1485 		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1486 		ccb.ccb_h.path_id = bus;
1487 		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1488 		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1489 		ccb.crcn.flags = CAM_FLAG_NONE;
1490 
1491 		/* run this at a low priority */
1492 		ccb.ccb_h.pinfo.priority = 5;
1493 
1494 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1495 			warn("CAMIOCOMMAND ioctl failed");
1496 			close(fd);
1497 			return(1);
1498 		}
1499 
1500 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1501 			fprintf(stdout, "%s of bus %d was successful\n",
1502 			    rescan ? "Re-scan" : "Reset", bus);
1503 		} else {
1504 			fprintf(stdout, "%s of bus %d returned error %#x\n",
1505 				rescan ? "Re-scan" : "Reset", bus,
1506 				ccb.ccb_h.status & CAM_STATUS_MASK);
1507 			retval = 1;
1508 		}
1509 
1510 		close(fd);
1511 		return(retval);
1512 
1513 	}
1514 
1515 
1516 	/*
1517 	 * The right way to handle this is to modify the xpt so that it can
1518 	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
1519 	 * that isn't implemented, so instead we enumerate the busses and
1520 	 * send the rescan or reset to those busses in the case where the
1521 	 * given bus is -1 (wildcard).  We don't send a rescan or reset
1522 	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1523 	 * no-op, sending a rescan to the xpt bus would result in a status of
1524 	 * CAM_REQ_INVALID.
1525 	 */
1526 	bzero(&(&matchccb.ccb_h)[1],
1527 	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1528 	matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1529 	bufsize = sizeof(struct dev_match_result) * 20;
1530 	matchccb.cdm.match_buf_len = bufsize;
1531 	matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1532 	if (matchccb.cdm.matches == NULL) {
1533 		warnx("can't malloc memory for matches");
1534 		retval = 1;
1535 		goto bailout;
1536 	}
1537 	matchccb.cdm.num_matches = 0;
1538 
1539 	matchccb.cdm.num_patterns = 1;
1540 	matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1541 
1542 	matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1543 		matchccb.cdm.pattern_buf_len);
1544 	if (matchccb.cdm.patterns == NULL) {
1545 		warnx("can't malloc memory for patterns");
1546 		retval = 1;
1547 		goto bailout;
1548 	}
1549 	matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1550 	matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1551 
1552 	do {
1553 		unsigned int i;
1554 
1555 		if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1556 			warn("CAMIOCOMMAND ioctl failed");
1557 			retval = 1;
1558 			goto bailout;
1559 		}
1560 
1561 		if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1562 		 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1563 		   && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1564 			warnx("got CAM error %#x, CDM error %d\n",
1565 			      matchccb.ccb_h.status, matchccb.cdm.status);
1566 			retval = 1;
1567 			goto bailout;
1568 		}
1569 
1570 		for (i = 0; i < matchccb.cdm.num_matches; i++) {
1571 			struct bus_match_result *bus_result;
1572 
1573 			/* This shouldn't happen. */
1574 			if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1575 				continue;
1576 
1577 			bus_result = &matchccb.cdm.matches[i].result.bus_result;
1578 
1579 			/*
1580 			 * We don't want to rescan or reset the xpt bus.
1581 			 * See above.
1582 			 */
1583 			if ((int)bus_result->path_id == -1)
1584 				continue;
1585 
1586 			ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1587 						       XPT_RESET_BUS;
1588 			ccb.ccb_h.path_id = bus_result->path_id;
1589 			ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1590 			ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1591 			ccb.crcn.flags = CAM_FLAG_NONE;
1592 
1593 			/* run this at a low priority */
1594 			ccb.ccb_h.pinfo.priority = 5;
1595 
1596 			if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1597 				warn("CAMIOCOMMAND ioctl failed");
1598 				retval = 1;
1599 				goto bailout;
1600 			}
1601 
1602 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1603 				fprintf(stdout, "%s of bus %d was successful\n",
1604 					rescan? "Re-scan" : "Reset",
1605 					bus_result->path_id);
1606 			} else {
1607 				/*
1608 				 * Don't bail out just yet, maybe the other
1609 				 * rescan or reset commands will complete
1610 				 * successfully.
1611 				 */
1612 				fprintf(stderr, "%s of bus %d returned error "
1613 					"%#x\n", rescan? "Re-scan" : "Reset",
1614 					bus_result->path_id,
1615 					ccb.ccb_h.status & CAM_STATUS_MASK);
1616 				retval = 1;
1617 			}
1618 		}
1619 	} while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1620 		 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1621 
1622 bailout:
1623 
1624 	if (fd != -1)
1625 		close(fd);
1626 
1627 	if (matchccb.cdm.patterns != NULL)
1628 		free(matchccb.cdm.patterns);
1629 	if (matchccb.cdm.matches != NULL)
1630 		free(matchccb.cdm.matches);
1631 
1632 	return(retval);
1633 }
1634 
1635 static int
1636 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1637 {
1638 	union ccb ccb;
1639 	struct cam_device *device;
1640 	int fd;
1641 
1642 	device = NULL;
1643 
1644 	if (bus < 0) {
1645 		warnx("invalid bus number %d", bus);
1646 		return(1);
1647 	}
1648 
1649 	if (target < 0) {
1650 		warnx("invalid target number %d", target);
1651 		return(1);
1652 	}
1653 
1654 	if (lun < 0) {
1655 		warnx("invalid lun number %d", lun);
1656 		return(1);
1657 	}
1658 
1659 	fd = -1;
1660 
1661 	bzero(&ccb, sizeof(union ccb));
1662 
1663 	if (scan) {
1664 		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1665 			warnx("error opening transport layer device %s\n",
1666 			    XPT_DEVICE);
1667 			warn("%s", XPT_DEVICE);
1668 			return(1);
1669 		}
1670 	} else {
1671 		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1672 		if (device == NULL) {
1673 			warnx("%s", cam_errbuf);
1674 			return(1);
1675 		}
1676 	}
1677 
1678 	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1679 	ccb.ccb_h.path_id = bus;
1680 	ccb.ccb_h.target_id = target;
1681 	ccb.ccb_h.target_lun = lun;
1682 	ccb.ccb_h.timeout = 5000;
1683 	ccb.crcn.flags = CAM_FLAG_NONE;
1684 
1685 	/* run this at a low priority */
1686 	ccb.ccb_h.pinfo.priority = 5;
1687 
1688 	if (scan) {
1689 		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1690 			warn("CAMIOCOMMAND ioctl failed");
1691 			close(fd);
1692 			return(1);
1693 		}
1694 	} else {
1695 		if (cam_send_ccb(device, &ccb) < 0) {
1696 			warn("error sending XPT_RESET_DEV CCB");
1697 			cam_close_device(device);
1698 			return(1);
1699 		}
1700 	}
1701 
1702 	if (scan)
1703 		close(fd);
1704 	else
1705 		cam_close_device(device);
1706 
1707 	/*
1708 	 * An error code of CAM_BDR_SENT is normal for a BDR request.
1709 	 */
1710 	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1711 	 || ((!scan)
1712 	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1713 		fprintf(stdout, "%s of %d:%d:%d was successful\n",
1714 		    scan? "Re-scan" : "Reset", bus, target, lun);
1715 		return(0);
1716 	} else {
1717 		fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1718 		    scan? "Re-scan" : "Reset", bus, target, lun,
1719 		    ccb.ccb_h.status & CAM_STATUS_MASK);
1720 		return(1);
1721 	}
1722 }
1723 
1724 #ifndef MINIMALISTIC
1725 static int
1726 readdefects(struct cam_device *device, int argc, char **argv,
1727 	    char *combinedopt, int retry_count, int timeout)
1728 {
1729 	union ccb *ccb = NULL;
1730 	struct scsi_read_defect_data_10 *rdd_cdb;
1731 	u_int8_t *defect_list = NULL;
1732 	u_int32_t dlist_length = 65000;
1733 	u_int32_t returned_length = 0;
1734 	u_int32_t num_returned = 0;
1735 	u_int8_t returned_format;
1736 	unsigned int i;
1737 	int c, error = 0;
1738 	int lists_specified = 0;
1739 
1740 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1741 		switch(c){
1742 		case 'f':
1743 		{
1744 			char *tstr;
1745 			tstr = optarg;
1746 			while (isspace(*tstr) && (*tstr != '\0'))
1747 				tstr++;
1748 			if (strcmp(tstr, "block") == 0)
1749 				arglist |= CAM_ARG_FORMAT_BLOCK;
1750 			else if (strcmp(tstr, "bfi") == 0)
1751 				arglist |= CAM_ARG_FORMAT_BFI;
1752 			else if (strcmp(tstr, "phys") == 0)
1753 				arglist |= CAM_ARG_FORMAT_PHYS;
1754 			else {
1755 				error = 1;
1756 				warnx("invalid defect format %s", tstr);
1757 				goto defect_bailout;
1758 			}
1759 			break;
1760 		}
1761 		case 'G':
1762 			arglist |= CAM_ARG_GLIST;
1763 			break;
1764 		case 'P':
1765 			arglist |= CAM_ARG_PLIST;
1766 			break;
1767 		default:
1768 			break;
1769 		}
1770 	}
1771 
1772 	ccb = cam_getccb(device);
1773 
1774 	/*
1775 	 * Hopefully 65000 bytes is enough to hold the defect list.  If it
1776 	 * isn't, the disk is probably dead already.  We'd have to go with
1777 	 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1778 	 * to hold them all.
1779 	 */
1780 	defect_list = malloc(dlist_length);
1781 	if (defect_list == NULL) {
1782 		warnx("can't malloc memory for defect list");
1783 		error = 1;
1784 		goto defect_bailout;
1785 	}
1786 
1787 	rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1788 
1789 	/*
1790 	 * cam_getccb() zeros the CCB header only.  So we need to zero the
1791 	 * payload portion of the ccb.
1792 	 */
1793 	bzero(&(&ccb->ccb_h)[1],
1794 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1795 
1796 	cam_fill_csio(&ccb->csio,
1797 		      /*retries*/ retry_count,
1798 		      /*cbfcnp*/ NULL,
1799 		      /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1800 					      CAM_PASS_ERR_RECOVER : 0),
1801 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
1802 		      /*data_ptr*/ defect_list,
1803 		      /*dxfer_len*/ dlist_length,
1804 		      /*sense_len*/ SSD_FULL_SIZE,
1805 		      /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1806 		      /*timeout*/ timeout ? timeout : 5000);
1807 
1808 	rdd_cdb->opcode = READ_DEFECT_DATA_10;
1809 	if (arglist & CAM_ARG_FORMAT_BLOCK)
1810 		rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1811 	else if (arglist & CAM_ARG_FORMAT_BFI)
1812 		rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1813 	else if (arglist & CAM_ARG_FORMAT_PHYS)
1814 		rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1815 	else {
1816 		error = 1;
1817 		warnx("no defect list format specified");
1818 		goto defect_bailout;
1819 	}
1820 	if (arglist & CAM_ARG_PLIST) {
1821 		rdd_cdb->format |= SRDD10_PLIST;
1822 		lists_specified++;
1823 	}
1824 
1825 	if (arglist & CAM_ARG_GLIST) {
1826 		rdd_cdb->format |= SRDD10_GLIST;
1827 		lists_specified++;
1828 	}
1829 
1830 	scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1831 
1832 	/* Disable freezing the device queue */
1833 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1834 
1835 	if (cam_send_ccb(device, ccb) < 0) {
1836 		perror("error reading defect list");
1837 
1838 		if (arglist & CAM_ARG_VERBOSE) {
1839 			cam_error_print(device, ccb, CAM_ESF_ALL,
1840 					CAM_EPF_ALL, stderr);
1841 		}
1842 
1843 		error = 1;
1844 		goto defect_bailout;
1845 	}
1846 
1847 	returned_length = scsi_2btoul(((struct
1848 		scsi_read_defect_data_hdr_10 *)defect_list)->length);
1849 
1850 	returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1851 			defect_list)->format;
1852 
1853 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1854 	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1855 	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1856 		struct scsi_sense_data *sense;
1857 		int error_code, sense_key, asc, ascq;
1858 
1859 		sense = &ccb->csio.sense_data;
1860 		scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1861 
1862 		/*
1863 		 * According to the SCSI spec, if the disk doesn't support
1864 		 * the requested format, it will generally return a sense
1865 		 * key of RECOVERED ERROR, and an additional sense code
1866 		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1867 		 * also check to make sure that the returned length is
1868 		 * greater than 0, and then print out whatever format the
1869 		 * disk gave us.
1870 		 */
1871 		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1872 		 && (asc == 0x1c) && (ascq == 0x00)
1873 		 && (returned_length > 0)) {
1874 			warnx("requested defect format not available");
1875 			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1876 			case SRDD10_BLOCK_FORMAT:
1877 				warnx("Device returned block format");
1878 				break;
1879 			case SRDD10_BYTES_FROM_INDEX_FORMAT:
1880 				warnx("Device returned bytes from index"
1881 				      " format");
1882 				break;
1883 			case SRDD10_PHYSICAL_SECTOR_FORMAT:
1884 				warnx("Device returned physical sector format");
1885 				break;
1886 			default:
1887 				error = 1;
1888 				warnx("Device returned unknown defect"
1889 				     " data format %#x", returned_format);
1890 				goto defect_bailout;
1891 				break; /* NOTREACHED */
1892 			}
1893 		} else {
1894 			error = 1;
1895 			warnx("Error returned from read defect data command");
1896 			if (arglist & CAM_ARG_VERBOSE)
1897 				cam_error_print(device, ccb, CAM_ESF_ALL,
1898 						CAM_EPF_ALL, stderr);
1899 			goto defect_bailout;
1900 		}
1901 	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1902 		error = 1;
1903 		warnx("Error returned from read defect data command");
1904 		if (arglist & CAM_ARG_VERBOSE)
1905 			cam_error_print(device, ccb, CAM_ESF_ALL,
1906 					CAM_EPF_ALL, stderr);
1907 		goto defect_bailout;
1908 	}
1909 
1910 	/*
1911 	 * XXX KDM  I should probably clean up the printout format for the
1912 	 * disk defects.
1913 	 */
1914 	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1915 		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1916 		{
1917 			struct scsi_defect_desc_phys_sector *dlist;
1918 
1919 			dlist = (struct scsi_defect_desc_phys_sector *)
1920 				(defect_list +
1921 				sizeof(struct scsi_read_defect_data_hdr_10));
1922 
1923 			num_returned = returned_length /
1924 				sizeof(struct scsi_defect_desc_phys_sector);
1925 
1926 			fprintf(stderr, "Got %d defect", num_returned);
1927 
1928 			if ((lists_specified == 0) || (num_returned == 0)) {
1929 				fprintf(stderr, "s.\n");
1930 				break;
1931 			} else if (num_returned == 1)
1932 				fprintf(stderr, ":\n");
1933 			else
1934 				fprintf(stderr, "s:\n");
1935 
1936 			for (i = 0; i < num_returned; i++) {
1937 				fprintf(stdout, "%d:%d:%d\n",
1938 					scsi_3btoul(dlist[i].cylinder),
1939 					dlist[i].head,
1940 					scsi_4btoul(dlist[i].sector));
1941 			}
1942 			break;
1943 		}
1944 		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1945 		{
1946 			struct scsi_defect_desc_bytes_from_index *dlist;
1947 
1948 			dlist = (struct scsi_defect_desc_bytes_from_index *)
1949 				(defect_list +
1950 				sizeof(struct scsi_read_defect_data_hdr_10));
1951 
1952 			num_returned = returned_length /
1953 			      sizeof(struct scsi_defect_desc_bytes_from_index);
1954 
1955 			fprintf(stderr, "Got %d defect", num_returned);
1956 
1957 			if ((lists_specified == 0) || (num_returned == 0)) {
1958 				fprintf(stderr, "s.\n");
1959 				break;
1960 			} else if (num_returned == 1)
1961 				fprintf(stderr, ":\n");
1962 			else
1963 				fprintf(stderr, "s:\n");
1964 
1965 			for (i = 0; i < num_returned; i++) {
1966 				fprintf(stdout, "%d:%d:%d\n",
1967 					scsi_3btoul(dlist[i].cylinder),
1968 					dlist[i].head,
1969 					scsi_4btoul(dlist[i].bytes_from_index));
1970 			}
1971 			break;
1972 		}
1973 		case SRDDH10_BLOCK_FORMAT:
1974 		{
1975 			struct scsi_defect_desc_block *dlist;
1976 
1977 			dlist = (struct scsi_defect_desc_block *)(defect_list +
1978 				sizeof(struct scsi_read_defect_data_hdr_10));
1979 
1980 			num_returned = returned_length /
1981 			      sizeof(struct scsi_defect_desc_block);
1982 
1983 			fprintf(stderr, "Got %d defect", num_returned);
1984 
1985 			if ((lists_specified == 0) || (num_returned == 0)) {
1986 				fprintf(stderr, "s.\n");
1987 				break;
1988 			} else if (num_returned == 1)
1989 				fprintf(stderr, ":\n");
1990 			else
1991 				fprintf(stderr, "s:\n");
1992 
1993 			for (i = 0; i < num_returned; i++)
1994 				fprintf(stdout, "%u\n",
1995 					scsi_4btoul(dlist[i].address));
1996 			break;
1997 		}
1998 		default:
1999 			fprintf(stderr, "Unknown defect format %d\n",
2000 				returned_format & SRDDH10_DLIST_FORMAT_MASK);
2001 			error = 1;
2002 			break;
2003 	}
2004 defect_bailout:
2005 
2006 	if (defect_list != NULL)
2007 		free(defect_list);
2008 
2009 	if (ccb != NULL)
2010 		cam_freeccb(ccb);
2011 
2012 	return(error);
2013 }
2014 #endif /* MINIMALISTIC */
2015 
2016 #if 0
2017 void
2018 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2019 {
2020 	union ccb *ccb;
2021 
2022 	ccb = cam_getccb(device);
2023 
2024 	cam_freeccb(ccb);
2025 }
2026 #endif
2027 
2028 #ifndef MINIMALISTIC
2029 void
2030 mode_sense(struct cam_device *device, int mode_page, int page_control,
2031 	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2032 {
2033 	union ccb *ccb;
2034 	int retval;
2035 
2036 	ccb = cam_getccb(device);
2037 
2038 	if (ccb == NULL)
2039 		errx(1, "mode_sense: couldn't allocate CCB");
2040 
2041 	bzero(&(&ccb->ccb_h)[1],
2042 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2043 
2044 	scsi_mode_sense(&ccb->csio,
2045 			/* retries */ retry_count,
2046 			/* cbfcnp */ NULL,
2047 			/* tag_action */ MSG_SIMPLE_Q_TAG,
2048 			/* dbd */ dbd,
2049 			/* page_code */ page_control << 6,
2050 			/* page */ mode_page,
2051 			/* param_buf */ data,
2052 			/* param_len */ datalen,
2053 			/* sense_len */ SSD_FULL_SIZE,
2054 			/* timeout */ timeout ? timeout : 5000);
2055 
2056 	if (arglist & CAM_ARG_ERR_RECOVER)
2057 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2058 
2059 	/* Disable freezing the device queue */
2060 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2061 
2062 	if (((retval = cam_send_ccb(device, ccb)) < 0)
2063 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2064 		if (arglist & CAM_ARG_VERBOSE) {
2065 			cam_error_print(device, ccb, CAM_ESF_ALL,
2066 					CAM_EPF_ALL, stderr);
2067 		}
2068 		cam_freeccb(ccb);
2069 		cam_close_device(device);
2070 		if (retval < 0)
2071 			err(1, "error sending mode sense command");
2072 		else
2073 			errx(1, "error sending mode sense command");
2074 	}
2075 
2076 	cam_freeccb(ccb);
2077 }
2078 
2079 void
2080 mode_select(struct cam_device *device, int save_pages, int retry_count,
2081 	   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_select: couldn't allocate CCB");
2090 
2091 	bzero(&(&ccb->ccb_h)[1],
2092 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2093 
2094 	scsi_mode_select(&ccb->csio,
2095 			 /* retries */ retry_count,
2096 			 /* cbfcnp */ NULL,
2097 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
2098 			 /* scsi_page_fmt */ 1,
2099 			 /* save_pages */ save_pages,
2100 			 /* param_buf */ data,
2101 			 /* param_len */ datalen,
2102 			 /* sense_len */ SSD_FULL_SIZE,
2103 			 /* timeout */ timeout ? timeout : 5000);
2104 
2105 	if (arglist & CAM_ARG_ERR_RECOVER)
2106 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2107 
2108 	/* Disable freezing the device queue */
2109 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2110 
2111 	if (((retval = cam_send_ccb(device, ccb)) < 0)
2112 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2113 		if (arglist & CAM_ARG_VERBOSE) {
2114 			cam_error_print(device, ccb, CAM_ESF_ALL,
2115 					CAM_EPF_ALL, stderr);
2116 		}
2117 		cam_freeccb(ccb);
2118 		cam_close_device(device);
2119 
2120 		if (retval < 0)
2121 			err(1, "error sending mode select command");
2122 		else
2123 			errx(1, "error sending mode select command");
2124 
2125 	}
2126 
2127 	cam_freeccb(ccb);
2128 }
2129 
2130 void
2131 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2132 	 int retry_count, int timeout)
2133 {
2134 	int c, mode_page = -1, page_control = 0;
2135 	int binary = 0, list = 0;
2136 
2137 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2138 		switch(c) {
2139 		case 'b':
2140 			binary = 1;
2141 			break;
2142 		case 'd':
2143 			arglist |= CAM_ARG_DBD;
2144 			break;
2145 		case 'e':
2146 			arglist |= CAM_ARG_MODE_EDIT;
2147 			break;
2148 		case 'l':
2149 			list = 1;
2150 			break;
2151 		case 'm':
2152 			mode_page = strtol(optarg, NULL, 0);
2153 			if (mode_page < 0)
2154 				errx(1, "invalid mode page %d", mode_page);
2155 			break;
2156 		case 'P':
2157 			page_control = strtol(optarg, NULL, 0);
2158 			if ((page_control < 0) || (page_control > 3))
2159 				errx(1, "invalid page control field %d",
2160 				     page_control);
2161 			arglist |= CAM_ARG_PAGE_CNTL;
2162 			break;
2163 		default:
2164 			break;
2165 		}
2166 	}
2167 
2168 	if (mode_page == -1 && list == 0)
2169 		errx(1, "you must specify a mode page!");
2170 
2171 	if (list) {
2172 		mode_list(device, page_control, arglist & CAM_ARG_DBD,
2173 		    retry_count, timeout);
2174 	} else {
2175 		mode_edit(device, mode_page, page_control,
2176 		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2177 		    retry_count, timeout);
2178 	}
2179 }
2180 
2181 static int
2182 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2183 	int retry_count, int timeout)
2184 {
2185 	union ccb *ccb;
2186 	u_int32_t flags = CAM_DIR_NONE;
2187 	u_int8_t *data_ptr = NULL;
2188 	u_int8_t cdb[20];
2189 	u_int8_t atacmd[12];
2190 	struct get_hook hook;
2191 	int c, data_bytes = 0;
2192 	int cdb_len = 0;
2193 	int atacmd_len = 0;
2194 	int dmacmd = 0;
2195 	int fpdmacmd = 0;
2196 	int need_res = 0;
2197 	char *datastr = NULL, *tstr, *resstr = NULL;
2198 	int error = 0;
2199 	int fd_data = 0, fd_res = 0;
2200 	int retval;
2201 
2202 	ccb = cam_getccb(device);
2203 
2204 	if (ccb == NULL) {
2205 		warnx("scsicmd: error allocating ccb");
2206 		return(1);
2207 	}
2208 
2209 	bzero(&(&ccb->ccb_h)[1],
2210 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
2211 
2212 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2213 		switch(c) {
2214 		case 'a':
2215 			tstr = optarg;
2216 			while (isspace(*tstr) && (*tstr != '\0'))
2217 				tstr++;
2218 			hook.argc = argc - optind;
2219 			hook.argv = argv + optind;
2220 			hook.got = 0;
2221 			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2222 						    iget, &hook);
2223 			/*
2224 			 * Increment optind by the number of arguments the
2225 			 * encoding routine processed.  After each call to
2226 			 * getopt(3), optind points to the argument that
2227 			 * getopt should process _next_.  In this case,
2228 			 * that means it points to the first command string
2229 			 * argument, if there is one.  Once we increment
2230 			 * this, it should point to either the next command
2231 			 * line argument, or it should be past the end of
2232 			 * the list.
2233 			 */
2234 			optind += hook.got;
2235 			break;
2236 		case 'c':
2237 			tstr = optarg;
2238 			while (isspace(*tstr) && (*tstr != '\0'))
2239 				tstr++;
2240 			hook.argc = argc - optind;
2241 			hook.argv = argv + optind;
2242 			hook.got = 0;
2243 			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2244 						    iget, &hook);
2245 			/*
2246 			 * Increment optind by the number of arguments the
2247 			 * encoding routine processed.  After each call to
2248 			 * getopt(3), optind points to the argument that
2249 			 * getopt should process _next_.  In this case,
2250 			 * that means it points to the first command string
2251 			 * argument, if there is one.  Once we increment
2252 			 * this, it should point to either the next command
2253 			 * line argument, or it should be past the end of
2254 			 * the list.
2255 			 */
2256 			optind += hook.got;
2257 			break;
2258 		case 'd':
2259 			dmacmd = 1;
2260 			break;
2261 		case 'f':
2262 			fpdmacmd = 1;
2263 			break;
2264 		case 'i':
2265 			if (arglist & CAM_ARG_CMD_OUT) {
2266 				warnx("command must either be "
2267 				      "read or write, not both");
2268 				error = 1;
2269 				goto scsicmd_bailout;
2270 			}
2271 			arglist |= CAM_ARG_CMD_IN;
2272 			flags = CAM_DIR_IN;
2273 			data_bytes = strtol(optarg, NULL, 0);
2274 			if (data_bytes <= 0) {
2275 				warnx("invalid number of input bytes %d",
2276 				      data_bytes);
2277 				error = 1;
2278 				goto scsicmd_bailout;
2279 			}
2280 			hook.argc = argc - optind;
2281 			hook.argv = argv + optind;
2282 			hook.got = 0;
2283 			optind++;
2284 			datastr = cget(&hook, NULL);
2285 			/*
2286 			 * If the user supplied "-" instead of a format, he
2287 			 * wants the data to be written to stdout.
2288 			 */
2289 			if ((datastr != NULL)
2290 			 && (datastr[0] == '-'))
2291 				fd_data = 1;
2292 
2293 			data_ptr = (u_int8_t *)malloc(data_bytes);
2294 			if (data_ptr == NULL) {
2295 				warnx("can't malloc memory for data_ptr");
2296 				error = 1;
2297 				goto scsicmd_bailout;
2298 			}
2299 			break;
2300 		case 'o':
2301 			if (arglist & CAM_ARG_CMD_IN) {
2302 				warnx("command must either be "
2303 				      "read or write, not both");
2304 				error = 1;
2305 				goto scsicmd_bailout;
2306 			}
2307 			arglist |= CAM_ARG_CMD_OUT;
2308 			flags = CAM_DIR_OUT;
2309 			data_bytes = strtol(optarg, NULL, 0);
2310 			if (data_bytes <= 0) {
2311 				warnx("invalid number of output bytes %d",
2312 				      data_bytes);
2313 				error = 1;
2314 				goto scsicmd_bailout;
2315 			}
2316 			hook.argc = argc - optind;
2317 			hook.argv = argv + optind;
2318 			hook.got = 0;
2319 			datastr = cget(&hook, NULL);
2320 			data_ptr = (u_int8_t *)malloc(data_bytes);
2321 			if (data_ptr == NULL) {
2322 				warnx("can't malloc memory for data_ptr");
2323 				error = 1;
2324 				goto scsicmd_bailout;
2325 			}
2326 			bzero(data_ptr, data_bytes);
2327 			/*
2328 			 * If the user supplied "-" instead of a format, he
2329 			 * wants the data to be read from stdin.
2330 			 */
2331 			if ((datastr != NULL)
2332 			 && (datastr[0] == '-'))
2333 				fd_data = 1;
2334 			else
2335 				buff_encode_visit(data_ptr, data_bytes, datastr,
2336 						  iget, &hook);
2337 			optind += hook.got;
2338 			break;
2339 		case 'r':
2340 			need_res = 1;
2341 			hook.argc = argc - optind;
2342 			hook.argv = argv + optind;
2343 			hook.got = 0;
2344 			resstr = cget(&hook, NULL);
2345 			if ((resstr != NULL) && (resstr[0] == '-'))
2346 				fd_res = 1;
2347 			optind += hook.got;
2348 			break;
2349 		default:
2350 			break;
2351 		}
2352 	}
2353 
2354 	/*
2355 	 * If fd_data is set, and we're writing to the device, we need to
2356 	 * read the data the user wants written from stdin.
2357 	 */
2358 	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2359 		ssize_t amt_read;
2360 		int amt_to_read = data_bytes;
2361 		u_int8_t *buf_ptr = data_ptr;
2362 
2363 		for (amt_read = 0; amt_to_read > 0;
2364 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2365 			if (amt_read == -1) {
2366 				warn("error reading data from stdin");
2367 				error = 1;
2368 				goto scsicmd_bailout;
2369 			}
2370 			amt_to_read -= amt_read;
2371 			buf_ptr += amt_read;
2372 		}
2373 	}
2374 
2375 	if (arglist & CAM_ARG_ERR_RECOVER)
2376 		flags |= CAM_PASS_ERR_RECOVER;
2377 
2378 	/* Disable freezing the device queue */
2379 	flags |= CAM_DEV_QFRZDIS;
2380 
2381 	if (cdb_len) {
2382 		/*
2383 		 * This is taken from the SCSI-3 draft spec.
2384 		 * (T10/1157D revision 0.3)
2385 		 * The top 3 bits of an opcode are the group code.
2386 		 * The next 5 bits are the command code.
2387 		 * Group 0:  six byte commands
2388 		 * Group 1:  ten byte commands
2389 		 * Group 2:  ten byte commands
2390 		 * Group 3:  reserved
2391 		 * Group 4:  sixteen byte commands
2392 		 * Group 5:  twelve byte commands
2393 		 * Group 6:  vendor specific
2394 		 * Group 7:  vendor specific
2395 		 */
2396 		switch((cdb[0] >> 5) & 0x7) {
2397 			case 0:
2398 				cdb_len = 6;
2399 				break;
2400 			case 1:
2401 			case 2:
2402 				cdb_len = 10;
2403 				break;
2404 			case 3:
2405 			case 6:
2406 			case 7:
2407 			        /* computed by buff_encode_visit */
2408 				break;
2409 			case 4:
2410 				cdb_len = 16;
2411 				break;
2412 			case 5:
2413 				cdb_len = 12;
2414 				break;
2415 		}
2416 
2417 		/*
2418 		 * We should probably use csio_build_visit or something like that
2419 		 * here, but it's easier to encode arguments as you go.  The
2420 		 * alternative would be skipping the CDB argument and then encoding
2421 		 * it here, since we've got the data buffer argument by now.
2422 		 */
2423 		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2424 
2425 		cam_fill_csio(&ccb->csio,
2426 		      /*retries*/ retry_count,
2427 		      /*cbfcnp*/ NULL,
2428 		      /*flags*/ flags,
2429 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
2430 		      /*data_ptr*/ data_ptr,
2431 		      /*dxfer_len*/ data_bytes,
2432 		      /*sense_len*/ SSD_FULL_SIZE,
2433 		      /*cdb_len*/ cdb_len,
2434 		      /*timeout*/ timeout ? timeout : 5000);
2435 	} else {
2436 		atacmd_len = 12;
2437 		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2438 		if (need_res)
2439 			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2440 		if (dmacmd)
2441 			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2442 		if (fpdmacmd)
2443 			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2444 
2445 		cam_fill_ataio(&ccb->ataio,
2446 		      /*retries*/ retry_count,
2447 		      /*cbfcnp*/ NULL,
2448 		      /*flags*/ flags,
2449 		      /*tag_action*/ 0,
2450 		      /*data_ptr*/ data_ptr,
2451 		      /*dxfer_len*/ data_bytes,
2452 		      /*timeout*/ timeout ? timeout : 5000);
2453 	}
2454 
2455 	if (((retval = cam_send_ccb(device, ccb)) < 0)
2456 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2457 		if (retval < 0)
2458 			warn("error sending command");
2459 		else
2460 			warnx("error sending command");
2461 
2462 		if (arglist & CAM_ARG_VERBOSE) {
2463 			cam_error_print(device, ccb, CAM_ESF_ALL,
2464 					CAM_EPF_ALL, stderr);
2465 		}
2466 
2467 		error = 1;
2468 		goto scsicmd_bailout;
2469 	}
2470 
2471 	if (atacmd_len && need_res) {
2472 		if (fd_res == 0) {
2473 			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2474 					  arg_put, NULL);
2475 			fprintf(stdout, "\n");
2476 		} else {
2477 			fprintf(stdout,
2478 			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2479 			    ccb->ataio.res.status,
2480 			    ccb->ataio.res.error,
2481 			    ccb->ataio.res.lba_low,
2482 			    ccb->ataio.res.lba_mid,
2483 			    ccb->ataio.res.lba_high,
2484 			    ccb->ataio.res.device,
2485 			    ccb->ataio.res.lba_low_exp,
2486 			    ccb->ataio.res.lba_mid_exp,
2487 			    ccb->ataio.res.lba_high_exp,
2488 			    ccb->ataio.res.sector_count,
2489 			    ccb->ataio.res.sector_count_exp);
2490 			fflush(stdout);
2491 		}
2492 	}
2493 
2494 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2495 	 && (arglist & CAM_ARG_CMD_IN)
2496 	 && (data_bytes > 0)) {
2497 		if (fd_data == 0) {
2498 			buff_decode_visit(data_ptr, data_bytes, datastr,
2499 					  arg_put, NULL);
2500 			fprintf(stdout, "\n");
2501 		} else {
2502 			ssize_t amt_written;
2503 			int amt_to_write = data_bytes;
2504 			u_int8_t *buf_ptr = data_ptr;
2505 
2506 			for (amt_written = 0; (amt_to_write > 0) &&
2507 			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2508 				amt_to_write -= amt_written;
2509 				buf_ptr += amt_written;
2510 			}
2511 			if (amt_written == -1) {
2512 				warn("error writing data to stdout");
2513 				error = 1;
2514 				goto scsicmd_bailout;
2515 			} else if ((amt_written == 0)
2516 				&& (amt_to_write > 0)) {
2517 				warnx("only wrote %u bytes out of %u",
2518 				      data_bytes - amt_to_write, data_bytes);
2519 			}
2520 		}
2521 	}
2522 
2523 scsicmd_bailout:
2524 
2525 	if ((data_bytes > 0) && (data_ptr != NULL))
2526 		free(data_ptr);
2527 
2528 	cam_freeccb(ccb);
2529 
2530 	return(error);
2531 }
2532 
2533 static int
2534 camdebug(int argc, char **argv, char *combinedopt)
2535 {
2536 	int c, fd;
2537 	int bus = -1, target = -1, lun = -1;
2538 	char *tstr, *tmpstr = NULL;
2539 	union ccb ccb;
2540 	int error = 0;
2541 
2542 	bzero(&ccb, sizeof(union ccb));
2543 
2544 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2545 		switch(c) {
2546 		case 'I':
2547 			arglist |= CAM_ARG_DEBUG_INFO;
2548 			ccb.cdbg.flags |= CAM_DEBUG_INFO;
2549 			break;
2550 		case 'P':
2551 			arglist |= CAM_ARG_DEBUG_PERIPH;
2552 			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2553 			break;
2554 		case 'S':
2555 			arglist |= CAM_ARG_DEBUG_SUBTRACE;
2556 			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2557 			break;
2558 		case 'T':
2559 			arglist |= CAM_ARG_DEBUG_TRACE;
2560 			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2561 			break;
2562 		case 'X':
2563 			arglist |= CAM_ARG_DEBUG_XPT;
2564 			ccb.cdbg.flags |= CAM_DEBUG_XPT;
2565 			break;
2566 		case 'c':
2567 			arglist |= CAM_ARG_DEBUG_CDB;
2568 			ccb.cdbg.flags |= CAM_DEBUG_CDB;
2569 			break;
2570 		default:
2571 			break;
2572 		}
2573 	}
2574 
2575 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2576 		warnx("error opening transport layer device %s", XPT_DEVICE);
2577 		warn("%s", XPT_DEVICE);
2578 		return(1);
2579 	}
2580 	argc -= optind;
2581 	argv += optind;
2582 
2583 	if (argc <= 0) {
2584 		warnx("you must specify \"off\", \"all\" or a bus,");
2585 		warnx("bus:target, or bus:target:lun");
2586 		close(fd);
2587 		return(1);
2588 	}
2589 
2590 	tstr = *argv;
2591 
2592 	while (isspace(*tstr) && (*tstr != '\0'))
2593 		tstr++;
2594 
2595 	if (strncmp(tstr, "off", 3) == 0) {
2596 		ccb.cdbg.flags = CAM_DEBUG_NONE;
2597 		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2598 			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2599 			     CAM_ARG_DEBUG_XPT);
2600 	} else if (strncmp(tstr, "all", 3) != 0) {
2601 		tmpstr = (char *)strtok(tstr, ":");
2602 		if ((tmpstr != NULL) && (*tmpstr != '\0')){
2603 			bus = strtol(tmpstr, NULL, 0);
2604 			arglist |= CAM_ARG_BUS;
2605 			tmpstr = (char *)strtok(NULL, ":");
2606 			if ((tmpstr != NULL) && (*tmpstr != '\0')){
2607 				target = strtol(tmpstr, NULL, 0);
2608 				arglist |= CAM_ARG_TARGET;
2609 				tmpstr = (char *)strtok(NULL, ":");
2610 				if ((tmpstr != NULL) && (*tmpstr != '\0')){
2611 					lun = strtol(tmpstr, NULL, 0);
2612 					arglist |= CAM_ARG_LUN;
2613 				}
2614 			}
2615 		} else {
2616 			error = 1;
2617 			warnx("you must specify \"all\", \"off\", or a bus,");
2618 			warnx("bus:target, or bus:target:lun to debug");
2619 		}
2620 	}
2621 
2622 	if (error == 0) {
2623 
2624 		ccb.ccb_h.func_code = XPT_DEBUG;
2625 		ccb.ccb_h.path_id = bus;
2626 		ccb.ccb_h.target_id = target;
2627 		ccb.ccb_h.target_lun = lun;
2628 
2629 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2630 			warn("CAMIOCOMMAND ioctl failed");
2631 			error = 1;
2632 		}
2633 
2634 		if (error == 0) {
2635 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2636 			     CAM_FUNC_NOTAVAIL) {
2637 				warnx("CAM debugging not available");
2638 				warnx("you need to put options CAMDEBUG in"
2639 				      " your kernel config file!");
2640 				error = 1;
2641 			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2642 				    CAM_REQ_CMP) {
2643 				warnx("XPT_DEBUG CCB failed with status %#x",
2644 				      ccb.ccb_h.status);
2645 				error = 1;
2646 			} else {
2647 				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2648 					fprintf(stderr,
2649 						"Debugging turned off\n");
2650 				} else {
2651 					fprintf(stderr,
2652 						"Debugging enabled for "
2653 						"%d:%d:%d\n",
2654 						bus, target, lun);
2655 				}
2656 			}
2657 		}
2658 		close(fd);
2659 	}
2660 
2661 	return(error);
2662 }
2663 
2664 static int
2665 tagcontrol(struct cam_device *device, int argc, char **argv,
2666 	   char *combinedopt)
2667 {
2668 	int c;
2669 	union ccb *ccb;
2670 	int numtags = -1;
2671 	int retval = 0;
2672 	int quiet = 0;
2673 	char pathstr[1024];
2674 
2675 	ccb = cam_getccb(device);
2676 
2677 	if (ccb == NULL) {
2678 		warnx("tagcontrol: error allocating ccb");
2679 		return(1);
2680 	}
2681 
2682 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2683 		switch(c) {
2684 		case 'N':
2685 			numtags = strtol(optarg, NULL, 0);
2686 			if (numtags < 0) {
2687 				warnx("tag count %d is < 0", numtags);
2688 				retval = 1;
2689 				goto tagcontrol_bailout;
2690 			}
2691 			break;
2692 		case 'q':
2693 			quiet++;
2694 			break;
2695 		default:
2696 			break;
2697 		}
2698 	}
2699 
2700 	cam_path_string(device, pathstr, sizeof(pathstr));
2701 
2702 	if (numtags >= 0) {
2703 		bzero(&(&ccb->ccb_h)[1],
2704 		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2705 		ccb->ccb_h.func_code = XPT_REL_SIMQ;
2706 		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2707 		ccb->crs.openings = numtags;
2708 
2709 
2710 		if (cam_send_ccb(device, ccb) < 0) {
2711 			perror("error sending XPT_REL_SIMQ CCB");
2712 			retval = 1;
2713 			goto tagcontrol_bailout;
2714 		}
2715 
2716 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2717 			warnx("XPT_REL_SIMQ CCB failed");
2718 			cam_error_print(device, ccb, CAM_ESF_ALL,
2719 					CAM_EPF_ALL, stderr);
2720 			retval = 1;
2721 			goto tagcontrol_bailout;
2722 		}
2723 
2724 
2725 		if (quiet == 0)
2726 			fprintf(stdout, "%stagged openings now %d\n",
2727 				pathstr, ccb->crs.openings);
2728 	}
2729 
2730 	bzero(&(&ccb->ccb_h)[1],
2731 	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2732 
2733 	ccb->ccb_h.func_code = XPT_GDEV_STATS;
2734 
2735 	if (cam_send_ccb(device, ccb) < 0) {
2736 		perror("error sending XPT_GDEV_STATS CCB");
2737 		retval = 1;
2738 		goto tagcontrol_bailout;
2739 	}
2740 
2741 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2742 		warnx("XPT_GDEV_STATS CCB failed");
2743 		cam_error_print(device, ccb, CAM_ESF_ALL,
2744 				CAM_EPF_ALL, stderr);
2745 		retval = 1;
2746 		goto tagcontrol_bailout;
2747 	}
2748 
2749 	if (arglist & CAM_ARG_VERBOSE) {
2750 		fprintf(stdout, "%s", pathstr);
2751 		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2752 		fprintf(stdout, "%s", pathstr);
2753 		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2754 		fprintf(stdout, "%s", pathstr);
2755 		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2756 		fprintf(stdout, "%s", pathstr);
2757 		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2758 		fprintf(stdout, "%s", pathstr);
2759 		fprintf(stdout, "held          %d\n", ccb->cgds.held);
2760 		fprintf(stdout, "%s", pathstr);
2761 		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2762 		fprintf(stdout, "%s", pathstr);
2763 		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2764 	} else {
2765 		if (quiet == 0) {
2766 			fprintf(stdout, "%s", pathstr);
2767 			fprintf(stdout, "device openings: ");
2768 		}
2769 		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2770 			ccb->cgds.dev_active);
2771 	}
2772 
2773 tagcontrol_bailout:
2774 
2775 	cam_freeccb(ccb);
2776 	return(retval);
2777 }
2778 
2779 static void
2780 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2781 {
2782 	char pathstr[1024];
2783 
2784 	cam_path_string(device, pathstr, sizeof(pathstr));
2785 
2786 	if (cts->transport == XPORT_SPI) {
2787 		struct ccb_trans_settings_spi *spi =
2788 		    &cts->xport_specific.spi;
2789 
2790 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2791 
2792 			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2793 				spi->sync_period);
2794 
2795 			if (spi->sync_offset != 0) {
2796 				u_int freq;
2797 
2798 				freq = scsi_calc_syncsrate(spi->sync_period);
2799 				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2800 					pathstr, freq / 1000, freq % 1000);
2801 			}
2802 		}
2803 
2804 		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2805 			fprintf(stdout, "%soffset: %d\n", pathstr,
2806 			    spi->sync_offset);
2807 		}
2808 
2809 		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2810 			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2811 				(0x01 << spi->bus_width) * 8);
2812 		}
2813 
2814 		if (spi->valid & CTS_SPI_VALID_DISC) {
2815 			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2816 				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2817 				"enabled" : "disabled");
2818 		}
2819 	}
2820 	if (cts->transport == XPORT_ATA) {
2821 		struct ccb_trans_settings_ata *ata =
2822 		    &cts->xport_specific.ata;
2823 
2824 		if ((ata->valid & CTS_ATA_VALID_MODE) != 0) {
2825 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
2826 				ata_mode2string(ata->mode));
2827 		}
2828 		if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2829 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2830 				ata->atapi);
2831 		}
2832 		if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2833 			fprintf(stdout, "%sPIO transaction length: %d\n",
2834 				pathstr, ata->bytecount);
2835 		}
2836 	}
2837 	if (cts->transport == XPORT_SATA) {
2838 		struct ccb_trans_settings_sata *sata =
2839 		    &cts->xport_specific.sata;
2840 
2841 		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2842 			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2843 				sata->revision);
2844 		}
2845 		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2846 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
2847 				ata_mode2string(sata->mode));
2848 		}
2849 		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2850 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2851 				sata->atapi);
2852 		}
2853 		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2854 			fprintf(stdout, "%sPIO transaction length: %d\n",
2855 				pathstr, sata->bytecount);
2856 		}
2857 		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2858 			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2859 				sata->pm_present);
2860 		}
2861 		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2862 			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2863 				sata->tags);
2864 		}
2865 		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2866 			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2867 				sata->caps);
2868 		}
2869 	}
2870 	if (cts->protocol == PROTO_SCSI) {
2871 		struct ccb_trans_settings_scsi *scsi=
2872 		    &cts->proto_specific.scsi;
2873 
2874 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
2875 			fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2876 				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2877 				"enabled" : "disabled");
2878 		}
2879 	}
2880 
2881 }
2882 
2883 /*
2884  * Get a path inquiry CCB for the specified device.
2885  */
2886 static int
2887 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2888 {
2889 	union ccb *ccb;
2890 	int retval = 0;
2891 
2892 	ccb = cam_getccb(device);
2893 	if (ccb == NULL) {
2894 		warnx("get_cpi: couldn't allocate CCB");
2895 		return(1);
2896 	}
2897 	bzero(&(&ccb->ccb_h)[1],
2898 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2899 	ccb->ccb_h.func_code = XPT_PATH_INQ;
2900 	if (cam_send_ccb(device, ccb) < 0) {
2901 		warn("get_cpi: error sending Path Inquiry CCB");
2902 		if (arglist & CAM_ARG_VERBOSE)
2903 			cam_error_print(device, ccb, CAM_ESF_ALL,
2904 					CAM_EPF_ALL, stderr);
2905 		retval = 1;
2906 		goto get_cpi_bailout;
2907 	}
2908 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2909 		if (arglist & CAM_ARG_VERBOSE)
2910 			cam_error_print(device, ccb, CAM_ESF_ALL,
2911 					CAM_EPF_ALL, stderr);
2912 		retval = 1;
2913 		goto get_cpi_bailout;
2914 	}
2915 	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2916 
2917 get_cpi_bailout:
2918 	cam_freeccb(ccb);
2919 	return(retval);
2920 }
2921 
2922 /*
2923  * Get a get device CCB for the specified device.
2924  */
2925 static int
2926 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
2927 {
2928 	union ccb *ccb;
2929 	int retval = 0;
2930 
2931 	ccb = cam_getccb(device);
2932 	if (ccb == NULL) {
2933 		warnx("get_cgd: couldn't allocate CCB");
2934 		return(1);
2935 	}
2936 	bzero(&(&ccb->ccb_h)[1],
2937 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2938 	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
2939 	if (cam_send_ccb(device, ccb) < 0) {
2940 		warn("get_cgd: error sending Path Inquiry CCB");
2941 		if (arglist & CAM_ARG_VERBOSE)
2942 			cam_error_print(device, ccb, CAM_ESF_ALL,
2943 					CAM_EPF_ALL, stderr);
2944 		retval = 1;
2945 		goto get_cgd_bailout;
2946 	}
2947 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2948 		if (arglist & CAM_ARG_VERBOSE)
2949 			cam_error_print(device, ccb, CAM_ESF_ALL,
2950 					CAM_EPF_ALL, stderr);
2951 		retval = 1;
2952 		goto get_cgd_bailout;
2953 	}
2954 	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
2955 
2956 get_cgd_bailout:
2957 	cam_freeccb(ccb);
2958 	return(retval);
2959 }
2960 
2961 static void
2962 cpi_print(struct ccb_pathinq *cpi)
2963 {
2964 	char adapter_str[1024];
2965 	int i;
2966 
2967 	snprintf(adapter_str, sizeof(adapter_str),
2968 		 "%s%d:", cpi->dev_name, cpi->unit_number);
2969 
2970 	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2971 		cpi->version_num);
2972 
2973 	for (i = 1; i < 0xff; i = i << 1) {
2974 		const char *str;
2975 
2976 		if ((i & cpi->hba_inquiry) == 0)
2977 			continue;
2978 
2979 		fprintf(stdout, "%s supports ", adapter_str);
2980 
2981 		switch(i) {
2982 		case PI_MDP_ABLE:
2983 			str = "MDP message";
2984 			break;
2985 		case PI_WIDE_32:
2986 			str = "32 bit wide SCSI";
2987 			break;
2988 		case PI_WIDE_16:
2989 			str = "16 bit wide SCSI";
2990 			break;
2991 		case PI_SDTR_ABLE:
2992 			str = "SDTR message";
2993 			break;
2994 		case PI_LINKED_CDB:
2995 			str = "linked CDBs";
2996 			break;
2997 		case PI_TAG_ABLE:
2998 			str = "tag queue messages";
2999 			break;
3000 		case PI_SOFT_RST:
3001 			str = "soft reset alternative";
3002 			break;
3003 		case PI_SATAPM:
3004 			str = "SATA Port Multiplier";
3005 			break;
3006 		default:
3007 			str = "unknown PI bit set";
3008 			break;
3009 		}
3010 		fprintf(stdout, "%s\n", str);
3011 	}
3012 
3013 	for (i = 1; i < 0xff; i = i << 1) {
3014 		const char *str;
3015 
3016 		if ((i & cpi->hba_misc) == 0)
3017 			continue;
3018 
3019 		fprintf(stdout, "%s ", adapter_str);
3020 
3021 		switch(i) {
3022 		case PIM_SCANHILO:
3023 			str = "bus scans from high ID to low ID";
3024 			break;
3025 		case PIM_NOREMOVE:
3026 			str = "removable devices not included in scan";
3027 			break;
3028 		case PIM_NOINITIATOR:
3029 			str = "initiator role not supported";
3030 			break;
3031 		case PIM_NOBUSRESET:
3032 			str = "user has disabled initial BUS RESET or"
3033 			      " controller is in target/mixed mode";
3034 			break;
3035 		case PIM_NO_6_BYTE:
3036 			str = "do not send 6-byte commands";
3037 			break;
3038 		case PIM_SEQSCAN:
3039 			str = "scan bus sequentially";
3040 			break;
3041 		default:
3042 			str = "unknown PIM bit set";
3043 			break;
3044 		}
3045 		fprintf(stdout, "%s\n", str);
3046 	}
3047 
3048 	for (i = 1; i < 0xff; i = i << 1) {
3049 		const char *str;
3050 
3051 		if ((i & cpi->target_sprt) == 0)
3052 			continue;
3053 
3054 		fprintf(stdout, "%s supports ", adapter_str);
3055 		switch(i) {
3056 		case PIT_PROCESSOR:
3057 			str = "target mode processor mode";
3058 			break;
3059 		case PIT_PHASE:
3060 			str = "target mode phase cog. mode";
3061 			break;
3062 		case PIT_DISCONNECT:
3063 			str = "disconnects in target mode";
3064 			break;
3065 		case PIT_TERM_IO:
3066 			str = "terminate I/O message in target mode";
3067 			break;
3068 		case PIT_GRP_6:
3069 			str = "group 6 commands in target mode";
3070 			break;
3071 		case PIT_GRP_7:
3072 			str = "group 7 commands in target mode";
3073 			break;
3074 		default:
3075 			str = "unknown PIT bit set";
3076 			break;
3077 		}
3078 
3079 		fprintf(stdout, "%s\n", str);
3080 	}
3081 	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3082 		cpi->hba_eng_cnt);
3083 	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3084 		cpi->max_target);
3085 	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3086 		cpi->max_lun);
3087 	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3088 		adapter_str, cpi->hpath_id);
3089 	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3090 		cpi->initiator_id);
3091 	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3092 	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3093 	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
3094 	    adapter_str, cpi->hba_vendor);
3095 	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
3096 	    adapter_str, cpi->hba_device);
3097 	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
3098 	    adapter_str, cpi->hba_subvendor);
3099 	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
3100 	    adapter_str, cpi->hba_subdevice);
3101 	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3102 	fprintf(stdout, "%s base transfer speed: ", adapter_str);
3103 	if (cpi->base_transfer_speed > 1000)
3104 		fprintf(stdout, "%d.%03dMB/sec\n",
3105 			cpi->base_transfer_speed / 1000,
3106 			cpi->base_transfer_speed % 1000);
3107 	else
3108 		fprintf(stdout, "%dKB/sec\n",
3109 			(cpi->base_transfer_speed % 1000) * 1000);
3110 	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
3111 	    adapter_str, cpi->maxio);
3112 }
3113 
3114 static int
3115 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3116 	      struct ccb_trans_settings *cts)
3117 {
3118 	int retval;
3119 	union ccb *ccb;
3120 
3121 	retval = 0;
3122 	ccb = cam_getccb(device);
3123 
3124 	if (ccb == NULL) {
3125 		warnx("get_print_cts: error allocating ccb");
3126 		return(1);
3127 	}
3128 
3129 	bzero(&(&ccb->ccb_h)[1],
3130 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3131 
3132 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3133 
3134 	if (user_settings == 0)
3135 		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3136 	else
3137 		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3138 
3139 	if (cam_send_ccb(device, ccb) < 0) {
3140 		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3141 		if (arglist & CAM_ARG_VERBOSE)
3142 			cam_error_print(device, ccb, CAM_ESF_ALL,
3143 					CAM_EPF_ALL, stderr);
3144 		retval = 1;
3145 		goto get_print_cts_bailout;
3146 	}
3147 
3148 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3149 		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3150 		if (arglist & CAM_ARG_VERBOSE)
3151 			cam_error_print(device, ccb, CAM_ESF_ALL,
3152 					CAM_EPF_ALL, stderr);
3153 		retval = 1;
3154 		goto get_print_cts_bailout;
3155 	}
3156 
3157 	if (quiet == 0)
3158 		cts_print(device, &ccb->cts);
3159 
3160 	if (cts != NULL)
3161 		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3162 
3163 get_print_cts_bailout:
3164 
3165 	cam_freeccb(ccb);
3166 
3167 	return(retval);
3168 }
3169 
3170 static int
3171 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3172 	    int argc, char **argv, char *combinedopt)
3173 {
3174 	int c;
3175 	union ccb *ccb;
3176 	int user_settings = 0;
3177 	int retval = 0;
3178 	int disc_enable = -1, tag_enable = -1;
3179 	int mode = -1;
3180 	int offset = -1;
3181 	double syncrate = -1;
3182 	int bus_width = -1;
3183 	int quiet = 0;
3184 	int change_settings = 0, send_tur = 0;
3185 	struct ccb_pathinq cpi;
3186 
3187 	ccb = cam_getccb(device);
3188 	if (ccb == NULL) {
3189 		warnx("ratecontrol: error allocating ccb");
3190 		return(1);
3191 	}
3192 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3193 		switch(c){
3194 		case 'a':
3195 			send_tur = 1;
3196 			break;
3197 		case 'c':
3198 			user_settings = 0;
3199 			break;
3200 		case 'D':
3201 			if (strncasecmp(optarg, "enable", 6) == 0)
3202 				disc_enable = 1;
3203 			else if (strncasecmp(optarg, "disable", 7) == 0)
3204 				disc_enable = 0;
3205 			else {
3206 				warnx("-D argument \"%s\" is unknown", optarg);
3207 				retval = 1;
3208 				goto ratecontrol_bailout;
3209 			}
3210 			change_settings = 1;
3211 			break;
3212 		case 'M':
3213 			mode = ata_string2mode(optarg);
3214 			if (mode < 0) {
3215 				warnx("unknown mode '%s'", optarg);
3216 				retval = 1;
3217 				goto ratecontrol_bailout;
3218 			}
3219 			change_settings = 1;
3220 			break;
3221 		case 'O':
3222 			offset = strtol(optarg, NULL, 0);
3223 			if (offset < 0) {
3224 				warnx("offset value %d is < 0", offset);
3225 				retval = 1;
3226 				goto ratecontrol_bailout;
3227 			}
3228 			change_settings = 1;
3229 			break;
3230 		case 'q':
3231 			quiet++;
3232 			break;
3233 		case 'R':
3234 			syncrate = atof(optarg);
3235 			if (syncrate < 0) {
3236 				warnx("sync rate %f is < 0", syncrate);
3237 				retval = 1;
3238 				goto ratecontrol_bailout;
3239 			}
3240 			change_settings = 1;
3241 			break;
3242 		case 'T':
3243 			if (strncasecmp(optarg, "enable", 6) == 0)
3244 				tag_enable = 1;
3245 			else if (strncasecmp(optarg, "disable", 7) == 0)
3246 				tag_enable = 0;
3247 			else {
3248 				warnx("-T argument \"%s\" is unknown", optarg);
3249 				retval = 1;
3250 				goto ratecontrol_bailout;
3251 			}
3252 			change_settings = 1;
3253 			break;
3254 		case 'U':
3255 			user_settings = 1;
3256 			break;
3257 		case 'W':
3258 			bus_width = strtol(optarg, NULL, 0);
3259 			if (bus_width < 0) {
3260 				warnx("bus width %d is < 0", bus_width);
3261 				retval = 1;
3262 				goto ratecontrol_bailout;
3263 			}
3264 			change_settings = 1;
3265 			break;
3266 		default:
3267 			break;
3268 		}
3269 	}
3270 	bzero(&(&ccb->ccb_h)[1],
3271 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3272 	/*
3273 	 * Grab path inquiry information, so we can determine whether
3274 	 * or not the initiator is capable of the things that the user
3275 	 * requests.
3276 	 */
3277 	ccb->ccb_h.func_code = XPT_PATH_INQ;
3278 	if (cam_send_ccb(device, ccb) < 0) {
3279 		perror("error sending XPT_PATH_INQ CCB");
3280 		if (arglist & CAM_ARG_VERBOSE) {
3281 			cam_error_print(device, ccb, CAM_ESF_ALL,
3282 					CAM_EPF_ALL, stderr);
3283 		}
3284 		retval = 1;
3285 		goto ratecontrol_bailout;
3286 	}
3287 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3288 		warnx("XPT_PATH_INQ CCB failed");
3289 		if (arglist & CAM_ARG_VERBOSE) {
3290 			cam_error_print(device, ccb, CAM_ESF_ALL,
3291 					CAM_EPF_ALL, stderr);
3292 		}
3293 		retval = 1;
3294 		goto ratecontrol_bailout;
3295 	}
3296 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3297 	bzero(&(&ccb->ccb_h)[1],
3298 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3299 	if (quiet == 0) {
3300 		fprintf(stdout, "%s parameters:\n",
3301 		    user_settings ? "User" : "Current");
3302 	}
3303 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3304 	if (retval != 0)
3305 		goto ratecontrol_bailout;
3306 
3307 	if (arglist & CAM_ARG_VERBOSE)
3308 		cpi_print(&cpi);
3309 
3310 	if (change_settings) {
3311 		int didsettings = 0;
3312 		struct ccb_trans_settings_spi *spi = NULL;
3313 		struct ccb_trans_settings_ata *ata = NULL;
3314 		struct ccb_trans_settings_sata *sata = NULL;
3315 		struct ccb_trans_settings_scsi *scsi = NULL;
3316 
3317 		if (ccb->cts.transport == XPORT_SPI)
3318 			spi = &ccb->cts.xport_specific.spi;
3319 		if (ccb->cts.transport == XPORT_ATA)
3320 			ata = &ccb->cts.xport_specific.ata;
3321 		if (ccb->cts.transport == XPORT_SATA)
3322 			sata = &ccb->cts.xport_specific.sata;
3323 		if (ccb->cts.protocol == PROTO_SCSI)
3324 			scsi = &ccb->cts.proto_specific.scsi;
3325 		ccb->cts.xport_specific.valid = 0;
3326 		ccb->cts.proto_specific.valid = 0;
3327 		if (spi && disc_enable != -1) {
3328 			spi->valid |= CTS_SPI_VALID_DISC;
3329 			if (disc_enable == 0)
3330 				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3331 			else
3332 				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3333 		}
3334 		if (scsi && tag_enable != -1) {
3335 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3336 				warnx("HBA does not support tagged queueing, "
3337 				      "so you cannot modify tag settings");
3338 				retval = 1;
3339 				goto ratecontrol_bailout;
3340 			}
3341 			scsi->valid |= CTS_SCSI_VALID_TQ;
3342 			if (tag_enable == 0)
3343 				scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3344 			else
3345 				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3346 			didsettings++;
3347 		}
3348 		if (spi && offset != -1) {
3349 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3350 				warnx("HBA is not capable of changing offset");
3351 				retval = 1;
3352 				goto ratecontrol_bailout;
3353 			}
3354 			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3355 			spi->sync_offset = offset;
3356 			didsettings++;
3357 		}
3358 		if (spi && syncrate != -1) {
3359 			int prelim_sync_period;
3360 			u_int freq;
3361 
3362 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3363 				warnx("HBA is not capable of changing "
3364 				      "transfer rates");
3365 				retval = 1;
3366 				goto ratecontrol_bailout;
3367 			}
3368 			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3369 			/*
3370 			 * The sync rate the user gives us is in MHz.
3371 			 * We need to translate it into KHz for this
3372 			 * calculation.
3373 			 */
3374 			syncrate *= 1000;
3375 			/*
3376 			 * Next, we calculate a "preliminary" sync period
3377 			 * in tenths of a nanosecond.
3378 			 */
3379 			if (syncrate == 0)
3380 				prelim_sync_period = 0;
3381 			else
3382 				prelim_sync_period = 10000000 / syncrate;
3383 			spi->sync_period =
3384 				scsi_calc_syncparam(prelim_sync_period);
3385 			freq = scsi_calc_syncsrate(spi->sync_period);
3386 			didsettings++;
3387 		}
3388 		if (sata && syncrate != -1) {
3389 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3390 				warnx("HBA is not capable of changing "
3391 				      "transfer rates");
3392 				retval = 1;
3393 				goto ratecontrol_bailout;
3394 			}
3395 			sata->revision = ata_speed2revision(syncrate * 100);
3396 			if (sata->revision < 0) {
3397 				warnx("Invalid rate %f", syncrate);
3398 				retval = 1;
3399 				goto ratecontrol_bailout;
3400 			}
3401 			sata->valid |= CTS_SATA_VALID_REVISION;
3402 			didsettings++;
3403 		}
3404 		if ((ata || sata) && mode != -1) {
3405 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3406 				warnx("HBA is not capable of changing "
3407 				      "transfer rates");
3408 				retval = 1;
3409 				goto ratecontrol_bailout;
3410 			}
3411 			if (ata) {
3412 				ata->mode = mode;
3413 				ata->valid |= CTS_ATA_VALID_MODE;
3414 			} else {
3415 				sata->mode = mode;
3416 				sata->valid |= CTS_SATA_VALID_MODE;
3417 			}
3418 			didsettings++;
3419 		}
3420 		/*
3421 		 * The bus_width argument goes like this:
3422 		 * 0 == 8 bit
3423 		 * 1 == 16 bit
3424 		 * 2 == 32 bit
3425 		 * Therefore, if you shift the number of bits given on the
3426 		 * command line right by 4, you should get the correct
3427 		 * number.
3428 		 */
3429 		if (spi && bus_width != -1) {
3430 			/*
3431 			 * We might as well validate things here with a
3432 			 * decipherable error message, rather than what
3433 			 * will probably be an indecipherable error message
3434 			 * by the time it gets back to us.
3435 			 */
3436 			if ((bus_width == 16)
3437 			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3438 				warnx("HBA does not support 16 bit bus width");
3439 				retval = 1;
3440 				goto ratecontrol_bailout;
3441 			} else if ((bus_width == 32)
3442 				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3443 				warnx("HBA does not support 32 bit bus width");
3444 				retval = 1;
3445 				goto ratecontrol_bailout;
3446 			} else if ((bus_width != 8)
3447 				&& (bus_width != 16)
3448 				&& (bus_width != 32)) {
3449 				warnx("Invalid bus width %d", bus_width);
3450 				retval = 1;
3451 				goto ratecontrol_bailout;
3452 			}
3453 			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3454 			spi->bus_width = bus_width >> 4;
3455 			didsettings++;
3456 		}
3457 		if  (didsettings == 0) {
3458 			goto ratecontrol_bailout;
3459 		}
3460 		if  (!user_settings && (ata || sata)) {
3461 			warnx("You can modify only user settings for ATA/SATA");
3462 			retval = 1;
3463 			goto ratecontrol_bailout;
3464 		}
3465 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3466 		if (cam_send_ccb(device, ccb) < 0) {
3467 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3468 			if (arglist & CAM_ARG_VERBOSE) {
3469 				cam_error_print(device, ccb, CAM_ESF_ALL,
3470 						CAM_EPF_ALL, stderr);
3471 			}
3472 			retval = 1;
3473 			goto ratecontrol_bailout;
3474 		}
3475 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3476 			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3477 			if (arglist & CAM_ARG_VERBOSE) {
3478 				cam_error_print(device, ccb, CAM_ESF_ALL,
3479 						CAM_EPF_ALL, stderr);
3480 			}
3481 			retval = 1;
3482 			goto ratecontrol_bailout;
3483 		}
3484 	}
3485 	if (send_tur) {
3486 		retval = testunitready(device, retry_count, timeout,
3487 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3488 		/*
3489 		 * If the TUR didn't succeed, just bail.
3490 		 */
3491 		if (retval != 0) {
3492 			if (quiet == 0)
3493 				fprintf(stderr, "Test Unit Ready failed\n");
3494 			goto ratecontrol_bailout;
3495 		}
3496 		/*
3497 		 * If the user wants things quiet, there's no sense in
3498 		 * getting the transfer settings, if we're not going
3499 		 * to print them.
3500 		 */
3501 		if (quiet != 0)
3502 			goto ratecontrol_bailout;
3503 		fprintf(stdout, "New parameters:\n");
3504 		retval = get_print_cts(device, user_settings, 0, NULL);
3505 	}
3506 
3507 ratecontrol_bailout:
3508 	cam_freeccb(ccb);
3509 	return(retval);
3510 }
3511 
3512 static int
3513 scsiformat(struct cam_device *device, int argc, char **argv,
3514 	   char *combinedopt, int retry_count, int timeout)
3515 {
3516 	union ccb *ccb;
3517 	int c;
3518 	int ycount = 0, quiet = 0;
3519 	int error = 0, response = 0, retval = 0;
3520 	int use_timeout = 10800 * 1000;
3521 	int immediate = 1;
3522 	struct format_defect_list_header fh;
3523 	u_int8_t *data_ptr = NULL;
3524 	u_int32_t dxfer_len = 0;
3525 	u_int8_t byte2 = 0;
3526 	int num_warnings = 0;
3527 	int reportonly = 0;
3528 
3529 	ccb = cam_getccb(device);
3530 
3531 	if (ccb == NULL) {
3532 		warnx("scsiformat: error allocating ccb");
3533 		return(1);
3534 	}
3535 
3536 	bzero(&(&ccb->ccb_h)[1],
3537 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3538 
3539 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3540 		switch(c) {
3541 		case 'q':
3542 			quiet++;
3543 			break;
3544 		case 'r':
3545 			reportonly = 1;
3546 			break;
3547 		case 'w':
3548 			immediate = 0;
3549 			break;
3550 		case 'y':
3551 			ycount++;
3552 			break;
3553 		}
3554 	}
3555 
3556 	if (reportonly)
3557 		goto doreport;
3558 
3559 	if (quiet == 0) {
3560 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3561 			"following device:\n");
3562 
3563 		error = scsidoinquiry(device, argc, argv, combinedopt,
3564 				      retry_count, timeout);
3565 
3566 		if (error != 0) {
3567 			warnx("scsiformat: error sending inquiry");
3568 			goto scsiformat_bailout;
3569 		}
3570 	}
3571 
3572 	if (ycount == 0) {
3573 
3574 		do {
3575 			char str[1024];
3576 
3577 			fprintf(stdout, "Are you SURE you want to do "
3578 				"this? (yes/no) ");
3579 
3580 			if (fgets(str, sizeof(str), stdin) != NULL) {
3581 
3582 				if (strncasecmp(str, "yes", 3) == 0)
3583 					response = 1;
3584 				else if (strncasecmp(str, "no", 2) == 0)
3585 					response = -1;
3586 				else {
3587 					fprintf(stdout, "Please answer"
3588 						" \"yes\" or \"no\"\n");
3589 				}
3590 			}
3591 		} while (response == 0);
3592 
3593 		if (response == -1) {
3594 			error = 1;
3595 			goto scsiformat_bailout;
3596 		}
3597 	}
3598 
3599 	if (timeout != 0)
3600 		use_timeout = timeout;
3601 
3602 	if (quiet == 0) {
3603 		fprintf(stdout, "Current format timeout is %d seconds\n",
3604 			use_timeout / 1000);
3605 	}
3606 
3607 	/*
3608 	 * If the user hasn't disabled questions and didn't specify a
3609 	 * timeout on the command line, ask them if they want the current
3610 	 * timeout.
3611 	 */
3612 	if ((ycount == 0)
3613 	 && (timeout == 0)) {
3614 		char str[1024];
3615 		int new_timeout = 0;
3616 
3617 		fprintf(stdout, "Enter new timeout in seconds or press\n"
3618 			"return to keep the current timeout [%d] ",
3619 			use_timeout / 1000);
3620 
3621 		if (fgets(str, sizeof(str), stdin) != NULL) {
3622 			if (str[0] != '\0')
3623 				new_timeout = atoi(str);
3624 		}
3625 
3626 		if (new_timeout != 0) {
3627 			use_timeout = new_timeout * 1000;
3628 			fprintf(stdout, "Using new timeout value %d\n",
3629 				use_timeout / 1000);
3630 		}
3631 	}
3632 
3633 	/*
3634 	 * Keep this outside the if block below to silence any unused
3635 	 * variable warnings.
3636 	 */
3637 	bzero(&fh, sizeof(fh));
3638 
3639 	/*
3640 	 * If we're in immediate mode, we've got to include the format
3641 	 * header
3642 	 */
3643 	if (immediate != 0) {
3644 		fh.byte2 = FU_DLH_IMMED;
3645 		data_ptr = (u_int8_t *)&fh;
3646 		dxfer_len = sizeof(fh);
3647 		byte2 = FU_FMT_DATA;
3648 	} else if (quiet == 0) {
3649 		fprintf(stdout, "Formatting...");
3650 		fflush(stdout);
3651 	}
3652 
3653 	scsi_format_unit(&ccb->csio,
3654 			 /* retries */ retry_count,
3655 			 /* cbfcnp */ NULL,
3656 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
3657 			 /* byte2 */ byte2,
3658 			 /* ileave */ 0,
3659 			 /* data_ptr */ data_ptr,
3660 			 /* dxfer_len */ dxfer_len,
3661 			 /* sense_len */ SSD_FULL_SIZE,
3662 			 /* timeout */ use_timeout);
3663 
3664 	/* Disable freezing the device queue */
3665 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3666 
3667 	if (arglist & CAM_ARG_ERR_RECOVER)
3668 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3669 
3670 	if (((retval = cam_send_ccb(device, ccb)) < 0)
3671 	 || ((immediate == 0)
3672 	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3673 		const char errstr[] = "error sending format command";
3674 
3675 		if (retval < 0)
3676 			warn(errstr);
3677 		else
3678 			warnx(errstr);
3679 
3680 		if (arglist & CAM_ARG_VERBOSE) {
3681 			cam_error_print(device, ccb, CAM_ESF_ALL,
3682 					CAM_EPF_ALL, stderr);
3683 		}
3684 		error = 1;
3685 		goto scsiformat_bailout;
3686 	}
3687 
3688 	/*
3689 	 * If we ran in non-immediate mode, we already checked for errors
3690 	 * above and printed out any necessary information.  If we're in
3691 	 * immediate mode, we need to loop through and get status
3692 	 * information periodically.
3693 	 */
3694 	if (immediate == 0) {
3695 		if (quiet == 0) {
3696 			fprintf(stdout, "Format Complete\n");
3697 		}
3698 		goto scsiformat_bailout;
3699 	}
3700 
3701 doreport:
3702 	do {
3703 		cam_status status;
3704 
3705 		bzero(&(&ccb->ccb_h)[1],
3706 		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3707 
3708 		/*
3709 		 * There's really no need to do error recovery or
3710 		 * retries here, since we're just going to sit in a
3711 		 * loop and wait for the device to finish formatting.
3712 		 */
3713 		scsi_test_unit_ready(&ccb->csio,
3714 				     /* retries */ 0,
3715 				     /* cbfcnp */ NULL,
3716 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
3717 				     /* sense_len */ SSD_FULL_SIZE,
3718 				     /* timeout */ 5000);
3719 
3720 		/* Disable freezing the device queue */
3721 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3722 
3723 		retval = cam_send_ccb(device, ccb);
3724 
3725 		/*
3726 		 * If we get an error from the ioctl, bail out.  SCSI
3727 		 * errors are expected.
3728 		 */
3729 		if (retval < 0) {
3730 			warn("error sending CAMIOCOMMAND ioctl");
3731 			if (arglist & CAM_ARG_VERBOSE) {
3732 				cam_error_print(device, ccb, CAM_ESF_ALL,
3733 						CAM_EPF_ALL, stderr);
3734 			}
3735 			error = 1;
3736 			goto scsiformat_bailout;
3737 		}
3738 
3739 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
3740 
3741 		if ((status != CAM_REQ_CMP)
3742 		 && (status == CAM_SCSI_STATUS_ERROR)
3743 		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3744 			struct scsi_sense_data *sense;
3745 			int error_code, sense_key, asc, ascq;
3746 
3747 			sense = &ccb->csio.sense_data;
3748 			scsi_extract_sense(sense, &error_code, &sense_key,
3749 					   &asc, &ascq);
3750 
3751 			/*
3752 			 * According to the SCSI-2 and SCSI-3 specs, a
3753 			 * drive that is in the middle of a format should
3754 			 * return NOT READY with an ASC of "logical unit
3755 			 * not ready, format in progress".  The sense key
3756 			 * specific bytes will then be a progress indicator.
3757 			 */
3758 			if ((sense_key == SSD_KEY_NOT_READY)
3759 			 && (asc == 0x04) && (ascq == 0x04)) {
3760 				if ((sense->extra_len >= 10)
3761 				 && ((sense->sense_key_spec[0] &
3762 				      SSD_SCS_VALID) != 0)
3763 				 && (quiet == 0)) {
3764 					int val;
3765 					u_int64_t percentage;
3766 
3767 					val = scsi_2btoul(
3768 						&sense->sense_key_spec[1]);
3769 					percentage = 10000 * val;
3770 
3771 					fprintf(stdout,
3772 						"\rFormatting:  %ju.%02u %% "
3773 						"(%d/%d) done",
3774 						(uintmax_t)(percentage /
3775 						(0x10000 * 100)),
3776 						(unsigned)((percentage /
3777 						0x10000) % 100),
3778 						val, 0x10000);
3779 					fflush(stdout);
3780 				} else if ((quiet == 0)
3781 					&& (++num_warnings <= 1)) {
3782 					warnx("Unexpected SCSI Sense Key "
3783 					      "Specific value returned "
3784 					      "during format:");
3785 					scsi_sense_print(device, &ccb->csio,
3786 							 stderr);
3787 					warnx("Unable to print status "
3788 					      "information, but format will "
3789 					      "proceed.");
3790 					warnx("will exit when format is "
3791 					      "complete");
3792 				}
3793 				sleep(1);
3794 			} else {
3795 				warnx("Unexpected SCSI error during format");
3796 				cam_error_print(device, ccb, CAM_ESF_ALL,
3797 						CAM_EPF_ALL, stderr);
3798 				error = 1;
3799 				goto scsiformat_bailout;
3800 			}
3801 
3802 		} else if (status != CAM_REQ_CMP) {
3803 			warnx("Unexpected CAM status %#x", status);
3804 			if (arglist & CAM_ARG_VERBOSE)
3805 				cam_error_print(device, ccb, CAM_ESF_ALL,
3806 						CAM_EPF_ALL, stderr);
3807 			error = 1;
3808 			goto scsiformat_bailout;
3809 		}
3810 
3811 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3812 
3813 	if (quiet == 0)
3814 		fprintf(stdout, "\nFormat Complete\n");
3815 
3816 scsiformat_bailout:
3817 
3818 	cam_freeccb(ccb);
3819 
3820 	return(error);
3821 }
3822 
3823 static int
3824 scsireportluns(struct cam_device *device, int argc, char **argv,
3825 	       char *combinedopt, int retry_count, int timeout)
3826 {
3827 	union ccb *ccb;
3828 	int c, countonly, lunsonly;
3829 	struct scsi_report_luns_data *lundata;
3830 	int alloc_len;
3831 	uint8_t report_type;
3832 	uint32_t list_len, i, j;
3833 	int retval;
3834 
3835 	retval = 0;
3836 	lundata = NULL;
3837 	report_type = RPL_REPORT_DEFAULT;
3838 	ccb = cam_getccb(device);
3839 
3840 	if (ccb == NULL) {
3841 		warnx("%s: error allocating ccb", __func__);
3842 		return (1);
3843 	}
3844 
3845 	bzero(&(&ccb->ccb_h)[1],
3846 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3847 
3848 	countonly = 0;
3849 	lunsonly = 0;
3850 
3851 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3852 		switch (c) {
3853 		case 'c':
3854 			countonly++;
3855 			break;
3856 		case 'l':
3857 			lunsonly++;
3858 			break;
3859 		case 'r':
3860 			if (strcasecmp(optarg, "default") == 0)
3861 				report_type = RPL_REPORT_DEFAULT;
3862 			else if (strcasecmp(optarg, "wellknown") == 0)
3863 				report_type = RPL_REPORT_WELLKNOWN;
3864 			else if (strcasecmp(optarg, "all") == 0)
3865 				report_type = RPL_REPORT_ALL;
3866 			else {
3867 				warnx("%s: invalid report type \"%s\"",
3868 				      __func__, optarg);
3869 				retval = 1;
3870 				goto bailout;
3871 			}
3872 			break;
3873 		default:
3874 			break;
3875 		}
3876 	}
3877 
3878 	if ((countonly != 0)
3879 	 && (lunsonly != 0)) {
3880 		warnx("%s: you can only specify one of -c or -l", __func__);
3881 		retval = 1;
3882 		goto bailout;
3883 	}
3884 	/*
3885 	 * According to SPC-4, the allocation length must be at least 16
3886 	 * bytes -- enough for the header and one LUN.
3887 	 */
3888 	alloc_len = sizeof(*lundata) + 8;
3889 
3890 retry:
3891 
3892 	lundata = malloc(alloc_len);
3893 
3894 	if (lundata == NULL) {
3895 		warn("%s: error mallocing %d bytes", __func__, alloc_len);
3896 		retval = 1;
3897 		goto bailout;
3898 	}
3899 
3900 	scsi_report_luns(&ccb->csio,
3901 			 /*retries*/ retry_count,
3902 			 /*cbfcnp*/ NULL,
3903 			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3904 			 /*select_report*/ report_type,
3905 			 /*rpl_buf*/ lundata,
3906 			 /*alloc_len*/ alloc_len,
3907 			 /*sense_len*/ SSD_FULL_SIZE,
3908 			 /*timeout*/ timeout ? timeout : 5000);
3909 
3910 	/* Disable freezing the device queue */
3911 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3912 
3913 	if (arglist & CAM_ARG_ERR_RECOVER)
3914 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3915 
3916 	if (cam_send_ccb(device, ccb) < 0) {
3917 		warn("error sending REPORT LUNS command");
3918 
3919 		if (arglist & CAM_ARG_VERBOSE)
3920 			cam_error_print(device, ccb, CAM_ESF_ALL,
3921 					CAM_EPF_ALL, stderr);
3922 
3923 		retval = 1;
3924 		goto bailout;
3925 	}
3926 
3927 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3928 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3929 		retval = 1;
3930 		goto bailout;
3931 	}
3932 
3933 
3934 	list_len = scsi_4btoul(lundata->length);
3935 
3936 	/*
3937 	 * If we need to list the LUNs, and our allocation
3938 	 * length was too short, reallocate and retry.
3939 	 */
3940 	if ((countonly == 0)
3941 	 && (list_len > (alloc_len - sizeof(*lundata)))) {
3942 		alloc_len = list_len + sizeof(*lundata);
3943 		free(lundata);
3944 		goto retry;
3945 	}
3946 
3947 	if (lunsonly == 0)
3948 		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
3949 			((list_len / 8) > 1) ? "s" : "");
3950 
3951 	if (countonly != 0)
3952 		goto bailout;
3953 
3954 	for (i = 0; i < (list_len / 8); i++) {
3955 		int no_more;
3956 
3957 		no_more = 0;
3958 		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
3959 			if (j != 0)
3960 				fprintf(stdout, ",");
3961 			switch (lundata->luns[i].lundata[j] &
3962 				RPL_LUNDATA_ATYP_MASK) {
3963 			case RPL_LUNDATA_ATYP_PERIPH:
3964 				if ((lundata->luns[i].lundata[j] &
3965 				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
3966 					fprintf(stdout, "%d:",
3967 						lundata->luns[i].lundata[j] &
3968 						RPL_LUNDATA_PERIPH_BUS_MASK);
3969 				else if ((j == 0)
3970 				      && ((lundata->luns[i].lundata[j+2] &
3971 					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
3972 					no_more = 1;
3973 
3974 				fprintf(stdout, "%d",
3975 					lundata->luns[i].lundata[j+1]);
3976 				break;
3977 			case RPL_LUNDATA_ATYP_FLAT: {
3978 				uint8_t tmplun[2];
3979 				tmplun[0] = lundata->luns[i].lundata[j] &
3980 					RPL_LUNDATA_FLAT_LUN_MASK;
3981 				tmplun[1] = lundata->luns[i].lundata[j+1];
3982 
3983 				fprintf(stdout, "%d", scsi_2btoul(tmplun));
3984 				no_more = 1;
3985 				break;
3986 			}
3987 			case RPL_LUNDATA_ATYP_LUN:
3988 				fprintf(stdout, "%d:%d:%d",
3989 					(lundata->luns[i].lundata[j+1] &
3990 					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
3991 					lundata->luns[i].lundata[j] &
3992 					RPL_LUNDATA_LUN_TARG_MASK,
3993 					lundata->luns[i].lundata[j+1] &
3994 					RPL_LUNDATA_LUN_LUN_MASK);
3995 				break;
3996 			case RPL_LUNDATA_ATYP_EXTLUN: {
3997 				int field_len, field_len_code, eam_code;
3998 
3999 				eam_code = lundata->luns[i].lundata[j] &
4000 					RPL_LUNDATA_EXT_EAM_MASK;
4001 				field_len_code = (lundata->luns[i].lundata[j] &
4002 					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4003 				field_len = field_len_code * 2;
4004 
4005 				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4006 				 && (field_len_code == 0x00)) {
4007 					fprintf(stdout, "%d",
4008 						lundata->luns[i].lundata[j+1]);
4009 				} else if ((eam_code ==
4010 					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4011 					&& (field_len_code == 0x03)) {
4012 					uint8_t tmp_lun[8];
4013 
4014 					/*
4015 					 * This format takes up all 8 bytes.
4016 					 * If we aren't starting at offset 0,
4017 					 * that's a bug.
4018 					 */
4019 					if (j != 0) {
4020 						fprintf(stdout, "Invalid "
4021 							"offset %d for "
4022 							"Extended LUN not "
4023 							"specified format", j);
4024 						no_more = 1;
4025 						break;
4026 					}
4027 					bzero(tmp_lun, sizeof(tmp_lun));
4028 					bcopy(&lundata->luns[i].lundata[j+1],
4029 					      &tmp_lun[1], sizeof(tmp_lun) - 1);
4030 					fprintf(stdout, "%#jx",
4031 					       (intmax_t)scsi_8btou64(tmp_lun));
4032 					no_more = 1;
4033 				} else {
4034 					fprintf(stderr, "Unknown Extended LUN"
4035 						"Address method %#x, length "
4036 						"code %#x", eam_code,
4037 						field_len_code);
4038 					no_more = 1;
4039 				}
4040 				break;
4041 			}
4042 			default:
4043 				fprintf(stderr, "Unknown LUN address method "
4044 					"%#x\n", lundata->luns[i].lundata[0] &
4045 					RPL_LUNDATA_ATYP_MASK);
4046 				break;
4047 			}
4048 			/*
4049 			 * For the flat addressing method, there are no
4050 			 * other levels after it.
4051 			 */
4052 			if (no_more != 0)
4053 				break;
4054 		}
4055 		fprintf(stdout, "\n");
4056 	}
4057 
4058 bailout:
4059 
4060 	cam_freeccb(ccb);
4061 
4062 	free(lundata);
4063 
4064 	return (retval);
4065 }
4066 
4067 static int
4068 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4069 		 char *combinedopt, int retry_count, int timeout)
4070 {
4071 	union ccb *ccb;
4072 	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4073 	struct scsi_read_capacity_data rcap;
4074 	struct scsi_read_capacity_data_long rcaplong;
4075 	uint64_t maxsector;
4076 	uint32_t block_len;
4077 	int retval;
4078 	int c;
4079 
4080 	blocksizeonly = 0;
4081 	humanize = 0;
4082 	numblocks = 0;
4083 	quiet = 0;
4084 	sizeonly = 0;
4085 	baseten = 0;
4086 	retval = 0;
4087 
4088 	ccb = cam_getccb(device);
4089 
4090 	if (ccb == NULL) {
4091 		warnx("%s: error allocating ccb", __func__);
4092 		return (1);
4093 	}
4094 
4095 	bzero(&(&ccb->ccb_h)[1],
4096 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4097 
4098 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4099 		switch (c) {
4100 		case 'b':
4101 			blocksizeonly++;
4102 			break;
4103 		case 'h':
4104 			humanize++;
4105 			baseten = 0;
4106 			break;
4107 		case 'H':
4108 			humanize++;
4109 			baseten++;
4110 			break;
4111 		case 'N':
4112 			numblocks++;
4113 			break;
4114 		case 'q':
4115 			quiet++;
4116 			break;
4117 		case 's':
4118 			sizeonly++;
4119 			break;
4120 		default:
4121 			break;
4122 		}
4123 	}
4124 
4125 	if ((blocksizeonly != 0)
4126 	 && (numblocks != 0)) {
4127 		warnx("%s: you can only specify one of -b or -N", __func__);
4128 		retval = 1;
4129 		goto bailout;
4130 	}
4131 
4132 	if ((blocksizeonly != 0)
4133 	 && (sizeonly != 0)) {
4134 		warnx("%s: you can only specify one of -b or -s", __func__);
4135 		retval = 1;
4136 		goto bailout;
4137 	}
4138 
4139 	if ((humanize != 0)
4140 	 && (quiet != 0)) {
4141 		warnx("%s: you can only specify one of -h/-H or -q", __func__);
4142 		retval = 1;
4143 		goto bailout;
4144 	}
4145 
4146 	if ((humanize != 0)
4147 	 && (blocksizeonly != 0)) {
4148 		warnx("%s: you can only specify one of -h/-H or -b", __func__);
4149 		retval = 1;
4150 		goto bailout;
4151 	}
4152 
4153 	scsi_read_capacity(&ccb->csio,
4154 			   /*retries*/ retry_count,
4155 			   /*cbfcnp*/ NULL,
4156 			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
4157 			   &rcap,
4158 			   SSD_FULL_SIZE,
4159 			   /*timeout*/ timeout ? timeout : 5000);
4160 
4161 	/* Disable freezing the device queue */
4162 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4163 
4164 	if (arglist & CAM_ARG_ERR_RECOVER)
4165 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4166 
4167 	if (cam_send_ccb(device, ccb) < 0) {
4168 		warn("error sending READ CAPACITY command");
4169 
4170 		if (arglist & CAM_ARG_VERBOSE)
4171 			cam_error_print(device, ccb, CAM_ESF_ALL,
4172 					CAM_EPF_ALL, stderr);
4173 
4174 		retval = 1;
4175 		goto bailout;
4176 	}
4177 
4178 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4179 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4180 		retval = 1;
4181 		goto bailout;
4182 	}
4183 
4184 	maxsector = scsi_4btoul(rcap.addr);
4185 	block_len = scsi_4btoul(rcap.length);
4186 
4187 	/*
4188 	 * A last block of 2^32-1 means that the true capacity is over 2TB,
4189 	 * and we need to issue the long READ CAPACITY to get the real
4190 	 * capacity.  Otherwise, we're all set.
4191 	 */
4192 	if (maxsector != 0xffffffff)
4193 		goto do_print;
4194 
4195 	scsi_read_capacity_16(&ccb->csio,
4196 			      /*retries*/ retry_count,
4197 			      /*cbfcnp*/ NULL,
4198 			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
4199 			      /*lba*/ 0,
4200 			      /*reladdr*/ 0,
4201 			      /*pmi*/ 0,
4202 			      &rcaplong,
4203 			      /*sense_len*/ SSD_FULL_SIZE,
4204 			      /*timeout*/ timeout ? timeout : 5000);
4205 
4206 	/* Disable freezing the device queue */
4207 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4208 
4209 	if (arglist & CAM_ARG_ERR_RECOVER)
4210 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4211 
4212 	if (cam_send_ccb(device, ccb) < 0) {
4213 		warn("error sending READ CAPACITY (16) command");
4214 
4215 		if (arglist & CAM_ARG_VERBOSE)
4216 			cam_error_print(device, ccb, CAM_ESF_ALL,
4217 					CAM_EPF_ALL, stderr);
4218 
4219 		retval = 1;
4220 		goto bailout;
4221 	}
4222 
4223 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4224 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4225 		retval = 1;
4226 		goto bailout;
4227 	}
4228 
4229 	maxsector = scsi_8btou64(rcaplong.addr);
4230 	block_len = scsi_4btoul(rcaplong.length);
4231 
4232 do_print:
4233 	if (blocksizeonly == 0) {
4234 		/*
4235 		 * Humanize implies !quiet, and also implies numblocks.
4236 		 */
4237 		if (humanize != 0) {
4238 			char tmpstr[6];
4239 			int64_t tmpbytes;
4240 			int ret;
4241 
4242 			tmpbytes = (maxsector + 1) * block_len;
4243 			ret = humanize_number(tmpstr, sizeof(tmpstr),
4244 					      tmpbytes, "", HN_AUTOSCALE,
4245 					      HN_B | HN_DECIMAL |
4246 					      ((baseten != 0) ?
4247 					      HN_DIVISOR_1000 : 0));
4248 			if (ret == -1) {
4249 				warnx("%s: humanize_number failed!", __func__);
4250 				retval = 1;
4251 				goto bailout;
4252 			}
4253 			fprintf(stdout, "Device Size: %s%s", tmpstr,
4254 				(sizeonly == 0) ?  ", " : "\n");
4255 		} else if (numblocks != 0) {
4256 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4257 				"Blocks: " : "", (uintmax_t)maxsector + 1,
4258 				(sizeonly == 0) ? ", " : "\n");
4259 		} else {
4260 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4261 				"Last Block: " : "", (uintmax_t)maxsector,
4262 				(sizeonly == 0) ? ", " : "\n");
4263 		}
4264 	}
4265 	if (sizeonly == 0)
4266 		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4267 			"Block Length: " : "", block_len, (quiet == 0) ?
4268 			" bytes" : "");
4269 bailout:
4270 	cam_freeccb(ccb);
4271 
4272 	return (retval);
4273 }
4274 
4275 static int
4276 atapm(struct cam_device *device, int argc, char **argv,
4277 		 char *combinedopt, int retry_count, int timeout)
4278 {
4279 	union ccb *ccb;
4280 	int retval = 0;
4281 	int t = -1;
4282 	int c;
4283 	u_char cmd, sc;
4284 
4285 	ccb = cam_getccb(device);
4286 
4287 	if (ccb == NULL) {
4288 		warnx("%s: error allocating ccb", __func__);
4289 		return (1);
4290 	}
4291 
4292 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4293 		switch (c) {
4294 		case 't':
4295 			t = atoi(optarg);
4296 			break;
4297 		default:
4298 			break;
4299 		}
4300 	}
4301 	if (strcmp(argv[1], "idle") == 0) {
4302 		if (t == -1)
4303 			cmd = ATA_IDLE_IMMEDIATE;
4304 		else
4305 			cmd = ATA_IDLE_CMD;
4306 	} else if (strcmp(argv[1], "standby") == 0) {
4307 		if (t == -1)
4308 			cmd = ATA_STANDBY_IMMEDIATE;
4309 		else
4310 			cmd = ATA_STANDBY_CMD;
4311 	} else {
4312 		cmd = ATA_SLEEP;
4313 		t = -1;
4314 	}
4315 	if (t < 0)
4316 		sc = 0;
4317 	else if (t <= (240 * 5))
4318 		sc = t / 5;
4319 	else if (t <= (11 * 30 * 60))
4320 		sc = t / (30 * 60) + 241;
4321 	else
4322 		sc = 253;
4323 	cam_fill_ataio(&ccb->ataio,
4324 		      retry_count,
4325 		      NULL,
4326 		      /*flags*/CAM_DIR_NONE,
4327 		      MSG_SIMPLE_Q_TAG,
4328 		      /*data_ptr*/NULL,
4329 		      /*dxfer_len*/0,
4330 		      timeout ? timeout : 30 * 1000);
4331 	ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
4332 
4333 	/* Disable freezing the device queue */
4334 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4335 
4336 	if (arglist & CAM_ARG_ERR_RECOVER)
4337 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4338 
4339 	if (cam_send_ccb(device, ccb) < 0) {
4340 		warn("error sending command");
4341 
4342 		if (arglist & CAM_ARG_VERBOSE)
4343 			cam_error_print(device, ccb, CAM_ESF_ALL,
4344 					CAM_EPF_ALL, stderr);
4345 
4346 		retval = 1;
4347 		goto bailout;
4348 	}
4349 
4350 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4351 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4352 		retval = 1;
4353 		goto bailout;
4354 	}
4355 bailout:
4356 	cam_freeccb(ccb);
4357 	return (retval);
4358 }
4359 
4360 #endif /* MINIMALISTIC */
4361 
4362 void
4363 usage(int verbose)
4364 {
4365 	fprintf(verbose ? stdout : stderr,
4366 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
4367 "        camcontrol devlist    [-v]\n"
4368 #ifndef MINIMALISTIC
4369 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
4370 "        camcontrol tur        [dev_id][generic args]\n"
4371 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
4372 "        camcontrol identify   [dev_id][generic args] [-v]\n"
4373 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
4374 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
4375 "                              [-q] [-s]\n"
4376 "        camcontrol start      [dev_id][generic args]\n"
4377 "        camcontrol stop       [dev_id][generic args]\n"
4378 "        camcontrol load       [dev_id][generic args]\n"
4379 "        camcontrol eject      [dev_id][generic args]\n"
4380 #endif /* MINIMALISTIC */
4381 "        camcontrol rescan     <all | bus[:target:lun]>\n"
4382 "        camcontrol reset      <all | bus[:target:lun]>\n"
4383 #ifndef MINIMALISTIC
4384 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
4385 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
4386 "                              [-P pagectl][-e | -b][-d]\n"
4387 "        camcontrol cmd        [dev_id][generic args]\n"
4388 "                              <-a cmd [args] | -c cmd [args]>\n"
4389 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
4390 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
4391 "                              <all|bus[:target[:lun]]|off>\n"
4392 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
4393 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
4394 "                              [-D <enable|disable>][-M mode][-O offset]\n"
4395 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
4396 "                              [-U][-W bus_width]\n"
4397 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
4398 "        camcontrol idle       [dev_id][generic args][-t time]\n"
4399 "        camcontrol standby    [dev_id][generic args][-t time]\n"
4400 "        camcontrol sleep      [dev_id][generic args]\n"
4401 #endif /* MINIMALISTIC */
4402 "        camcontrol help\n");
4403 	if (!verbose)
4404 		return;
4405 #ifndef MINIMALISTIC
4406 	fprintf(stdout,
4407 "Specify one of the following options:\n"
4408 "devlist     list all CAM devices\n"
4409 "periphlist  list all CAM peripheral drivers attached to a device\n"
4410 "tur         send a test unit ready to the named device\n"
4411 "inquiry     send a SCSI inquiry command to the named device\n"
4412 "identify    send a ATA identify command to the named device\n"
4413 "reportluns  send a SCSI report luns command to the device\n"
4414 "readcap     send a SCSI read capacity command to the device\n"
4415 "start       send a Start Unit command to the device\n"
4416 "stop        send a Stop Unit command to the device\n"
4417 "load        send a Start Unit command to the device with the load bit set\n"
4418 "eject       send a Stop Unit command to the device with the eject bit set\n"
4419 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
4420 "reset       reset all busses, the given bus, or bus:target:lun\n"
4421 "defects     read the defect list of the specified device\n"
4422 "modepage    display or edit (-e) the given mode page\n"
4423 "cmd         send the given scsi command, may need -i or -o as well\n"
4424 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
4425 "tags        report or set the number of transaction slots for a device\n"
4426 "negotiate   report or set device negotiation parameters\n"
4427 "format      send the SCSI FORMAT UNIT command to the named device\n"
4428 "idle        send the ATA IDLE command to the named device\n"
4429 "standby     send the ATA STANDBY command to the named device\n"
4430 "sleep       send the ATA SLEEP command to the named device\n"
4431 "help        this message\n"
4432 "Device Identifiers:\n"
4433 "bus:target        specify the bus and target, lun defaults to 0\n"
4434 "bus:target:lun    specify the bus, target and lun\n"
4435 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
4436 "Generic arguments:\n"
4437 "-v                be verbose, print out sense information\n"
4438 "-t timeout        command timeout in seconds, overrides default timeout\n"
4439 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
4440 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
4441 "-E                have the kernel attempt to perform SCSI error recovery\n"
4442 "-C count          specify the SCSI command retry count (needs -E to work)\n"
4443 "modepage arguments:\n"
4444 "-l                list all available mode pages\n"
4445 "-m page           specify the mode page to view or edit\n"
4446 "-e                edit the specified mode page\n"
4447 "-b                force view to binary mode\n"
4448 "-d                disable block descriptors for mode sense\n"
4449 "-P pgctl          page control field 0-3\n"
4450 "defects arguments:\n"
4451 "-f format         specify defect list format (block, bfi or phys)\n"
4452 "-G                get the grown defect list\n"
4453 "-P                get the permanant defect list\n"
4454 "inquiry arguments:\n"
4455 "-D                get the standard inquiry data\n"
4456 "-S                get the serial number\n"
4457 "-R                get the transfer rate, etc.\n"
4458 "reportluns arguments:\n"
4459 "-c                only report a count of available LUNs\n"
4460 "-l                only print out luns, and not a count\n"
4461 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
4462 "readcap arguments\n"
4463 "-b                only report the blocksize\n"
4464 "-h                human readable device size, base 2\n"
4465 "-H                human readable device size, base 10\n"
4466 "-N                print the number of blocks instead of last block\n"
4467 "-q                quiet, print numbers only\n"
4468 "-s                only report the last block/device size\n"
4469 "cmd arguments:\n"
4470 "-c cdb [args]     specify the SCSI CDB\n"
4471 "-i len fmt        specify input data and input data format\n"
4472 "-o len fmt [args] specify output data and output data fmt\n"
4473 "debug arguments:\n"
4474 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
4475 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
4476 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
4477 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
4478 "tags arguments:\n"
4479 "-N tags           specify the number of tags to use for this device\n"
4480 "-q                be quiet, don't report the number of tags\n"
4481 "-v                report a number of tag-related parameters\n"
4482 "negotiate arguments:\n"
4483 "-a                send a test unit ready after negotiation\n"
4484 "-c                report/set current negotiation settings\n"
4485 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
4486 "-M mode           set ATA mode\n"
4487 "-O offset         set command delay offset\n"
4488 "-q                be quiet, don't report anything\n"
4489 "-R syncrate       synchronization rate in MHz\n"
4490 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
4491 "-U                report/set user negotiation settings\n"
4492 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
4493 "-v                also print a Path Inquiry CCB for the controller\n"
4494 "format arguments:\n"
4495 "-q                be quiet, don't print status messages\n"
4496 "-r                run in report only mode\n"
4497 "-w                don't send immediate format command\n"
4498 "-y                don't ask any questions\n"
4499 "idle/standby arguments:\n"
4500 "-t <arg>          number of seconds before respective state.\n");
4501 #endif /* MINIMALISTIC */
4502 }
4503 
4504 int
4505 main(int argc, char **argv)
4506 {
4507 	int c;
4508 	char *device = NULL;
4509 	int unit = 0;
4510 	struct cam_device *cam_dev = NULL;
4511 	int timeout = 0, retry_count = 1;
4512 	camcontrol_optret optreturn;
4513 	char *tstr;
4514 	const char *mainopt = "C:En:t:u:v";
4515 	const char *subopt = NULL;
4516 	char combinedopt[256];
4517 	int error = 0, optstart = 2;
4518 	int devopen = 1;
4519 #ifndef MINIMALISTIC
4520 	int bus, target, lun;
4521 #endif /* MINIMALISTIC */
4522 
4523 	cmdlist = CAM_CMD_NONE;
4524 	arglist = CAM_ARG_NONE;
4525 
4526 	if (argc < 2) {
4527 		usage(0);
4528 		exit(1);
4529 	}
4530 
4531 	/*
4532 	 * Get the base option.
4533 	 */
4534 	optreturn = getoption(argv[1], &cmdlist, &arglist, &subopt);
4535 
4536 	if (optreturn == CC_OR_AMBIGUOUS) {
4537 		warnx("ambiguous option %s", argv[1]);
4538 		usage(0);
4539 		exit(1);
4540 	} else if (optreturn == CC_OR_NOT_FOUND) {
4541 		warnx("option %s not found", argv[1]);
4542 		usage(0);
4543 		exit(1);
4544 	}
4545 
4546 	/*
4547 	 * Ahh, getopt(3) is a pain.
4548 	 *
4549 	 * This is a gross hack.  There really aren't many other good
4550 	 * options (excuse the pun) for parsing options in a situation like
4551 	 * this.  getopt is kinda braindead, so you end up having to run
4552 	 * through the options twice, and give each invocation of getopt
4553 	 * the option string for the other invocation.
4554 	 *
4555 	 * You would think that you could just have two groups of options.
4556 	 * The first group would get parsed by the first invocation of
4557 	 * getopt, and the second group would get parsed by the second
4558 	 * invocation of getopt.  It doesn't quite work out that way.  When
4559 	 * the first invocation of getopt finishes, it leaves optind pointing
4560 	 * to the argument _after_ the first argument in the second group.
4561 	 * So when the second invocation of getopt comes around, it doesn't
4562 	 * recognize the first argument it gets and then bails out.
4563 	 *
4564 	 * A nice alternative would be to have a flag for getopt that says
4565 	 * "just keep parsing arguments even when you encounter an unknown
4566 	 * argument", but there isn't one.  So there's no real clean way to
4567 	 * easily parse two sets of arguments without having one invocation
4568 	 * of getopt know about the other.
4569 	 *
4570 	 * Without this hack, the first invocation of getopt would work as
4571 	 * long as the generic arguments are first, but the second invocation
4572 	 * (in the subfunction) would fail in one of two ways.  In the case
4573 	 * where you don't set optreset, it would fail because optind may be
4574 	 * pointing to the argument after the one it should be pointing at.
4575 	 * In the case where you do set optreset, and reset optind, it would
4576 	 * fail because getopt would run into the first set of options, which
4577 	 * it doesn't understand.
4578 	 *
4579 	 * All of this would "sort of" work if you could somehow figure out
4580 	 * whether optind had been incremented one option too far.  The
4581 	 * mechanics of that, however, are more daunting than just giving
4582 	 * both invocations all of the expect options for either invocation.
4583 	 *
4584 	 * Needless to say, I wouldn't mind if someone invented a better
4585 	 * (non-GPL!) command line parsing interface than getopt.  I
4586 	 * wouldn't mind if someone added more knobs to getopt to make it
4587 	 * work better.  Who knows, I may talk myself into doing it someday,
4588 	 * if the standards weenies let me.  As it is, it just leads to
4589 	 * hackery like this and causes people to avoid it in some cases.
4590 	 *
4591 	 * KDM, September 8th, 1998
4592 	 */
4593 	if (subopt != NULL)
4594 		sprintf(combinedopt, "%s%s", mainopt, subopt);
4595 	else
4596 		sprintf(combinedopt, "%s", mainopt);
4597 
4598 	/*
4599 	 * For these options we do not parse optional device arguments and
4600 	 * we do not open a passthrough device.
4601 	 */
4602 	if ((cmdlist == CAM_CMD_RESCAN)
4603 	 || (cmdlist == CAM_CMD_RESET)
4604 	 || (cmdlist == CAM_CMD_DEVTREE)
4605 	 || (cmdlist == CAM_CMD_USAGE)
4606 	 || (cmdlist == CAM_CMD_DEBUG))
4607 		devopen = 0;
4608 
4609 #ifndef MINIMALISTIC
4610 	if ((devopen == 1)
4611 	 && (argc > 2 && argv[2][0] != '-')) {
4612 		char name[30];
4613 		int rv;
4614 
4615 		if (isdigit(argv[2][0])) {
4616 			/* device specified as bus:target[:lun] */
4617 			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
4618 			if (rv < 2)
4619 				errx(1, "numeric device specification must "
4620 				     "be either bus:target, or "
4621 				     "bus:target:lun");
4622 			/* default to 0 if lun was not specified */
4623 			if ((arglist & CAM_ARG_LUN) == 0) {
4624 				lun = 0;
4625 				arglist |= CAM_ARG_LUN;
4626 			}
4627 			optstart++;
4628 		} else {
4629 			if (cam_get_device(argv[2], name, sizeof name, &unit)
4630 			    == -1)
4631 				errx(1, "%s", cam_errbuf);
4632 			device = strdup(name);
4633 			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
4634 			optstart++;
4635 		}
4636 	}
4637 #endif /* MINIMALISTIC */
4638 	/*
4639 	 * Start getopt processing at argv[2/3], since we've already
4640 	 * accepted argv[1..2] as the command name, and as a possible
4641 	 * device name.
4642 	 */
4643 	optind = optstart;
4644 
4645 	/*
4646 	 * Now we run through the argument list looking for generic
4647 	 * options, and ignoring options that possibly belong to
4648 	 * subfunctions.
4649 	 */
4650 	while ((c = getopt(argc, argv, combinedopt))!= -1){
4651 		switch(c) {
4652 			case 'C':
4653 				retry_count = strtol(optarg, NULL, 0);
4654 				if (retry_count < 0)
4655 					errx(1, "retry count %d is < 0",
4656 					     retry_count);
4657 				arglist |= CAM_ARG_RETRIES;
4658 				break;
4659 			case 'E':
4660 				arglist |= CAM_ARG_ERR_RECOVER;
4661 				break;
4662 			case 'n':
4663 				arglist |= CAM_ARG_DEVICE;
4664 				tstr = optarg;
4665 				while (isspace(*tstr) && (*tstr != '\0'))
4666 					tstr++;
4667 				device = (char *)strdup(tstr);
4668 				break;
4669 			case 't':
4670 				timeout = strtol(optarg, NULL, 0);
4671 				if (timeout < 0)
4672 					errx(1, "invalid timeout %d", timeout);
4673 				/* Convert the timeout from seconds to ms */
4674 				timeout *= 1000;
4675 				arglist |= CAM_ARG_TIMEOUT;
4676 				break;
4677 			case 'u':
4678 				arglist |= CAM_ARG_UNIT;
4679 				unit = strtol(optarg, NULL, 0);
4680 				break;
4681 			case 'v':
4682 				arglist |= CAM_ARG_VERBOSE;
4683 				break;
4684 			default:
4685 				break;
4686 		}
4687 	}
4688 
4689 #ifndef MINIMALISTIC
4690 	/*
4691 	 * For most commands we'll want to open the passthrough device
4692 	 * associated with the specified device.  In the case of the rescan
4693 	 * commands, we don't use a passthrough device at all, just the
4694 	 * transport layer device.
4695 	 */
4696 	if (devopen == 1) {
4697 		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
4698 		 && (((arglist & CAM_ARG_DEVICE) == 0)
4699 		  || ((arglist & CAM_ARG_UNIT) == 0))) {
4700 			errx(1, "subcommand \"%s\" requires a valid device "
4701 			     "identifier", argv[1]);
4702 		}
4703 
4704 		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
4705 				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
4706 				cam_open_spec_device(device,unit,O_RDWR,NULL)))
4707 		     == NULL)
4708 			errx(1,"%s", cam_errbuf);
4709 	}
4710 #endif /* MINIMALISTIC */
4711 
4712 	/*
4713 	 * Reset optind to 2, and reset getopt, so these routines can parse
4714 	 * the arguments again.
4715 	 */
4716 	optind = optstart;
4717 	optreset = 1;
4718 
4719 	switch(cmdlist) {
4720 #ifndef MINIMALISTIC
4721 		case CAM_CMD_DEVLIST:
4722 			error = getdevlist(cam_dev);
4723 			break;
4724 #endif /* MINIMALISTIC */
4725 		case CAM_CMD_DEVTREE:
4726 			error = getdevtree();
4727 			break;
4728 #ifndef MINIMALISTIC
4729 		case CAM_CMD_TUR:
4730 			error = testunitready(cam_dev, retry_count, timeout, 0);
4731 			break;
4732 		case CAM_CMD_INQUIRY:
4733 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
4734 					      retry_count, timeout);
4735 			break;
4736 		case CAM_CMD_IDENTIFY:
4737 			error = ataidentify(cam_dev, retry_count, timeout);
4738 			break;
4739 		case CAM_CMD_STARTSTOP:
4740 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
4741 					  arglist & CAM_ARG_EJECT, retry_count,
4742 					  timeout);
4743 			break;
4744 #endif /* MINIMALISTIC */
4745 		case CAM_CMD_RESCAN:
4746 			error = dorescan_or_reset(argc, argv, 1);
4747 			break;
4748 		case CAM_CMD_RESET:
4749 			error = dorescan_or_reset(argc, argv, 0);
4750 			break;
4751 #ifndef MINIMALISTIC
4752 		case CAM_CMD_READ_DEFECTS:
4753 			error = readdefects(cam_dev, argc, argv, combinedopt,
4754 					    retry_count, timeout);
4755 			break;
4756 		case CAM_CMD_MODE_PAGE:
4757 			modepage(cam_dev, argc, argv, combinedopt,
4758 				 retry_count, timeout);
4759 			break;
4760 		case CAM_CMD_SCSI_CMD:
4761 			error = scsicmd(cam_dev, argc, argv, combinedopt,
4762 					retry_count, timeout);
4763 			break;
4764 		case CAM_CMD_DEBUG:
4765 			error = camdebug(argc, argv, combinedopt);
4766 			break;
4767 		case CAM_CMD_TAG:
4768 			error = tagcontrol(cam_dev, argc, argv, combinedopt);
4769 			break;
4770 		case CAM_CMD_RATE:
4771 			error = ratecontrol(cam_dev, retry_count, timeout,
4772 					    argc, argv, combinedopt);
4773 			break;
4774 		case CAM_CMD_FORMAT:
4775 			error = scsiformat(cam_dev, argc, argv,
4776 					   combinedopt, retry_count, timeout);
4777 			break;
4778 		case CAM_CMD_REPORTLUNS:
4779 			error = scsireportluns(cam_dev, argc, argv,
4780 					       combinedopt, retry_count,
4781 					       timeout);
4782 			break;
4783 		case CAM_CMD_READCAP:
4784 			error = scsireadcapacity(cam_dev, argc, argv,
4785 						 combinedopt, retry_count,
4786 						 timeout);
4787 			break;
4788 		case CAM_CMD_IDLE:
4789 		case CAM_CMD_STANDBY:
4790 		case CAM_CMD_SLEEP:
4791 			error = atapm(cam_dev, argc, argv,
4792 						 combinedopt, retry_count,
4793 						 timeout);
4794 			break;
4795 #endif /* MINIMALISTIC */
4796 		case CAM_CMD_USAGE:
4797 			usage(1);
4798 			break;
4799 		default:
4800 			usage(0);
4801 			error = 1;
4802 			break;
4803 	}
4804 
4805 	if (cam_dev != NULL)
4806 		cam_close_device(cam_dev);
4807 
4808 	exit(error);
4809 }
4810