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