xref: /freebsd/sbin/camcontrol/camcontrol.c (revision c4f6a2a9e1b1879b618c436ab4f56ff75c73a0f5)
1 /*
2  * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002 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  * $FreeBSD$
29  */
30 
31 #include <sys/ioctl.h>
32 #include <sys/types.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <ctype.h>
39 #include <err.h>
40 
41 #include <cam/cam.h>
42 #include <cam/cam_debug.h>
43 #include <cam/cam_ccb.h>
44 #include <cam/scsi/scsi_all.h>
45 #include <cam/scsi/scsi_da.h>
46 #include <cam/scsi/scsi_pass.h>
47 #include <cam/scsi/scsi_message.h>
48 #include <camlib.h>
49 #include "camcontrol.h"
50 
51 typedef enum {
52 	CAM_ARG_NONE		= 0x00000000,
53 	CAM_ARG_DEVLIST		= 0x00000001,
54 	CAM_ARG_TUR		= 0x00000002,
55 	CAM_ARG_INQUIRY		= 0x00000003,
56 	CAM_ARG_STARTSTOP	= 0x00000004,
57 	CAM_ARG_RESCAN		= 0x00000005,
58 	CAM_ARG_READ_DEFECTS	= 0x00000006,
59 	CAM_ARG_MODE_PAGE	= 0x00000007,
60 	CAM_ARG_SCSI_CMD	= 0x00000008,
61 	CAM_ARG_DEVTREE		= 0x00000009,
62 	CAM_ARG_USAGE		= 0x0000000a,
63 	CAM_ARG_DEBUG		= 0x0000000b,
64 	CAM_ARG_RESET		= 0x0000000c,
65 	CAM_ARG_FORMAT		= 0x0000000d,
66 	CAM_ARG_TAG		= 0x0000000e,
67 	CAM_ARG_RATE		= 0x0000000f,
68 	CAM_ARG_OPT_MASK	= 0x0000000f,
69 	CAM_ARG_VERBOSE		= 0x00000010,
70 	CAM_ARG_DEVICE		= 0x00000020,
71 	CAM_ARG_BUS		= 0x00000040,
72 	CAM_ARG_TARGET		= 0x00000080,
73 	CAM_ARG_LUN		= 0x00000100,
74 	CAM_ARG_EJECT		= 0x00000200,
75 	CAM_ARG_UNIT		= 0x00000400,
76 	CAM_ARG_FORMAT_BLOCK	= 0x00000800,
77 	CAM_ARG_FORMAT_BFI	= 0x00001000,
78 	CAM_ARG_FORMAT_PHYS	= 0x00002000,
79 	CAM_ARG_PLIST		= 0x00004000,
80 	CAM_ARG_GLIST		= 0x00008000,
81 	CAM_ARG_GET_SERIAL	= 0x00010000,
82 	CAM_ARG_GET_STDINQ	= 0x00020000,
83 	CAM_ARG_GET_XFERRATE	= 0x00040000,
84 	CAM_ARG_INQ_MASK	= 0x00070000,
85 	CAM_ARG_MODE_EDIT	= 0x00080000,
86 	CAM_ARG_PAGE_CNTL	= 0x00100000,
87 	CAM_ARG_TIMEOUT		= 0x00200000,
88 	CAM_ARG_CMD_IN		= 0x00400000,
89 	CAM_ARG_CMD_OUT		= 0x00800000,
90 	CAM_ARG_DBD		= 0x01000000,
91 	CAM_ARG_ERR_RECOVER	= 0x02000000,
92 	CAM_ARG_RETRIES		= 0x04000000,
93 	CAM_ARG_START_UNIT	= 0x08000000,
94 	CAM_ARG_DEBUG_INFO	= 0x10000000,
95 	CAM_ARG_DEBUG_TRACE	= 0x20000000,
96 	CAM_ARG_DEBUG_SUBTRACE	= 0x40000000,
97 	CAM_ARG_DEBUG_CDB	= 0x80000000,
98 	CAM_ARG_FLAG_MASK	= 0xfffffff0
99 } cam_argmask;
100 
101 struct camcontrol_opts {
102 	char 		*optname;
103 	cam_argmask	argnum;
104 	const char	*subopt;
105 };
106 
107 #ifndef MINIMALISTIC
108 static const char scsicmd_opts[] = "c:i:o:";
109 static const char readdefect_opts[] = "f:GP";
110 static const char negotiate_opts[] = "acD:O:qR:T:UW:";
111 #endif
112 
113 struct camcontrol_opts option_table[] = {
114 #ifndef MINIMALISTIC
115 	{"tur", CAM_ARG_TUR, NULL},
116 	{"inquiry", CAM_ARG_INQUIRY, "DSR"},
117 	{"start", CAM_ARG_STARTSTOP | CAM_ARG_START_UNIT, NULL},
118 	{"stop", CAM_ARG_STARTSTOP, NULL},
119 	{"eject", CAM_ARG_STARTSTOP | CAM_ARG_EJECT, NULL},
120 #endif /* MINIMALISTIC */
121 	{"rescan", CAM_ARG_RESCAN, NULL},
122 	{"reset", CAM_ARG_RESET, NULL},
123 #ifndef MINIMALISTIC
124 	{"cmd", CAM_ARG_SCSI_CMD, scsicmd_opts},
125 	{"command", CAM_ARG_SCSI_CMD, scsicmd_opts},
126 	{"defects", CAM_ARG_READ_DEFECTS, readdefect_opts},
127 	{"defectlist", CAM_ARG_READ_DEFECTS, readdefect_opts},
128 #endif /* MINIMALISTIC */
129 	{"devlist", CAM_ARG_DEVTREE, NULL},
130 #ifndef MINIMALISTIC
131 	{"periphlist", CAM_ARG_DEVLIST, NULL},
132 	{"modepage", CAM_ARG_MODE_PAGE, "bdelm:P:"},
133 	{"tags", CAM_ARG_TAG, "N:q"},
134 	{"negotiate", CAM_ARG_RATE, negotiate_opts},
135 	{"rate", CAM_ARG_RATE, negotiate_opts},
136 	{"debug", CAM_ARG_DEBUG, "ITSc"},
137 	{"format", CAM_ARG_FORMAT, "qwy"},
138 #endif /* MINIMALISTIC */
139 	{"help", CAM_ARG_USAGE, NULL},
140 	{"-?", CAM_ARG_USAGE, NULL},
141 	{"-h", CAM_ARG_USAGE, NULL},
142 	{NULL, 0, NULL}
143 };
144 
145 typedef enum {
146 	CC_OR_NOT_FOUND,
147 	CC_OR_AMBIGUOUS,
148 	CC_OR_FOUND
149 } camcontrol_optret;
150 
151 cam_argmask arglist;
152 int bus, target, lun;
153 
154 
155 camcontrol_optret getoption(char *arg, cam_argmask *argnum, char **subopt);
156 #ifndef MINIMALISTIC
157 static int getdevlist(struct cam_device *device);
158 static int getdevtree(void);
159 static int testunitready(struct cam_device *device, int retry_count,
160 			 int timeout, int quiet);
161 static int scsistart(struct cam_device *device, int startstop, int loadeject,
162 		     int retry_count, int timeout);
163 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
164 			 char *combinedopt, int retry_count, int timeout);
165 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
166 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
167 static int scsixferrate(struct cam_device *device);
168 #endif /* MINIMALISTIC */
169 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
170 		     cam_argmask *arglist);
171 static int dorescan_or_reset(int argc, char **argv, int rescan);
172 static int rescan_or_reset_bus(int bus, int rescan);
173 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
174 #ifndef MINIMALISTIC
175 static int readdefects(struct cam_device *device, int argc, char **argv,
176 		       char *combinedopt, int retry_count, int timeout);
177 static void modepage(struct cam_device *device, int argc, char **argv,
178 		     char *combinedopt, int retry_count, int timeout);
179 static int scsicmd(struct cam_device *device, int argc, char **argv,
180 		   char *combinedopt, int retry_count, int timeout);
181 static int tagcontrol(struct cam_device *device, int argc, char **argv,
182 		      char *combinedopt);
183 static void cts_print(struct cam_device *device,
184 		      struct ccb_trans_settings *cts);
185 static void cpi_print(struct ccb_pathinq *cpi);
186 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
187 static int get_print_cts(struct cam_device *device, int user_settings,
188 			 int quiet, struct ccb_trans_settings *cts);
189 static int ratecontrol(struct cam_device *device, int retry_count,
190 		       int timeout, int argc, char **argv, char *combinedopt);
191 static int scsiformat(struct cam_device *device, int argc, char **argv,
192 		      char *combinedopt, int retry_count, int timeout);
193 #endif /* MINIMALISTIC */
194 
195 camcontrol_optret
196 getoption(char *arg, cam_argmask *argnum, char **subopt)
197 {
198 	struct camcontrol_opts *opts;
199 	int num_matches = 0;
200 
201 	for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
202 	     opts++) {
203 		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
204 			*argnum = opts->argnum;
205 			*subopt = (char *)opts->subopt;
206 			if (++num_matches > 1)
207 				return(CC_OR_AMBIGUOUS);
208 		}
209 	}
210 
211 	if (num_matches > 0)
212 		return(CC_OR_FOUND);
213 	else
214 		return(CC_OR_NOT_FOUND);
215 }
216 
217 #ifndef MINIMALISTIC
218 static int
219 getdevlist(struct cam_device *device)
220 {
221 	union ccb *ccb;
222 	char status[32];
223 	int error = 0;
224 
225 	ccb = cam_getccb(device);
226 
227 	ccb->ccb_h.func_code = XPT_GDEVLIST;
228 	ccb->ccb_h.flags = CAM_DIR_NONE;
229 	ccb->ccb_h.retry_count = 1;
230 	ccb->cgdl.index = 0;
231 	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
232 	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
233 		if (cam_send_ccb(device, ccb) < 0) {
234 			perror("error getting device list");
235 			cam_freeccb(ccb);
236 			return(1);
237 		}
238 
239 		status[0] = '\0';
240 
241 		switch (ccb->cgdl.status) {
242 			case CAM_GDEVLIST_MORE_DEVS:
243 				strcpy(status, "MORE");
244 				break;
245 			case CAM_GDEVLIST_LAST_DEVICE:
246 				strcpy(status, "LAST");
247 				break;
248 			case CAM_GDEVLIST_LIST_CHANGED:
249 				strcpy(status, "CHANGED");
250 				break;
251 			case CAM_GDEVLIST_ERROR:
252 				strcpy(status, "ERROR");
253 				error = 1;
254 				break;
255 		}
256 
257 		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
258 			ccb->cgdl.periph_name,
259 			ccb->cgdl.unit_number,
260 			ccb->cgdl.generation,
261 			ccb->cgdl.index,
262 			status);
263 
264 		/*
265 		 * If the list has changed, we need to start over from the
266 		 * beginning.
267 		 */
268 		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
269 			ccb->cgdl.index = 0;
270 	}
271 
272 	cam_freeccb(ccb);
273 
274 	return(error);
275 }
276 #endif /* MINIMALISTIC */
277 
278 static int
279 getdevtree(void)
280 {
281 	union ccb ccb;
282 	int bufsize, fd;
283 	unsigned int i;
284 	int need_close = 0;
285 	int error = 0;
286 	int skip_device = 0;
287 
288 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
289 		warn("couldn't open %s", XPT_DEVICE);
290 		return(1);
291 	}
292 
293 	bzero(&(&ccb.ccb_h)[1],
294 	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
295 
296 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
297 	bufsize = sizeof(struct dev_match_result) * 100;
298 	ccb.cdm.match_buf_len = bufsize;
299 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
300 	if (ccb.cdm.matches == NULL) {
301 		warnx("can't malloc memory for matches");
302 		close(fd);
303 		return(1);
304 	}
305 	ccb.cdm.num_matches = 0;
306 
307 	/*
308 	 * We fetch all nodes, since we display most of them in the default
309 	 * case, and all in the verbose case.
310 	 */
311 	ccb.cdm.num_patterns = 0;
312 	ccb.cdm.pattern_buf_len = 0;
313 
314 	/*
315 	 * We do the ioctl multiple times if necessary, in case there are
316 	 * more than 100 nodes in the EDT.
317 	 */
318 	do {
319 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
320 			warn("error sending CAMIOCOMMAND ioctl");
321 			error = 1;
322 			break;
323 		}
324 
325 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
326 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
327 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
328 			warnx("got CAM error %#x, CDM error %d\n",
329 			      ccb.ccb_h.status, ccb.cdm.status);
330 			error = 1;
331 			break;
332 		}
333 
334 		for (i = 0; i < ccb.cdm.num_matches; i++) {
335 			switch (ccb.cdm.matches[i].type) {
336 			case DEV_MATCH_BUS: {
337 				struct bus_match_result *bus_result;
338 
339 				/*
340 				 * Only print the bus information if the
341 				 * user turns on the verbose flag.
342 				 */
343 				if ((arglist & CAM_ARG_VERBOSE) == 0)
344 					break;
345 
346 				bus_result =
347 					&ccb.cdm.matches[i].result.bus_result;
348 
349 				if (need_close) {
350 					fprintf(stdout, ")\n");
351 					need_close = 0;
352 				}
353 
354 				fprintf(stdout, "scbus%d on %s%d bus %d:\n",
355 					bus_result->path_id,
356 					bus_result->dev_name,
357 					bus_result->unit_number,
358 					bus_result->bus_id);
359 				break;
360 			}
361 			case DEV_MATCH_DEVICE: {
362 				struct device_match_result *dev_result;
363 				char vendor[16], product[48], revision[16];
364 				char tmpstr[256];
365 
366 				dev_result =
367 				     &ccb.cdm.matches[i].result.device_result;
368 
369 				if ((dev_result->flags
370 				     & DEV_RESULT_UNCONFIGURED)
371 				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
372 					skip_device = 1;
373 					break;
374 				} else
375 					skip_device = 0;
376 
377 				cam_strvis(vendor, dev_result->inq_data.vendor,
378 					   sizeof(dev_result->inq_data.vendor),
379 					   sizeof(vendor));
380 				cam_strvis(product,
381 					   dev_result->inq_data.product,
382 					   sizeof(dev_result->inq_data.product),
383 					   sizeof(product));
384 				cam_strvis(revision,
385 					   dev_result->inq_data.revision,
386 					  sizeof(dev_result->inq_data.revision),
387 					   sizeof(revision));
388 				sprintf(tmpstr, "<%s %s %s>", vendor, product,
389 					revision);
390 				if (need_close) {
391 					fprintf(stdout, ")\n");
392 					need_close = 0;
393 				}
394 
395 				fprintf(stdout, "%-33s  at scbus%d "
396 					"target %d lun %d (",
397 					tmpstr,
398 					dev_result->path_id,
399 					dev_result->target_id,
400 					dev_result->target_lun);
401 
402 				need_close = 1;
403 
404 				break;
405 			}
406 			case DEV_MATCH_PERIPH: {
407 				struct periph_match_result *periph_result;
408 
409 				periph_result =
410 				      &ccb.cdm.matches[i].result.periph_result;
411 
412 				if (skip_device != 0)
413 					break;
414 
415 				if (need_close > 1)
416 					fprintf(stdout, ",");
417 
418 				fprintf(stdout, "%s%d",
419 					periph_result->periph_name,
420 					periph_result->unit_number);
421 
422 				need_close++;
423 				break;
424 			}
425 			default:
426 				fprintf(stdout, "unknown match type\n");
427 				break;
428 			}
429 		}
430 
431 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
432 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
433 
434 	if (need_close)
435 		fprintf(stdout, ")\n");
436 
437 	close(fd);
438 
439 	return(error);
440 }
441 
442 #ifndef MINIMALISTIC
443 static int
444 testunitready(struct cam_device *device, int retry_count, int timeout,
445 	      int quiet)
446 {
447 	int error = 0;
448 	union ccb *ccb;
449 
450 	ccb = cam_getccb(device);
451 
452 	scsi_test_unit_ready(&ccb->csio,
453 			     /* retries */ retry_count,
454 			     /* cbfcnp */ NULL,
455 			     /* tag_action */ MSG_SIMPLE_Q_TAG,
456 			     /* sense_len */ SSD_FULL_SIZE,
457 			     /* timeout */ timeout ? timeout : 5000);
458 
459 	/* Disable freezing the device queue */
460 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
461 
462 	if (arglist & CAM_ARG_ERR_RECOVER)
463 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
464 
465 	if (cam_send_ccb(device, ccb) < 0) {
466 		if (quiet == 0)
467 			perror("error sending test unit ready");
468 
469 		if (arglist & CAM_ARG_VERBOSE) {
470 			cam_error_print(device, ccb, CAM_ESF_ALL,
471 					CAM_EPF_ALL, stderr);
472 		}
473 
474 		cam_freeccb(ccb);
475 		return(1);
476 	}
477 
478 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
479 		if (quiet == 0)
480 			fprintf(stdout, "Unit is ready\n");
481 	} else {
482 		if (quiet == 0)
483 			fprintf(stdout, "Unit is not ready\n");
484 		error = 1;
485 
486 		if (arglist & CAM_ARG_VERBOSE) {
487 			cam_error_print(device, ccb, CAM_ESF_ALL,
488 					CAM_EPF_ALL, stderr);
489 		}
490 	}
491 
492 	cam_freeccb(ccb);
493 
494 	return(error);
495 }
496 
497 static int
498 scsistart(struct cam_device *device, int startstop, int loadeject,
499 	  int retry_count, int timeout)
500 {
501 	union ccb *ccb;
502 	int error = 0;
503 
504 	ccb = cam_getccb(device);
505 
506 	/*
507 	 * If we're stopping, send an ordered tag so the drive in question
508 	 * will finish any previously queued writes before stopping.  If
509 	 * the device isn't capable of tagged queueing, or if tagged
510 	 * queueing is turned off, the tag action is a no-op.
511 	 */
512 	scsi_start_stop(&ccb->csio,
513 			/* retries */ retry_count,
514 			/* cbfcnp */ NULL,
515 			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
516 						     MSG_ORDERED_Q_TAG,
517 			/* start/stop */ startstop,
518 			/* load_eject */ loadeject,
519 			/* immediate */ 0,
520 			/* sense_len */ SSD_FULL_SIZE,
521 			/* timeout */ timeout ? timeout : 120000);
522 
523 	/* Disable freezing the device queue */
524 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
525 
526 	if (arglist & CAM_ARG_ERR_RECOVER)
527 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
528 
529 	if (cam_send_ccb(device, ccb) < 0) {
530 		perror("error sending start unit");
531 
532 		if (arglist & CAM_ARG_VERBOSE) {
533 			cam_error_print(device, ccb, CAM_ESF_ALL,
534 					CAM_EPF_ALL, stderr);
535 		}
536 
537 		cam_freeccb(ccb);
538 		return(1);
539 	}
540 
541 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
542 		if (startstop) {
543 			fprintf(stdout, "Unit started successfully");
544 			if (loadeject)
545 				fprintf(stdout,", Media loaded\n");
546 			else
547 				fprintf(stdout,"\n");
548 		} else {
549 			fprintf(stdout, "Unit stopped successfully");
550 			if (loadeject)
551 				fprintf(stdout, ", Media ejected\n");
552 			else
553 				fprintf(stdout, "\n");
554 		}
555 	else {
556 		error = 1;
557 		if (startstop)
558 			fprintf(stdout,
559 				"Error received from start unit command\n");
560 		else
561 			fprintf(stdout,
562 				"Error received from stop unit command\n");
563 
564 		if (arglist & CAM_ARG_VERBOSE) {
565 			cam_error_print(device, ccb, CAM_ESF_ALL,
566 					CAM_EPF_ALL, stderr);
567 		}
568 	}
569 
570 	cam_freeccb(ccb);
571 
572 	return(error);
573 }
574 
575 static int
576 scsidoinquiry(struct cam_device *device, int argc, char **argv,
577 	      char *combinedopt, int retry_count, int timeout)
578 {
579 	int c;
580 	int error = 0;
581 
582 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
583 		switch(c) {
584 		case 'D':
585 			arglist |= CAM_ARG_GET_STDINQ;
586 			break;
587 		case 'R':
588 			arglist |= CAM_ARG_GET_XFERRATE;
589 			break;
590 		case 'S':
591 			arglist |= CAM_ARG_GET_SERIAL;
592 			break;
593 		default:
594 			break;
595 		}
596 	}
597 
598 	/*
599 	 * If the user didn't specify any inquiry options, he wants all of
600 	 * them.
601 	 */
602 	if ((arglist & CAM_ARG_INQ_MASK) == 0)
603 		arglist |= CAM_ARG_INQ_MASK;
604 
605 	if (arglist & CAM_ARG_GET_STDINQ)
606 		error = scsiinquiry(device, retry_count, timeout);
607 
608 	if (error != 0)
609 		return(error);
610 
611 	if (arglist & CAM_ARG_GET_SERIAL)
612 		scsiserial(device, retry_count, timeout);
613 
614 	if (error != 0)
615 		return(error);
616 
617 	if (arglist & CAM_ARG_GET_XFERRATE)
618 		error = scsixferrate(device);
619 
620 	return(error);
621 }
622 
623 static int
624 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
625 {
626 	union ccb *ccb;
627 	struct scsi_inquiry_data *inq_buf;
628 	int error = 0;
629 
630 	ccb = cam_getccb(device);
631 
632 	if (ccb == NULL) {
633 		warnx("couldn't allocate CCB");
634 		return(1);
635 	}
636 
637 	/* cam_getccb cleans up the header, caller has to zero the payload */
638 	bzero(&(&ccb->ccb_h)[1],
639 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
640 
641 	inq_buf = (struct scsi_inquiry_data *)malloc(
642 		sizeof(struct scsi_inquiry_data));
643 
644 	if (inq_buf == NULL) {
645 		cam_freeccb(ccb);
646 		warnx("can't malloc memory for inquiry\n");
647 		return(1);
648 	}
649 	bzero(inq_buf, sizeof(*inq_buf));
650 
651 	/*
652 	 * Note that although the size of the inquiry buffer is the full
653 	 * 256 bytes specified in the SCSI spec, we only tell the device
654 	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
655 	 * two reasons for this:
656 	 *
657 	 *  - The SCSI spec says that when a length field is only 1 byte,
658 	 *    a value of 0 will be interpreted as 256.  Therefore
659 	 *    scsi_inquiry() will convert an inq_len (which is passed in as
660 	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
661 	 *    to 0.  Evidently, very few devices meet the spec in that
662 	 *    regard.  Some devices, like many Seagate disks, take the 0 as
663 	 *    0, and don't return any data.  One Pioneer DVD-R drive
664 	 *    returns more data than the command asked for.
665 	 *
666 	 *    So, since there are numerous devices that just don't work
667 	 *    right with the full inquiry size, we don't send the full size.
668 	 *
669 	 *  - The second reason not to use the full inquiry data length is
670 	 *    that we don't need it here.  The only reason we issue a
671 	 *    standard inquiry is to get the vendor name, device name,
672 	 *    and revision so scsi_print_inquiry() can print them.
673 	 *
674 	 * If, at some point in the future, more inquiry data is needed for
675 	 * some reason, this code should use a procedure similar to the
676 	 * probe code.  i.e., issue a short inquiry, and determine from
677 	 * the additional length passed back from the device how much
678 	 * inquiry data the device supports.  Once the amount the device
679 	 * supports is determined, issue an inquiry for that amount and no
680 	 * more.
681 	 *
682 	 * KDM, 2/18/2000
683 	 */
684 	scsi_inquiry(&ccb->csio,
685 		     /* retries */ retry_count,
686 		     /* cbfcnp */ NULL,
687 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
688 		     /* inq_buf */ (u_int8_t *)inq_buf,
689 		     /* inq_len */ SHORT_INQUIRY_LENGTH,
690 		     /* evpd */ 0,
691 		     /* page_code */ 0,
692 		     /* sense_len */ SSD_FULL_SIZE,
693 		     /* timeout */ timeout ? timeout : 5000);
694 
695 	/* Disable freezing the device queue */
696 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
697 
698 	if (arglist & CAM_ARG_ERR_RECOVER)
699 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
700 
701 	if (cam_send_ccb(device, ccb) < 0) {
702 		perror("error sending SCSI inquiry");
703 
704 		if (arglist & CAM_ARG_VERBOSE) {
705 			cam_error_print(device, ccb, CAM_ESF_ALL,
706 					CAM_EPF_ALL, stderr);
707 		}
708 
709 		cam_freeccb(ccb);
710 		return(1);
711 	}
712 
713 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
714 		error = 1;
715 
716 		if (arglist & CAM_ARG_VERBOSE) {
717 			cam_error_print(device, ccb, CAM_ESF_ALL,
718 					CAM_EPF_ALL, stderr);
719 		}
720 	}
721 
722 	cam_freeccb(ccb);
723 
724 	if (error != 0) {
725 		free(inq_buf);
726 		return(error);
727 	}
728 
729 	fprintf(stdout, "%s%d: ", device->device_name,
730 		device->dev_unit_num);
731 	scsi_print_inquiry(inq_buf);
732 
733 	free(inq_buf);
734 
735 	return(0);
736 }
737 
738 static int
739 scsiserial(struct cam_device *device, int retry_count, int timeout)
740 {
741 	union ccb *ccb;
742 	struct scsi_vpd_unit_serial_number *serial_buf;
743 	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
744 	int error = 0;
745 
746 	ccb = cam_getccb(device);
747 
748 	if (ccb == NULL) {
749 		warnx("couldn't allocate CCB");
750 		return(1);
751 	}
752 
753 	/* cam_getccb cleans up the header, caller has to zero the payload */
754 	bzero(&(&ccb->ccb_h)[1],
755 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
756 
757 	serial_buf = (struct scsi_vpd_unit_serial_number *)
758 		malloc(sizeof(*serial_buf));
759 
760 	if (serial_buf == NULL) {
761 		cam_freeccb(ccb);
762 		warnx("can't malloc memory for serial number");
763 		return(1);
764 	}
765 
766 	scsi_inquiry(&ccb->csio,
767 		     /*retries*/ retry_count,
768 		     /*cbfcnp*/ NULL,
769 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
770 		     /* inq_buf */ (u_int8_t *)serial_buf,
771 		     /* inq_len */ sizeof(*serial_buf),
772 		     /* evpd */ 1,
773 		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
774 		     /* sense_len */ SSD_FULL_SIZE,
775 		     /* timeout */ timeout ? timeout : 5000);
776 
777 	/* Disable freezing the device queue */
778 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
779 
780 	if (arglist & CAM_ARG_ERR_RECOVER)
781 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
782 
783 	if (cam_send_ccb(device, ccb) < 0) {
784 		warn("error getting serial number");
785 
786 		if (arglist & CAM_ARG_VERBOSE) {
787 			cam_error_print(device, ccb, CAM_ESF_ALL,
788 					CAM_EPF_ALL, stderr);
789 		}
790 
791 		cam_freeccb(ccb);
792 		free(serial_buf);
793 		return(1);
794 	}
795 
796 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
797 		error = 1;
798 
799 		if (arglist & CAM_ARG_VERBOSE) {
800 			cam_error_print(device, ccb, CAM_ESF_ALL,
801 					CAM_EPF_ALL, stderr);
802 		}
803 	}
804 
805 	cam_freeccb(ccb);
806 
807 	if (error != 0) {
808 		free(serial_buf);
809 		return(error);
810 	}
811 
812 	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
813 	serial_num[serial_buf->length] = '\0';
814 
815 	if ((arglist & CAM_ARG_GET_STDINQ)
816 	 || (arglist & CAM_ARG_GET_XFERRATE))
817 		fprintf(stdout, "%s%d: Serial Number ",
818 			device->device_name, device->dev_unit_num);
819 
820 	fprintf(stdout, "%.60s\n", serial_num);
821 
822 	free(serial_buf);
823 
824 	return(0);
825 }
826 
827 static int
828 scsixferrate(struct cam_device *device)
829 {
830 	u_int32_t freq;
831 	u_int32_t speed;
832 	union ccb *ccb;
833 	u_int mb;
834 	int retval = 0;
835 
836 	ccb = cam_getccb(device);
837 
838 	if (ccb == NULL) {
839 		warnx("couldn't allocate CCB");
840 		return(1);
841 	}
842 
843 	bzero(&(&ccb->ccb_h)[1],
844 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
845 
846 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
847 	ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
848 
849 	if (((retval = cam_send_ccb(device, ccb)) < 0)
850 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
851 		const char error_string[] = "error getting transfer settings";
852 
853 		if (retval < 0)
854 			warn(error_string);
855 		else
856 			warnx(error_string);
857 
858 		if (arglist & CAM_ARG_VERBOSE)
859 			cam_error_print(device, ccb, CAM_ESF_ALL,
860 					CAM_EPF_ALL, stderr);
861 
862 		retval = 1;
863 
864 		goto xferrate_bailout;
865 
866 	}
867 
868 	if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
869 	 && (ccb->cts.sync_offset != 0)) {
870 		freq = scsi_calc_syncsrate(ccb->cts.sync_period);
871 		speed = freq;
872 	} else {
873 		struct ccb_pathinq cpi;
874 
875 		retval = get_cpi(device, &cpi);
876 
877 		if (retval != 0)
878 			goto xferrate_bailout;
879 
880 		speed = cpi.base_transfer_speed;
881 		freq = 0;
882 	}
883 
884 	fprintf(stdout, "%s%d: ", device->device_name,
885 		device->dev_unit_num);
886 
887 	if ((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
888 		speed *= (0x01 << device->bus_width);
889 
890 	mb = speed / 1000;
891 
892 	if (mb > 0)
893 		fprintf(stdout, "%d.%03dMB/s transfers ",
894 			mb, speed % 1000);
895 	else
896 		fprintf(stdout, "%dKB/s transfers ",
897 			speed);
898 
899 	if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
900 	 && (ccb->cts.sync_offset != 0))
901                 fprintf(stdout, "(%d.%03dMHz, offset %d", freq / 1000,
902 			freq % 1000, ccb->cts.sync_offset);
903 
904 	if (((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
905 	 && (ccb->cts.bus_width > 0)) {
906 		if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
907 		 && (ccb->cts.sync_offset != 0)) {
908 			fprintf(stdout, ", ");
909 		} else {
910 			fprintf(stdout, " (");
911 		}
912 		fprintf(stdout, "%dbit)", 8 * (0x01 << ccb->cts.bus_width));
913 	} else if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
914 		&& (ccb->cts.sync_offset != 0)) {
915 		fprintf(stdout, ")");
916 	}
917 
918 	if (((ccb->cts.valid & CCB_TRANS_TQ_VALID) != 0)
919 	 && (ccb->cts.flags & CCB_TRANS_TAG_ENB))
920                 fprintf(stdout, ", Tagged Queueing Enabled");
921 
922         fprintf(stdout, "\n");
923 
924 xferrate_bailout:
925 
926 	cam_freeccb(ccb);
927 
928 	return(retval);
929 }
930 #endif /* MINIMALISTIC */
931 
932 /*
933  * Parse out a bus, or a bus, target and lun in the following
934  * format:
935  * bus
936  * bus:target
937  * bus:target:lun
938  *
939  * Returns the number of parsed components, or 0.
940  */
941 static int
942 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglist)
943 {
944 	char *tmpstr;
945 	int convs = 0;
946 
947 	while (isspace(*tstr) && (*tstr != '\0'))
948 		tstr++;
949 
950 	tmpstr = (char *)strtok(tstr, ":");
951 	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
952 		*bus = strtol(tmpstr, NULL, 0);
953 		*arglist |= CAM_ARG_BUS;
954 		convs++;
955 		tmpstr = (char *)strtok(NULL, ":");
956 		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
957 			*target = strtol(tmpstr, NULL, 0);
958 			*arglist |= CAM_ARG_TARGET;
959 			convs++;
960 			tmpstr = (char *)strtok(NULL, ":");
961 			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
962 				*lun = strtol(tmpstr, NULL, 0);
963 				*arglist |= CAM_ARG_LUN;
964 				convs++;
965 			}
966 		}
967 	}
968 
969 	return convs;
970 }
971 
972 static int
973 dorescan_or_reset(int argc, char **argv, int rescan)
974 {
975 	static const char must[] =
976 		"you must specify \"all\", a bus, or a bus:target:lun to %s";
977 	int rv, error = 0;
978 	int bus = -1, target = -1, lun = -1;
979 	char *tstr;
980 
981 	if (argc < 3) {
982 		warnx(must, rescan? "rescan" : "reset");
983 		return(1);
984 	}
985 
986 	tstr = argv[optind];
987 	while (isspace(*tstr) && (*tstr != '\0'))
988 		tstr++;
989 	if (strncasecmp(tstr, "all", strlen("all")) == 0)
990 		arglist |= CAM_ARG_BUS;
991 	else {
992 		rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
993 		if (rv != 1 && rv != 3) {
994 			warnx(must, rescan? "rescan" : "reset");
995 			return(1);
996 		}
997 	}
998 
999 	if ((arglist & CAM_ARG_BUS)
1000 	    && (arglist & CAM_ARG_TARGET)
1001 	    && (arglist & CAM_ARG_LUN))
1002 		error = scanlun_or_reset_dev(bus, target, lun, rescan);
1003 	else
1004 		error = rescan_or_reset_bus(bus, rescan);
1005 
1006 	return(error);
1007 }
1008 
1009 static int
1010 rescan_or_reset_bus(int bus, int rescan)
1011 {
1012 	union ccb ccb, matchccb;
1013 	int fd, retval;
1014 	int bufsize;
1015 
1016 	retval = 0;
1017 
1018 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1019 		warnx("error opening tranport layer device %s", XPT_DEVICE);
1020 		warn("%s", XPT_DEVICE);
1021 		return(1);
1022 	}
1023 
1024 	if (bus != -1) {
1025 		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1026 		ccb.ccb_h.path_id = bus;
1027 		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1028 		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1029 		ccb.crcn.flags = CAM_FLAG_NONE;
1030 
1031 		/* run this at a low priority */
1032 		ccb.ccb_h.pinfo.priority = 5;
1033 
1034 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1035 			warn("CAMIOCOMMAND ioctl failed");
1036 			close(fd);
1037 			return(1);
1038 		}
1039 
1040 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1041 			fprintf(stdout, "%s of bus %d was successful\n",
1042 			    rescan ? "Re-scan" : "Reset", bus);
1043 		} else {
1044 			fprintf(stdout, "%s of bus %d returned error %#x\n",
1045 				rescan ? "Re-scan" : "Reset", bus,
1046 				ccb.ccb_h.status & CAM_STATUS_MASK);
1047 			retval = 1;
1048 		}
1049 
1050 		close(fd);
1051 		return(retval);
1052 
1053 	}
1054 
1055 
1056 	/*
1057 	 * The right way to handle this is to modify the xpt so that it can
1058 	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
1059 	 * that isn't implemented, so instead we enumerate the busses and
1060 	 * send the rescan or reset to those busses in the case where the
1061 	 * given bus is -1 (wildcard).  We don't send a rescan or reset
1062 	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1063 	 * no-op, sending a rescan to the xpt bus would result in a status of
1064 	 * CAM_REQ_INVALID.
1065 	 */
1066 	bzero(&(&matchccb.ccb_h)[1],
1067 	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1068 	matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1069 	bufsize = sizeof(struct dev_match_result) * 20;
1070 	matchccb.cdm.match_buf_len = bufsize;
1071 	matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1072 	if (matchccb.cdm.matches == NULL) {
1073 		warnx("can't malloc memory for matches");
1074 		retval = 1;
1075 		goto bailout;
1076 	}
1077 	matchccb.cdm.num_matches = 0;
1078 
1079 	matchccb.cdm.num_patterns = 1;
1080 	matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1081 
1082 	matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1083 		matchccb.cdm.pattern_buf_len);
1084 	if (matchccb.cdm.patterns == NULL) {
1085 		warnx("can't malloc memory for patterns");
1086 		retval = 1;
1087 		goto bailout;
1088 	}
1089 	matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1090 	matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1091 
1092 	do {
1093 		unsigned int i;
1094 
1095 		if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1096 			warn("CAMIOCOMMAND ioctl failed");
1097 			retval = 1;
1098 			goto bailout;
1099 		}
1100 
1101 		if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1102 		 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1103 		   && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1104 			warnx("got CAM error %#x, CDM error %d\n",
1105 			      matchccb.ccb_h.status, matchccb.cdm.status);
1106 			retval = 1;
1107 			goto bailout;
1108 		}
1109 
1110 		for (i = 0; i < matchccb.cdm.num_matches; i++) {
1111 			struct bus_match_result *bus_result;
1112 
1113 			/* This shouldn't happen. */
1114 			if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1115 				continue;
1116 
1117 			bus_result = &matchccb.cdm.matches[i].result.bus_result;
1118 
1119 			/*
1120 			 * We don't want to rescan or reset the xpt bus.
1121 			 * See above.
1122 			 */
1123 			if ((int)bus_result->path_id == -1)
1124 				continue;
1125 
1126 			ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1127 						       XPT_RESET_BUS;
1128 			ccb.ccb_h.path_id = bus_result->path_id;
1129 			ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1130 			ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1131 			ccb.crcn.flags = CAM_FLAG_NONE;
1132 
1133 			/* run this at a low priority */
1134 			ccb.ccb_h.pinfo.priority = 5;
1135 
1136 			if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1137 				warn("CAMIOCOMMAND ioctl failed");
1138 				retval = 1;
1139 				goto bailout;
1140 			}
1141 
1142 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1143 				fprintf(stdout, "%s of bus %d was successful\n",
1144 					rescan? "Re-scan" : "Reset",
1145 					bus_result->path_id);
1146 			} else {
1147 				/*
1148 				 * Don't bail out just yet, maybe the other
1149 				 * rescan or reset commands will complete
1150 				 * successfully.
1151 				 */
1152 				fprintf(stderr, "%s of bus %d returned error "
1153 					"%#x\n", rescan? "Re-scan" : "Reset",
1154 					bus_result->path_id,
1155 					ccb.ccb_h.status & CAM_STATUS_MASK);
1156 				retval = 1;
1157 			}
1158 		}
1159 	} while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1160 		 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1161 
1162 bailout:
1163 
1164 	if (fd != -1)
1165 		close(fd);
1166 
1167 	if (matchccb.cdm.patterns != NULL)
1168 		free(matchccb.cdm.patterns);
1169 	if (matchccb.cdm.matches != NULL)
1170 		free(matchccb.cdm.matches);
1171 
1172 	return(retval);
1173 }
1174 
1175 static int
1176 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1177 {
1178 	union ccb ccb;
1179 	struct cam_device *device;
1180 	int fd;
1181 
1182 	device = NULL;
1183 
1184 	if (bus < 0) {
1185 		warnx("invalid bus number %d", bus);
1186 		return(1);
1187 	}
1188 
1189 	if (target < 0) {
1190 		warnx("invalid target number %d", target);
1191 		return(1);
1192 	}
1193 
1194 	if (lun < 0) {
1195 		warnx("invalid lun number %d", lun);
1196 		return(1);
1197 	}
1198 
1199 	fd = -1;
1200 
1201 	bzero(&ccb, sizeof(union ccb));
1202 
1203 	if (scan) {
1204 		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1205 			warnx("error opening tranport layer device %s\n",
1206 			    XPT_DEVICE);
1207 			warn("%s", XPT_DEVICE);
1208 			return(1);
1209 		}
1210 	} else {
1211 		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1212 		if (device == NULL) {
1213 			warnx("%s", cam_errbuf);
1214 			return(1);
1215 		}
1216 	}
1217 
1218 	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1219 	ccb.ccb_h.path_id = bus;
1220 	ccb.ccb_h.target_id = target;
1221 	ccb.ccb_h.target_lun = lun;
1222 	ccb.ccb_h.timeout = 5000;
1223 	ccb.crcn.flags = CAM_FLAG_NONE;
1224 
1225 	/* run this at a low priority */
1226 	ccb.ccb_h.pinfo.priority = 5;
1227 
1228 	if (scan) {
1229 		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1230 			warn("CAMIOCOMMAND ioctl failed");
1231 			close(fd);
1232 			return(1);
1233 		}
1234 	} else {
1235 		if (cam_send_ccb(device, &ccb) < 0) {
1236 			warn("error sending XPT_RESET_DEV CCB");
1237 			cam_close_device(device);
1238 			return(1);
1239 		}
1240 	}
1241 
1242 	if (scan)
1243 		close(fd);
1244 	else
1245 		cam_close_device(device);
1246 
1247 	/*
1248 	 * An error code of CAM_BDR_SENT is normal for a BDR request.
1249 	 */
1250 	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1251 	 || ((!scan)
1252 	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1253 		fprintf(stdout, "%s of %d:%d:%d was successful\n",
1254 		    scan? "Re-scan" : "Reset", bus, target, lun);
1255 		return(0);
1256 	} else {
1257 		fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1258 		    scan? "Re-scan" : "Reset", bus, target, lun,
1259 		    ccb.ccb_h.status & CAM_STATUS_MASK);
1260 		return(1);
1261 	}
1262 }
1263 
1264 #ifndef MINIMALISTIC
1265 static int
1266 readdefects(struct cam_device *device, int argc, char **argv,
1267 	    char *combinedopt, int retry_count, int timeout)
1268 {
1269 	union ccb *ccb = NULL;
1270 	struct scsi_read_defect_data_10 *rdd_cdb;
1271 	u_int8_t *defect_list = NULL;
1272 	u_int32_t dlist_length = 65000;
1273 	u_int32_t returned_length = 0;
1274 	u_int32_t num_returned = 0;
1275 	u_int8_t returned_format;
1276 	unsigned int i;
1277 	int c, error = 0;
1278 	int lists_specified = 0;
1279 
1280 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1281 		switch(c){
1282 		case 'f':
1283 		{
1284 			char *tstr;
1285 			tstr = optarg;
1286 			while (isspace(*tstr) && (*tstr != '\0'))
1287 				tstr++;
1288 			if (strcmp(tstr, "block") == 0)
1289 				arglist |= CAM_ARG_FORMAT_BLOCK;
1290 			else if (strcmp(tstr, "bfi") == 0)
1291 				arglist |= CAM_ARG_FORMAT_BFI;
1292 			else if (strcmp(tstr, "phys") == 0)
1293 				arglist |= CAM_ARG_FORMAT_PHYS;
1294 			else {
1295 				error = 1;
1296 				warnx("invalid defect format %s", tstr);
1297 				goto defect_bailout;
1298 			}
1299 			break;
1300 		}
1301 		case 'G':
1302 			arglist |= CAM_ARG_GLIST;
1303 			break;
1304 		case 'P':
1305 			arglist |= CAM_ARG_PLIST;
1306 			break;
1307 		default:
1308 			break;
1309 		}
1310 	}
1311 
1312 	ccb = cam_getccb(device);
1313 
1314 	/*
1315 	 * Hopefully 65000 bytes is enough to hold the defect list.  If it
1316 	 * isn't, the disk is probably dead already.  We'd have to go with
1317 	 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1318 	 * to hold them all.
1319 	 */
1320 	defect_list = malloc(dlist_length);
1321 	if (defect_list == NULL) {
1322 		warnx("can't malloc memory for defect list");
1323 		error = 1;
1324 		goto defect_bailout;
1325 	}
1326 
1327 	rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1328 
1329 	/*
1330 	 * cam_getccb() zeros the CCB header only.  So we need to zero the
1331 	 * payload portion of the ccb.
1332 	 */
1333 	bzero(&(&ccb->ccb_h)[1],
1334 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1335 
1336 	cam_fill_csio(&ccb->csio,
1337 		      /*retries*/ retry_count,
1338 		      /*cbfcnp*/ NULL,
1339 		      /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1340 					      CAM_PASS_ERR_RECOVER : 0),
1341 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
1342 		      /*data_ptr*/ defect_list,
1343 		      /*dxfer_len*/ dlist_length,
1344 		      /*sense_len*/ SSD_FULL_SIZE,
1345 		      /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1346 		      /*timeout*/ timeout ? timeout : 5000);
1347 
1348 	rdd_cdb->opcode = READ_DEFECT_DATA_10;
1349 	if (arglist & CAM_ARG_FORMAT_BLOCK)
1350 		rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1351 	else if (arglist & CAM_ARG_FORMAT_BFI)
1352 		rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1353 	else if (arglist & CAM_ARG_FORMAT_PHYS)
1354 		rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1355 	else {
1356 		error = 1;
1357 		warnx("no defect list format specified");
1358 		goto defect_bailout;
1359 	}
1360 	if (arglist & CAM_ARG_PLIST) {
1361 		rdd_cdb->format |= SRDD10_PLIST;
1362 		lists_specified++;
1363 	}
1364 
1365 	if (arglist & CAM_ARG_GLIST) {
1366 		rdd_cdb->format |= SRDD10_GLIST;
1367 		lists_specified++;
1368 	}
1369 
1370 	scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1371 
1372 	/* Disable freezing the device queue */
1373 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1374 
1375 	if (cam_send_ccb(device, ccb) < 0) {
1376 		perror("error reading defect list");
1377 
1378 		if (arglist & CAM_ARG_VERBOSE) {
1379 			cam_error_print(device, ccb, CAM_ESF_ALL,
1380 					CAM_EPF_ALL, stderr);
1381 		}
1382 
1383 		error = 1;
1384 		goto defect_bailout;
1385 	}
1386 
1387 	returned_length = scsi_2btoul(((struct
1388 		scsi_read_defect_data_hdr_10 *)defect_list)->length);
1389 
1390 	returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1391 			defect_list)->format;
1392 
1393 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1394 	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1395 	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1396 		struct scsi_sense_data *sense;
1397 		int error_code, sense_key, asc, ascq;
1398 
1399 		sense = &ccb->csio.sense_data;
1400 		scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1401 
1402 		/*
1403 		 * According to the SCSI spec, if the disk doesn't support
1404 		 * the requested format, it will generally return a sense
1405 		 * key of RECOVERED ERROR, and an additional sense code
1406 		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1407 		 * also check to make sure that the returned length is
1408 		 * greater than 0, and then print out whatever format the
1409 		 * disk gave us.
1410 		 */
1411 		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1412 		 && (asc == 0x1c) && (ascq == 0x00)
1413 		 && (returned_length > 0)) {
1414 			warnx("requested defect format not available");
1415 			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1416 			case SRDD10_BLOCK_FORMAT:
1417 				warnx("Device returned block format");
1418 				break;
1419 			case SRDD10_BYTES_FROM_INDEX_FORMAT:
1420 				warnx("Device returned bytes from index"
1421 				      " format");
1422 				break;
1423 			case SRDD10_PHYSICAL_SECTOR_FORMAT:
1424 				warnx("Device returned physical sector format");
1425 				break;
1426 			default:
1427 				error = 1;
1428 				warnx("Device returned unknown defect"
1429 				     " data format %#x", returned_format);
1430 				goto defect_bailout;
1431 				break; /* NOTREACHED */
1432 			}
1433 		} else {
1434 			error = 1;
1435 			warnx("Error returned from read defect data command");
1436 			if (arglist & CAM_ARG_VERBOSE)
1437 				cam_error_print(device, ccb, CAM_ESF_ALL,
1438 						CAM_EPF_ALL, stderr);
1439 			goto defect_bailout;
1440 		}
1441 	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1442 		error = 1;
1443 		warnx("Error returned from read defect data command");
1444 		if (arglist & CAM_ARG_VERBOSE)
1445 			cam_error_print(device, ccb, CAM_ESF_ALL,
1446 					CAM_EPF_ALL, stderr);
1447 		goto defect_bailout;
1448 	}
1449 
1450 	/*
1451 	 * XXX KDM  I should probably clean up the printout format for the
1452 	 * disk defects.
1453 	 */
1454 	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1455 		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1456 		{
1457 			struct scsi_defect_desc_phys_sector *dlist;
1458 
1459 			dlist = (struct scsi_defect_desc_phys_sector *)
1460 				(defect_list +
1461 				sizeof(struct scsi_read_defect_data_hdr_10));
1462 
1463 			num_returned = returned_length /
1464 				sizeof(struct scsi_defect_desc_phys_sector);
1465 
1466 			fprintf(stderr, "Got %d defect", num_returned);
1467 
1468 			if ((lists_specified == 0) || (num_returned == 0)) {
1469 				fprintf(stderr, "s.\n");
1470 				break;
1471 			} else if (num_returned == 1)
1472 				fprintf(stderr, ":\n");
1473 			else
1474 				fprintf(stderr, "s:\n");
1475 
1476 			for (i = 0; i < num_returned; i++) {
1477 				fprintf(stdout, "%d:%d:%d\n",
1478 					scsi_3btoul(dlist[i].cylinder),
1479 					dlist[i].head,
1480 					scsi_4btoul(dlist[i].sector));
1481 			}
1482 			break;
1483 		}
1484 		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1485 		{
1486 			struct scsi_defect_desc_bytes_from_index *dlist;
1487 
1488 			dlist = (struct scsi_defect_desc_bytes_from_index *)
1489 				(defect_list +
1490 				sizeof(struct scsi_read_defect_data_hdr_10));
1491 
1492 			num_returned = returned_length /
1493 			      sizeof(struct scsi_defect_desc_bytes_from_index);
1494 
1495 			fprintf(stderr, "Got %d defect", num_returned);
1496 
1497 			if ((lists_specified == 0) || (num_returned == 0)) {
1498 				fprintf(stderr, "s.\n");
1499 				break;
1500 			} else if (num_returned == 1)
1501 				fprintf(stderr, ":\n");
1502 			else
1503 				fprintf(stderr, "s:\n");
1504 
1505 			for (i = 0; i < num_returned; i++) {
1506 				fprintf(stdout, "%d:%d:%d\n",
1507 					scsi_3btoul(dlist[i].cylinder),
1508 					dlist[i].head,
1509 					scsi_4btoul(dlist[i].bytes_from_index));
1510 			}
1511 			break;
1512 		}
1513 		case SRDDH10_BLOCK_FORMAT:
1514 		{
1515 			struct scsi_defect_desc_block *dlist;
1516 
1517 			dlist = (struct scsi_defect_desc_block *)(defect_list +
1518 				sizeof(struct scsi_read_defect_data_hdr_10));
1519 
1520 			num_returned = returned_length /
1521 			      sizeof(struct scsi_defect_desc_block);
1522 
1523 			fprintf(stderr, "Got %d defect", num_returned);
1524 
1525 			if ((lists_specified == 0) || (num_returned == 0)) {
1526 				fprintf(stderr, "s.\n");
1527 				break;
1528 			} else if (num_returned == 1)
1529 				fprintf(stderr, ":\n");
1530 			else
1531 				fprintf(stderr, "s:\n");
1532 
1533 			for (i = 0; i < num_returned; i++)
1534 				fprintf(stdout, "%u\n",
1535 					scsi_4btoul(dlist[i].address));
1536 			break;
1537 		}
1538 		default:
1539 			fprintf(stderr, "Unknown defect format %d\n",
1540 				returned_format & SRDDH10_DLIST_FORMAT_MASK);
1541 			error = 1;
1542 			break;
1543 	}
1544 defect_bailout:
1545 
1546 	if (defect_list != NULL)
1547 		free(defect_list);
1548 
1549 	if (ccb != NULL)
1550 		cam_freeccb(ccb);
1551 
1552 	return(error);
1553 }
1554 #endif /* MINIMALISTIC */
1555 
1556 #if 0
1557 void
1558 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
1559 {
1560 	union ccb *ccb;
1561 
1562 	ccb = cam_getccb(device);
1563 
1564 	cam_freeccb(ccb);
1565 }
1566 #endif
1567 
1568 #ifndef MINIMALISTIC
1569 void
1570 mode_sense(struct cam_device *device, int mode_page, int page_control,
1571 	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
1572 {
1573 	union ccb *ccb;
1574 	int retval;
1575 
1576 	ccb = cam_getccb(device);
1577 
1578 	if (ccb == NULL)
1579 		errx(1, "mode_sense: couldn't allocate CCB");
1580 
1581 	bzero(&(&ccb->ccb_h)[1],
1582 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1583 
1584 	scsi_mode_sense(&ccb->csio,
1585 			/* retries */ retry_count,
1586 			/* cbfcnp */ NULL,
1587 			/* tag_action */ MSG_SIMPLE_Q_TAG,
1588 			/* dbd */ dbd,
1589 			/* page_code */ page_control << 6,
1590 			/* page */ mode_page,
1591 			/* param_buf */ data,
1592 			/* param_len */ datalen,
1593 			/* sense_len */ SSD_FULL_SIZE,
1594 			/* timeout */ timeout ? timeout : 5000);
1595 
1596 	if (arglist & CAM_ARG_ERR_RECOVER)
1597 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1598 
1599 	/* Disable freezing the device queue */
1600 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1601 
1602 	if (((retval = cam_send_ccb(device, ccb)) < 0)
1603 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1604 		if (arglist & CAM_ARG_VERBOSE) {
1605 			cam_error_print(device, ccb, CAM_ESF_ALL,
1606 					CAM_EPF_ALL, stderr);
1607 		}
1608 		cam_freeccb(ccb);
1609 		cam_close_device(device);
1610 		if (retval < 0)
1611 			err(1, "error sending mode sense command");
1612 		else
1613 			errx(1, "error sending mode sense command");
1614 	}
1615 
1616 	cam_freeccb(ccb);
1617 }
1618 
1619 void
1620 mode_select(struct cam_device *device, int save_pages, int retry_count,
1621 	   int timeout, u_int8_t *data, int datalen)
1622 {
1623 	union ccb *ccb;
1624 	int retval;
1625 
1626 	ccb = cam_getccb(device);
1627 
1628 	if (ccb == NULL)
1629 		errx(1, "mode_select: couldn't allocate CCB");
1630 
1631 	bzero(&(&ccb->ccb_h)[1],
1632 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1633 
1634 	scsi_mode_select(&ccb->csio,
1635 			 /* retries */ retry_count,
1636 			 /* cbfcnp */ NULL,
1637 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
1638 			 /* scsi_page_fmt */ 1,
1639 			 /* save_pages */ save_pages,
1640 			 /* param_buf */ data,
1641 			 /* param_len */ datalen,
1642 			 /* sense_len */ SSD_FULL_SIZE,
1643 			 /* timeout */ timeout ? timeout : 5000);
1644 
1645 	if (arglist & CAM_ARG_ERR_RECOVER)
1646 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1647 
1648 	/* Disable freezing the device queue */
1649 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1650 
1651 	if (((retval = cam_send_ccb(device, ccb)) < 0)
1652 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1653 		if (arglist & CAM_ARG_VERBOSE) {
1654 			cam_error_print(device, ccb, CAM_ESF_ALL,
1655 					CAM_EPF_ALL, stderr);
1656 		}
1657 		cam_freeccb(ccb);
1658 		cam_close_device(device);
1659 
1660 		if (retval < 0)
1661 			err(1, "error sending mode select command");
1662 		else
1663 			errx(1, "error sending mode select command");
1664 
1665 	}
1666 
1667 	cam_freeccb(ccb);
1668 }
1669 
1670 void
1671 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
1672 	 int retry_count, int timeout)
1673 {
1674 	int c, mode_page = -1, page_control = 0;
1675 	int binary = 0, list = 0;
1676 
1677 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1678 		switch(c) {
1679 		case 'b':
1680 			binary = 1;
1681 			break;
1682 		case 'd':
1683 			arglist |= CAM_ARG_DBD;
1684 			break;
1685 		case 'e':
1686 			arglist |= CAM_ARG_MODE_EDIT;
1687 			break;
1688 		case 'l':
1689 			list = 1;
1690 			break;
1691 		case 'm':
1692 			mode_page = strtol(optarg, NULL, 0);
1693 			if (mode_page < 0)
1694 				errx(1, "invalid mode page %d", mode_page);
1695 			break;
1696 		case 'P':
1697 			page_control = strtol(optarg, NULL, 0);
1698 			if ((page_control < 0) || (page_control > 3))
1699 				errx(1, "invalid page control field %d",
1700 				     page_control);
1701 			arglist |= CAM_ARG_PAGE_CNTL;
1702 			break;
1703 		default:
1704 			break;
1705 		}
1706 	}
1707 
1708 	if (mode_page == -1 && list == 0)
1709 		errx(1, "you must specify a mode page!");
1710 
1711 	if (list) {
1712 		mode_list(device, page_control, arglist & CAM_ARG_DBD,
1713 		    retry_count, timeout);
1714 	} else {
1715 		mode_edit(device, mode_page, page_control,
1716 		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
1717 		    retry_count, timeout);
1718 	}
1719 }
1720 
1721 static int
1722 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
1723 	int retry_count, int timeout)
1724 {
1725 	union ccb *ccb;
1726 	u_int32_t flags = CAM_DIR_NONE;
1727 	u_int8_t *data_ptr = NULL;
1728 	u_int8_t cdb[20];
1729 	struct get_hook hook;
1730 	int c, data_bytes = 0;
1731 	int cdb_len = 0;
1732 	char *datastr = NULL, *tstr;
1733 	int error = 0;
1734 	int fd_data = 0;
1735 	int retval;
1736 
1737 	ccb = cam_getccb(device);
1738 
1739 	if (ccb == NULL) {
1740 		warnx("scsicmd: error allocating ccb");
1741 		return(1);
1742 	}
1743 
1744 	bzero(&(&ccb->ccb_h)[1],
1745 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1746 
1747 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1748 		switch(c) {
1749 		case 'c':
1750 			tstr = optarg;
1751 			while (isspace(*tstr) && (*tstr != '\0'))
1752 				tstr++;
1753 			hook.argc = argc - optind;
1754 			hook.argv = argv + optind;
1755 			hook.got = 0;
1756 			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
1757 						    iget, &hook);
1758 			/*
1759 			 * Increment optind by the number of arguments the
1760 			 * encoding routine processed.  After each call to
1761 			 * getopt(3), optind points to the argument that
1762 			 * getopt should process _next_.  In this case,
1763 			 * that means it points to the first command string
1764 			 * argument, if there is one.  Once we increment
1765 			 * this, it should point to either the next command
1766 			 * line argument, or it should be past the end of
1767 			 * the list.
1768 			 */
1769 			optind += hook.got;
1770 			break;
1771 		case 'i':
1772 			if (arglist & CAM_ARG_CMD_OUT) {
1773 				warnx("command must either be "
1774 				      "read or write, not both");
1775 				error = 1;
1776 				goto scsicmd_bailout;
1777 			}
1778 			arglist |= CAM_ARG_CMD_IN;
1779 			flags = CAM_DIR_IN;
1780 			data_bytes = strtol(optarg, NULL, 0);
1781 			if (data_bytes <= 0) {
1782 				warnx("invalid number of input bytes %d",
1783 				      data_bytes);
1784 				error = 1;
1785 				goto scsicmd_bailout;
1786 			}
1787 			hook.argc = argc - optind;
1788 			hook.argv = argv + optind;
1789 			hook.got = 0;
1790 			optind++;
1791 			datastr = cget(&hook, NULL);
1792 			/*
1793 			 * If the user supplied "-" instead of a format, he
1794 			 * wants the data to be written to stdout.
1795 			 */
1796 			if ((datastr != NULL)
1797 			 && (datastr[0] == '-'))
1798 				fd_data = 1;
1799 
1800 			data_ptr = (u_int8_t *)malloc(data_bytes);
1801 			if (data_ptr == NULL) {
1802 				warnx("can't malloc memory for data_ptr");
1803 				error = 1;
1804 				goto scsicmd_bailout;
1805 			}
1806 			break;
1807 		case 'o':
1808 			if (arglist & CAM_ARG_CMD_IN) {
1809 				warnx("command must either be "
1810 				      "read or write, not both");
1811 				error = 1;
1812 				goto scsicmd_bailout;
1813 			}
1814 			arglist |= CAM_ARG_CMD_OUT;
1815 			flags = CAM_DIR_OUT;
1816 			data_bytes = strtol(optarg, NULL, 0);
1817 			if (data_bytes <= 0) {
1818 				warnx("invalid number of output bytes %d",
1819 				      data_bytes);
1820 				error = 1;
1821 				goto scsicmd_bailout;
1822 			}
1823 			hook.argc = argc - optind;
1824 			hook.argv = argv + optind;
1825 			hook.got = 0;
1826 			datastr = cget(&hook, NULL);
1827 			data_ptr = (u_int8_t *)malloc(data_bytes);
1828 			if (data_ptr == NULL) {
1829 				warnx("can't malloc memory for data_ptr");
1830 				error = 1;
1831 				goto scsicmd_bailout;
1832 			}
1833 			/*
1834 			 * If the user supplied "-" instead of a format, he
1835 			 * wants the data to be read from stdin.
1836 			 */
1837 			if ((datastr != NULL)
1838 			 && (datastr[0] == '-'))
1839 				fd_data = 1;
1840 			else
1841 				buff_encode_visit(data_ptr, data_bytes, datastr,
1842 						  iget, &hook);
1843 			optind += hook.got;
1844 			break;
1845 		default:
1846 			break;
1847 		}
1848 	}
1849 
1850 	/*
1851 	 * If fd_data is set, and we're writing to the device, we need to
1852 	 * read the data the user wants written from stdin.
1853 	 */
1854 	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
1855 		ssize_t amt_read;
1856 		int amt_to_read = data_bytes;
1857 		u_int8_t *buf_ptr = data_ptr;
1858 
1859 		for (amt_read = 0; amt_to_read > 0;
1860 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
1861 			if (amt_read == -1) {
1862 				warn("error reading data from stdin");
1863 				error = 1;
1864 				goto scsicmd_bailout;
1865 			}
1866 			amt_to_read -= amt_read;
1867 			buf_ptr += amt_read;
1868 		}
1869 	}
1870 
1871 	if (arglist & CAM_ARG_ERR_RECOVER)
1872 		flags |= CAM_PASS_ERR_RECOVER;
1873 
1874 	/* Disable freezing the device queue */
1875 	flags |= CAM_DEV_QFRZDIS;
1876 
1877 	/*
1878 	 * This is taken from the SCSI-3 draft spec.
1879 	 * (T10/1157D revision 0.3)
1880 	 * The top 3 bits of an opcode are the group code.  The next 5 bits
1881 	 * are the command code.
1882 	 * Group 0:  six byte commands
1883 	 * Group 1:  ten byte commands
1884 	 * Group 2:  ten byte commands
1885 	 * Group 3:  reserved
1886 	 * Group 4:  sixteen byte commands
1887 	 * Group 5:  twelve byte commands
1888 	 * Group 6:  vendor specific
1889 	 * Group 7:  vendor specific
1890 	 */
1891 	switch((cdb[0] >> 5) & 0x7) {
1892 		case 0:
1893 			cdb_len = 6;
1894 			break;
1895 		case 1:
1896 		case 2:
1897 			cdb_len = 10;
1898 			break;
1899 		case 3:
1900 		case 6:
1901 		case 7:
1902 		        /* computed by buff_encode_visit */
1903 			break;
1904 		case 4:
1905 			cdb_len = 16;
1906 			break;
1907 		case 5:
1908 			cdb_len = 12;
1909 			break;
1910 	}
1911 
1912 	/*
1913 	 * We should probably use csio_build_visit or something like that
1914 	 * here, but it's easier to encode arguments as you go.  The
1915 	 * alternative would be skipping the CDB argument and then encoding
1916 	 * it here, since we've got the data buffer argument by now.
1917 	 */
1918 	bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
1919 
1920 	cam_fill_csio(&ccb->csio,
1921 		      /*retries*/ retry_count,
1922 		      /*cbfcnp*/ NULL,
1923 		      /*flags*/ flags,
1924 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
1925 		      /*data_ptr*/ data_ptr,
1926 		      /*dxfer_len*/ data_bytes,
1927 		      /*sense_len*/ SSD_FULL_SIZE,
1928 		      /*cdb_len*/ cdb_len,
1929 		      /*timeout*/ timeout ? timeout : 5000);
1930 
1931 	if (((retval = cam_send_ccb(device, ccb)) < 0)
1932 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1933 		if (retval < 0)
1934 			warn("error sending command");
1935 		else
1936 			warnx("error sending command");
1937 
1938 		if (arglist & CAM_ARG_VERBOSE) {
1939 			cam_error_print(device, ccb, CAM_ESF_ALL,
1940 					CAM_EPF_ALL, stderr);
1941 		}
1942 
1943 		error = 1;
1944 		goto scsicmd_bailout;
1945 	}
1946 
1947 
1948 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1949 	 && (arglist & CAM_ARG_CMD_IN)
1950 	 && (data_bytes > 0)) {
1951 		if (fd_data == 0) {
1952 			buff_decode_visit(data_ptr, data_bytes, datastr,
1953 					  arg_put, NULL);
1954 			fprintf(stdout, "\n");
1955 		} else {
1956 			ssize_t amt_written;
1957 			int amt_to_write = data_bytes;
1958 			u_int8_t *buf_ptr = data_ptr;
1959 
1960 			for (amt_written = 0; (amt_to_write > 0) &&
1961 			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
1962 				amt_to_write -= amt_written;
1963 				buf_ptr += amt_written;
1964 			}
1965 			if (amt_written == -1) {
1966 				warn("error writing data to stdout");
1967 				error = 1;
1968 				goto scsicmd_bailout;
1969 			} else if ((amt_written == 0)
1970 				&& (amt_to_write > 0)) {
1971 				warnx("only wrote %u bytes out of %u",
1972 				      data_bytes - amt_to_write, data_bytes);
1973 			}
1974 		}
1975 	}
1976 
1977 scsicmd_bailout:
1978 
1979 	if ((data_bytes > 0) && (data_ptr != NULL))
1980 		free(data_ptr);
1981 
1982 	cam_freeccb(ccb);
1983 
1984 	return(error);
1985 }
1986 
1987 static int
1988 camdebug(int argc, char **argv, char *combinedopt)
1989 {
1990 	int c, fd;
1991 	int bus = -1, target = -1, lun = -1;
1992 	char *tstr, *tmpstr = NULL;
1993 	union ccb ccb;
1994 	int error = 0;
1995 
1996 	bzero(&ccb, sizeof(union ccb));
1997 
1998 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1999 		switch(c) {
2000 		case 'I':
2001 			arglist |= CAM_ARG_DEBUG_INFO;
2002 			ccb.cdbg.flags |= CAM_DEBUG_INFO;
2003 			break;
2004 		case 'S':
2005 			arglist |= CAM_ARG_DEBUG_SUBTRACE;
2006 			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2007 			break;
2008 		case 'T':
2009 			arglist |= CAM_ARG_DEBUG_TRACE;
2010 			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2011 			break;
2012 		case 'c':
2013 			arglist |= CAM_ARG_DEBUG_CDB;
2014 			ccb.cdbg.flags |= CAM_DEBUG_CDB;
2015 			break;
2016 		default:
2017 			break;
2018 		}
2019 	}
2020 
2021 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2022 		warnx("error opening transport layer device %s", XPT_DEVICE);
2023 		warn("%s", XPT_DEVICE);
2024 		return(1);
2025 	}
2026 	argc -= optind;
2027 	argv += optind;
2028 
2029 	if (argc <= 0) {
2030 		warnx("you must specify \"off\", \"all\" or a bus,");
2031 		warnx("bus:target, or bus:target:lun");
2032 		close(fd);
2033 		return(1);
2034 	}
2035 
2036 	tstr = *argv;
2037 
2038 	while (isspace(*tstr) && (*tstr != '\0'))
2039 		tstr++;
2040 
2041 	if (strncmp(tstr, "off", 3) == 0) {
2042 		ccb.cdbg.flags = CAM_DEBUG_NONE;
2043 		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_TRACE|
2044 			     CAM_ARG_DEBUG_SUBTRACE);
2045 	} else if (strncmp(tstr, "all", 3) != 0) {
2046 		tmpstr = (char *)strtok(tstr, ":");
2047 		if ((tmpstr != NULL) && (*tmpstr != '\0')){
2048 			bus = strtol(tmpstr, NULL, 0);
2049 			arglist |= CAM_ARG_BUS;
2050 			tmpstr = (char *)strtok(NULL, ":");
2051 			if ((tmpstr != NULL) && (*tmpstr != '\0')){
2052 				target = strtol(tmpstr, NULL, 0);
2053 				arglist |= CAM_ARG_TARGET;
2054 				tmpstr = (char *)strtok(NULL, ":");
2055 				if ((tmpstr != NULL) && (*tmpstr != '\0')){
2056 					lun = strtol(tmpstr, NULL, 0);
2057 					arglist |= CAM_ARG_LUN;
2058 				}
2059 			}
2060 		} else {
2061 			error = 1;
2062 			warnx("you must specify \"all\", \"off\", or a bus,");
2063 			warnx("bus:target, or bus:target:lun to debug");
2064 		}
2065 	}
2066 
2067 	if (error == 0) {
2068 
2069 		ccb.ccb_h.func_code = XPT_DEBUG;
2070 		ccb.ccb_h.path_id = bus;
2071 		ccb.ccb_h.target_id = target;
2072 		ccb.ccb_h.target_lun = lun;
2073 
2074 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2075 			warn("CAMIOCOMMAND ioctl failed");
2076 			error = 1;
2077 		}
2078 
2079 		if (error == 0) {
2080 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2081 			     CAM_FUNC_NOTAVAIL) {
2082 				warnx("CAM debugging not available");
2083 				warnx("you need to put options CAMDEBUG in"
2084 				      " your kernel config file!");
2085 				error = 1;
2086 			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2087 				    CAM_REQ_CMP) {
2088 				warnx("XPT_DEBUG CCB failed with status %#x",
2089 				      ccb.ccb_h.status);
2090 				error = 1;
2091 			} else {
2092 				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2093 					fprintf(stderr,
2094 						"Debugging turned off\n");
2095 				} else {
2096 					fprintf(stderr,
2097 						"Debugging enabled for "
2098 						"%d:%d:%d\n",
2099 						bus, target, lun);
2100 				}
2101 			}
2102 		}
2103 		close(fd);
2104 	}
2105 
2106 	return(error);
2107 }
2108 
2109 static int
2110 tagcontrol(struct cam_device *device, int argc, char **argv,
2111 	   char *combinedopt)
2112 {
2113 	int c;
2114 	union ccb *ccb;
2115 	int numtags = -1;
2116 	int retval = 0;
2117 	int quiet = 0;
2118 	char pathstr[1024];
2119 
2120 	ccb = cam_getccb(device);
2121 
2122 	if (ccb == NULL) {
2123 		warnx("tagcontrol: error allocating ccb");
2124 		return(1);
2125 	}
2126 
2127 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2128 		switch(c) {
2129 		case 'N':
2130 			numtags = strtol(optarg, NULL, 0);
2131 			if (numtags < 0) {
2132 				warnx("tag count %d is < 0", numtags);
2133 				retval = 1;
2134 				goto tagcontrol_bailout;
2135 			}
2136 			break;
2137 		case 'q':
2138 			quiet++;
2139 			break;
2140 		default:
2141 			break;
2142 		}
2143 	}
2144 
2145 	cam_path_string(device, pathstr, sizeof(pathstr));
2146 
2147 	if (numtags >= 0) {
2148 		bzero(&(&ccb->ccb_h)[1],
2149 		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2150 		ccb->ccb_h.func_code = XPT_REL_SIMQ;
2151 		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2152 		ccb->crs.openings = numtags;
2153 
2154 
2155 		if (cam_send_ccb(device, ccb) < 0) {
2156 			perror("error sending XPT_REL_SIMQ CCB");
2157 			retval = 1;
2158 			goto tagcontrol_bailout;
2159 		}
2160 
2161 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2162 			warnx("XPT_REL_SIMQ CCB failed");
2163 			cam_error_print(device, ccb, CAM_ESF_ALL,
2164 					CAM_EPF_ALL, stderr);
2165 			retval = 1;
2166 			goto tagcontrol_bailout;
2167 		}
2168 
2169 
2170 		if (quiet == 0)
2171 			fprintf(stdout, "%stagged openings now %d\n",
2172 				pathstr, ccb->crs.openings);
2173 	}
2174 
2175 	bzero(&(&ccb->ccb_h)[1],
2176 	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2177 
2178 	ccb->ccb_h.func_code = XPT_GDEV_STATS;
2179 
2180 	if (cam_send_ccb(device, ccb) < 0) {
2181 		perror("error sending XPT_GDEV_STATS CCB");
2182 		retval = 1;
2183 		goto tagcontrol_bailout;
2184 	}
2185 
2186 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2187 		warnx("XPT_GDEV_STATS CCB failed");
2188 		cam_error_print(device, ccb, CAM_ESF_ALL,
2189 				CAM_EPF_ALL, stderr);
2190 		retval = 1;
2191 		goto tagcontrol_bailout;
2192 	}
2193 
2194 	if (arglist & CAM_ARG_VERBOSE) {
2195 		fprintf(stdout, "%s", pathstr);
2196 		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2197 		fprintf(stdout, "%s", pathstr);
2198 		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2199 		fprintf(stdout, "%s", pathstr);
2200 		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2201 		fprintf(stdout, "%s", pathstr);
2202 		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2203 		fprintf(stdout, "%s", pathstr);
2204 		fprintf(stdout, "held          %d\n", ccb->cgds.held);
2205 		fprintf(stdout, "%s", pathstr);
2206 		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2207 		fprintf(stdout, "%s", pathstr);
2208 		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2209 	} else {
2210 		if (quiet == 0) {
2211 			fprintf(stdout, "%s", pathstr);
2212 			fprintf(stdout, "device openings: ");
2213 		}
2214 		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2215 			ccb->cgds.dev_active);
2216 	}
2217 
2218 tagcontrol_bailout:
2219 
2220 	cam_freeccb(ccb);
2221 	return(retval);
2222 }
2223 
2224 static void
2225 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2226 {
2227 	char pathstr[1024];
2228 
2229 	cam_path_string(device, pathstr, sizeof(pathstr));
2230 
2231 	if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
2232 
2233 		fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2234 			cts->sync_period);
2235 
2236 		if (cts->sync_offset != 0) {
2237 			u_int freq;
2238 
2239 			freq = scsi_calc_syncsrate(cts->sync_period);
2240 			fprintf(stdout, "%sfrequency: %d.%03dMHz\n", pathstr,
2241 				freq / 1000, freq % 1000);
2242 		}
2243 	}
2244 
2245 	if (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)
2246 		fprintf(stdout, "%soffset: %d\n", pathstr, cts->sync_offset);
2247 
2248 	if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID)
2249 		fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2250 			(0x01 << cts->bus_width) * 8);
2251 
2252 	if (cts->valid & CCB_TRANS_DISC_VALID)
2253 		fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2254 			(cts->flags & CCB_TRANS_DISC_ENB) ? "enabled" :
2255 			"disabled");
2256 
2257 	if (cts->valid & CCB_TRANS_TQ_VALID)
2258 		fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2259 			(cts->flags & CCB_TRANS_TAG_ENB) ? "enabled" :
2260 			"disabled");
2261 
2262 }
2263 
2264 /*
2265  * Get a path inquiry CCB for the specified device.
2266  */
2267 static int
2268 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2269 {
2270 	union ccb *ccb;
2271 	int retval = 0;
2272 
2273 	ccb = cam_getccb(device);
2274 
2275 	if (ccb == NULL) {
2276 		warnx("get_cpi: couldn't allocate CCB");
2277 		return(1);
2278 	}
2279 
2280 	bzero(&(&ccb->ccb_h)[1],
2281 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2282 
2283 	ccb->ccb_h.func_code = XPT_PATH_INQ;
2284 
2285 	if (cam_send_ccb(device, ccb) < 0) {
2286 		warn("get_cpi: error sending Path Inquiry CCB");
2287 
2288 		if (arglist & CAM_ARG_VERBOSE)
2289 			cam_error_print(device, ccb, CAM_ESF_ALL,
2290 					CAM_EPF_ALL, stderr);
2291 
2292 		retval = 1;
2293 
2294 		goto get_cpi_bailout;
2295 	}
2296 
2297 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2298 
2299 		if (arglist & CAM_ARG_VERBOSE)
2300 			cam_error_print(device, ccb, CAM_ESF_ALL,
2301 					CAM_EPF_ALL, stderr);
2302 
2303 		retval = 1;
2304 
2305 		goto get_cpi_bailout;
2306 	}
2307 
2308 	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2309 
2310 get_cpi_bailout:
2311 
2312 	cam_freeccb(ccb);
2313 
2314 	return(retval);
2315 }
2316 
2317 static void
2318 cpi_print(struct ccb_pathinq *cpi)
2319 {
2320 	char adapter_str[1024];
2321 	int i;
2322 
2323 	snprintf(adapter_str, sizeof(adapter_str),
2324 		 "%s%d:", cpi->dev_name, cpi->unit_number);
2325 
2326 	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2327 		cpi->version_num);
2328 
2329 	for (i = 1; i < 0xff; i = i << 1) {
2330 		char *str;
2331 
2332 		if ((i & cpi->hba_inquiry) == 0)
2333 			continue;
2334 
2335 		fprintf(stdout, "%s supports ", adapter_str);
2336 
2337 		switch(i) {
2338 		case PI_MDP_ABLE:
2339 			str = "MDP message";
2340 			break;
2341 		case PI_WIDE_32:
2342 			str = "32 bit wide SCSI";
2343 			break;
2344 		case PI_WIDE_16:
2345 			str = "16 bit wide SCSI";
2346 			break;
2347 		case PI_SDTR_ABLE:
2348 			str = "SDTR message";
2349 			break;
2350 		case PI_LINKED_CDB:
2351 			str = "linked CDBs";
2352 			break;
2353 		case PI_TAG_ABLE:
2354 			str = "tag queue messages";
2355 			break;
2356 		case PI_SOFT_RST:
2357 			str = "soft reset alternative";
2358 			break;
2359 		default:
2360 			str = "unknown PI bit set";
2361 			break;
2362 		}
2363 		fprintf(stdout, "%s\n", str);
2364 	}
2365 
2366 	for (i = 1; i < 0xff; i = i << 1) {
2367 		char *str;
2368 
2369 		if ((i & cpi->hba_misc) == 0)
2370 			continue;
2371 
2372 		fprintf(stdout, "%s ", adapter_str);
2373 
2374 		switch(i) {
2375 		case PIM_SCANHILO:
2376 			str = "bus scans from high ID to low ID";
2377 			break;
2378 		case PIM_NOREMOVE:
2379 			str = "removable devices not included in scan";
2380 			break;
2381 		case PIM_NOINITIATOR:
2382 			str = "initiator role not supported";
2383 			break;
2384 		case PIM_NOBUSRESET:
2385 			str = "user has disabled initial BUS RESET or"
2386 			      " controller is in target/mixed mode";
2387 			break;
2388 		default:
2389 			str = "unknown PIM bit set";
2390 			break;
2391 		}
2392 		fprintf(stdout, "%s\n", str);
2393 	}
2394 
2395 	for (i = 1; i < 0xff; i = i << 1) {
2396 		char *str;
2397 
2398 		if ((i & cpi->target_sprt) == 0)
2399 			continue;
2400 
2401 		fprintf(stdout, "%s supports ", adapter_str);
2402 		switch(i) {
2403 		case PIT_PROCESSOR:
2404 			str = "target mode processor mode";
2405 			break;
2406 		case PIT_PHASE:
2407 			str = "target mode phase cog. mode";
2408 			break;
2409 		case PIT_DISCONNECT:
2410 			str = "disconnects in target mode";
2411 			break;
2412 		case PIT_TERM_IO:
2413 			str = "terminate I/O message in target mode";
2414 			break;
2415 		case PIT_GRP_6:
2416 			str = "group 6 commands in target mode";
2417 			break;
2418 		case PIT_GRP_7:
2419 			str = "group 7 commands in target mode";
2420 			break;
2421 		default:
2422 			str = "unknown PIT bit set";
2423 			break;
2424 		}
2425 
2426 		fprintf(stdout, "%s\n", str);
2427 	}
2428 	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
2429 		cpi->hba_eng_cnt);
2430 	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
2431 		cpi->max_target);
2432 	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
2433 		cpi->max_lun);
2434 	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
2435 		adapter_str, cpi->hpath_id);
2436 	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
2437 		cpi->initiator_id);
2438 	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
2439 	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
2440 	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
2441 	fprintf(stdout, "%s base transfer speed: ", adapter_str);
2442 	if (cpi->base_transfer_speed > 1000)
2443 		fprintf(stdout, "%d.%03dMB/sec\n",
2444 			cpi->base_transfer_speed / 1000,
2445 			cpi->base_transfer_speed % 1000);
2446 	else
2447 		fprintf(stdout, "%dKB/sec\n",
2448 			(cpi->base_transfer_speed % 1000) * 1000);
2449 }
2450 
2451 static int
2452 get_print_cts(struct cam_device *device, int user_settings, int quiet,
2453 	      struct ccb_trans_settings *cts)
2454 {
2455 	int retval;
2456 	union ccb *ccb;
2457 
2458 	retval = 0;
2459 	ccb = cam_getccb(device);
2460 
2461 	if (ccb == NULL) {
2462 		warnx("get_print_cts: error allocating ccb");
2463 		return(1);
2464 	}
2465 
2466 	bzero(&(&ccb->ccb_h)[1],
2467 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2468 
2469 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
2470 
2471 	if (user_settings == 0)
2472 		ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
2473 	else
2474 		ccb->cts.flags = CCB_TRANS_USER_SETTINGS;
2475 
2476 	if (cam_send_ccb(device, ccb) < 0) {
2477 		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
2478 		if (arglist & CAM_ARG_VERBOSE)
2479 			cam_error_print(device, ccb, CAM_ESF_ALL,
2480 					CAM_EPF_ALL, stderr);
2481 		retval = 1;
2482 		goto get_print_cts_bailout;
2483 	}
2484 
2485 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2486 		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
2487 		if (arglist & CAM_ARG_VERBOSE)
2488 			cam_error_print(device, ccb, CAM_ESF_ALL,
2489 					CAM_EPF_ALL, stderr);
2490 		retval = 1;
2491 		goto get_print_cts_bailout;
2492 	}
2493 
2494 	if (quiet == 0)
2495 		cts_print(device, &ccb->cts);
2496 
2497 	if (cts != NULL)
2498 		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
2499 
2500 get_print_cts_bailout:
2501 
2502 	cam_freeccb(ccb);
2503 
2504 	return(retval);
2505 }
2506 
2507 static int
2508 ratecontrol(struct cam_device *device, int retry_count, int timeout,
2509 	    int argc, char **argv, char *combinedopt)
2510 {
2511 	int c;
2512 	union ccb *ccb;
2513 	int user_settings = 0;
2514 	int retval = 0;
2515 	int disc_enable = -1, tag_enable = -1;
2516 	int offset = -1;
2517 	double syncrate = -1;
2518 	int bus_width = -1;
2519 	int quiet = 0;
2520 	int change_settings = 0, send_tur = 0;
2521 	struct ccb_pathinq cpi;
2522 
2523 	ccb = cam_getccb(device);
2524 
2525 	if (ccb == NULL) {
2526 		warnx("ratecontrol: error allocating ccb");
2527 		return(1);
2528 	}
2529 
2530 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2531 		switch(c){
2532 		case 'a':
2533 			send_tur = 1;
2534 			break;
2535 		case 'c':
2536 			user_settings = 0;
2537 			break;
2538 		case 'D':
2539 			if (strncasecmp(optarg, "enable", 6) == 0)
2540 				disc_enable = 1;
2541 			else if (strncasecmp(optarg, "disable", 7) == 0)
2542 				disc_enable = 0;
2543 			else {
2544 				warnx("-D argument \"%s\" is unknown", optarg);
2545 				retval = 1;
2546 				goto ratecontrol_bailout;
2547 			}
2548 			change_settings = 1;
2549 			break;
2550 		case 'O':
2551 			offset = strtol(optarg, NULL, 0);
2552 			if (offset < 0) {
2553 				warnx("offset value %d is < 0", offset);
2554 				retval = 1;
2555 				goto ratecontrol_bailout;
2556 			}
2557 			change_settings = 1;
2558 			break;
2559 		case 'q':
2560 			quiet++;
2561 			break;
2562 		case 'R':
2563 			syncrate = atof(optarg);
2564 
2565 			if (syncrate < 0) {
2566 				warnx("sync rate %f is < 0", syncrate);
2567 				retval = 1;
2568 				goto ratecontrol_bailout;
2569 			}
2570 			change_settings = 1;
2571 			break;
2572 		case 'T':
2573 			if (strncasecmp(optarg, "enable", 6) == 0)
2574 				tag_enable = 1;
2575 			else if (strncasecmp(optarg, "disable", 7) == 0)
2576 				tag_enable = 0;
2577 			else {
2578 				warnx("-T argument \"%s\" is unknown", optarg);
2579 				retval = 1;
2580 				goto ratecontrol_bailout;
2581 			}
2582 			change_settings = 1;
2583 			break;
2584 		case 'U':
2585 			user_settings = 1;
2586 			break;
2587 		case 'W':
2588 			bus_width = strtol(optarg, NULL, 0);
2589 			if (bus_width < 0) {
2590 				warnx("bus width %d is < 0", bus_width);
2591 				retval = 1;
2592 				goto ratecontrol_bailout;
2593 			}
2594 			change_settings = 1;
2595 			break;
2596 		default:
2597 			break;
2598 		}
2599 	}
2600 
2601 	bzero(&(&ccb->ccb_h)[1],
2602 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2603 
2604 	/*
2605 	 * Grab path inquiry information, so we can determine whether
2606 	 * or not the initiator is capable of the things that the user
2607 	 * requests.
2608 	 */
2609 	ccb->ccb_h.func_code = XPT_PATH_INQ;
2610 
2611 	if (cam_send_ccb(device, ccb) < 0) {
2612 		perror("error sending XPT_PATH_INQ CCB");
2613 		if (arglist & CAM_ARG_VERBOSE) {
2614 			cam_error_print(device, ccb, CAM_ESF_ALL,
2615 					CAM_EPF_ALL, stderr);
2616 		}
2617 		retval = 1;
2618 		goto ratecontrol_bailout;
2619 	}
2620 
2621 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2622 		warnx("XPT_PATH_INQ CCB failed");
2623 		if (arglist & CAM_ARG_VERBOSE) {
2624 			cam_error_print(device, ccb, CAM_ESF_ALL,
2625 					CAM_EPF_ALL, stderr);
2626 		}
2627 		retval = 1;
2628 		goto ratecontrol_bailout;
2629 	}
2630 
2631 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
2632 
2633 	bzero(&(&ccb->ccb_h)[1],
2634 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2635 
2636 	if (quiet == 0)
2637 		fprintf(stdout, "Current Parameters:\n");
2638 
2639 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
2640 
2641 	if (retval != 0)
2642 		goto ratecontrol_bailout;
2643 
2644 	if (arglist & CAM_ARG_VERBOSE)
2645 		cpi_print(&cpi);
2646 
2647 	if (change_settings) {
2648 		if (disc_enable != -1) {
2649 			ccb->cts.valid |= CCB_TRANS_DISC_VALID;
2650 			if (disc_enable == 0)
2651 				ccb->cts.flags &= ~CCB_TRANS_DISC_ENB;
2652 			else
2653 				ccb->cts.flags |= CCB_TRANS_DISC_ENB;
2654 		} else
2655 			ccb->cts.valid &= ~CCB_TRANS_DISC_VALID;
2656 
2657 		if (tag_enable != -1) {
2658 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
2659 				warnx("HBA does not support tagged queueing, "
2660 				      "so you cannot modify tag settings");
2661 				retval = 1;
2662 				goto ratecontrol_bailout;
2663 			}
2664 
2665 			ccb->cts.valid |= CCB_TRANS_TQ_VALID;
2666 
2667 			if (tag_enable == 0)
2668 				ccb->cts.flags &= ~CCB_TRANS_TAG_ENB;
2669 			else
2670 				ccb->cts.flags |= CCB_TRANS_TAG_ENB;
2671 		} else
2672 			ccb->cts.valid &= ~CCB_TRANS_TQ_VALID;
2673 
2674 		if (offset != -1) {
2675 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2676 				warnx("HBA at %s%d is not cable of changing "
2677 				      "offset", cpi.dev_name,
2678 				      cpi.unit_number);
2679 				retval = 1;
2680 				goto ratecontrol_bailout;
2681 			}
2682 			ccb->cts.valid |= CCB_TRANS_SYNC_OFFSET_VALID;
2683 			ccb->cts.sync_offset = offset;
2684 		} else
2685 			ccb->cts.valid &= ~CCB_TRANS_SYNC_OFFSET_VALID;
2686 
2687 		if (syncrate != -1) {
2688 			int prelim_sync_period;
2689 			u_int freq;
2690 
2691 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2692 				warnx("HBA at %s%d is not cable of changing "
2693 				      "transfer rates", cpi.dev_name,
2694 				      cpi.unit_number);
2695 				retval = 1;
2696 				goto ratecontrol_bailout;
2697 			}
2698 
2699 			ccb->cts.valid |= CCB_TRANS_SYNC_RATE_VALID;
2700 
2701 			/*
2702 			 * The sync rate the user gives us is in MHz.
2703 			 * We need to translate it into KHz for this
2704 			 * calculation.
2705 			 */
2706 			syncrate *= 1000;
2707 
2708 			/*
2709 			 * Next, we calculate a "preliminary" sync period
2710 			 * in tenths of a nanosecond.
2711 			 */
2712 			if (syncrate == 0)
2713 				prelim_sync_period = 0;
2714 			else
2715 				prelim_sync_period = 10000000 / syncrate;
2716 
2717 			ccb->cts.sync_period =
2718 				scsi_calc_syncparam(prelim_sync_period);
2719 
2720 			freq = scsi_calc_syncsrate(ccb->cts.sync_period);
2721 		} else
2722 			ccb->cts.valid &= ~CCB_TRANS_SYNC_RATE_VALID;
2723 
2724 		/*
2725 		 * The bus_width argument goes like this:
2726 		 * 0 == 8 bit
2727 		 * 1 == 16 bit
2728 		 * 2 == 32 bit
2729 		 * Therefore, if you shift the number of bits given on the
2730 		 * command line right by 4, you should get the correct
2731 		 * number.
2732 		 */
2733 		if (bus_width != -1) {
2734 
2735 			/*
2736 			 * We might as well validate things here with a
2737 			 * decipherable error message, rather than what
2738 			 * will probably be an indecipherable error message
2739 			 * by the time it gets back to us.
2740 			 */
2741 			if ((bus_width == 16)
2742 			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
2743 				warnx("HBA does not support 16 bit bus width");
2744 				retval = 1;
2745 				goto ratecontrol_bailout;
2746 			} else if ((bus_width == 32)
2747 				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
2748 				warnx("HBA does not support 32 bit bus width");
2749 				retval = 1;
2750 				goto ratecontrol_bailout;
2751 			} else if ((bus_width != 8)
2752 				&& (bus_width != 16)
2753 				&& (bus_width != 32)) {
2754 				warnx("Invalid bus width %d", bus_width);
2755 				retval = 1;
2756 				goto ratecontrol_bailout;
2757 			}
2758 
2759 			ccb->cts.valid |= CCB_TRANS_BUS_WIDTH_VALID;
2760 			ccb->cts.bus_width = bus_width >> 4;
2761 		} else
2762 			ccb->cts.valid &= ~CCB_TRANS_BUS_WIDTH_VALID;
2763 
2764 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
2765 
2766 		if (cam_send_ccb(device, ccb) < 0) {
2767 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
2768 			if (arglist & CAM_ARG_VERBOSE) {
2769 				cam_error_print(device, ccb, CAM_ESF_ALL,
2770 						CAM_EPF_ALL, stderr);
2771 			}
2772 			retval = 1;
2773 			goto ratecontrol_bailout;
2774 		}
2775 
2776 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2777 			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
2778 			if (arglist & CAM_ARG_VERBOSE) {
2779 				cam_error_print(device, ccb, CAM_ESF_ALL,
2780 						CAM_EPF_ALL, stderr);
2781 			}
2782 			retval = 1;
2783 			goto ratecontrol_bailout;
2784 		}
2785 	}
2786 
2787 	if (send_tur) {
2788 		retval = testunitready(device, retry_count, timeout,
2789 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
2790 
2791 		/*
2792 		 * If the TUR didn't succeed, just bail.
2793 		 */
2794 		if (retval != 0) {
2795 			if (quiet == 0)
2796 				fprintf(stderr, "Test Unit Ready failed\n");
2797 			goto ratecontrol_bailout;
2798 		}
2799 
2800 		/*
2801 		 * If the user wants things quiet, there's no sense in
2802 		 * getting the transfer settings, if we're not going
2803 		 * to print them.
2804 		 */
2805 		if (quiet != 0)
2806 			goto ratecontrol_bailout;
2807 
2808 		fprintf(stdout, "New Parameters:\n");
2809 		retval = get_print_cts(device, user_settings, 0, NULL);
2810 	}
2811 
2812 ratecontrol_bailout:
2813 
2814 	cam_freeccb(ccb);
2815 	return(retval);
2816 }
2817 
2818 static int
2819 scsiformat(struct cam_device *device, int argc, char **argv,
2820 	   char *combinedopt, int retry_count, int timeout)
2821 {
2822 	union ccb *ccb;
2823 	int c;
2824 	int ycount = 0, quiet = 0;
2825 	int error = 0, response = 0, retval = 0;
2826 	int use_timeout = 10800 * 1000;
2827 	int immediate = 1;
2828 	struct format_defect_list_header fh;
2829 	u_int8_t *data_ptr = NULL;
2830 	u_int32_t dxfer_len = 0;
2831 	u_int8_t byte2 = 0;
2832 	int num_warnings = 0;
2833 
2834 	ccb = cam_getccb(device);
2835 
2836 	if (ccb == NULL) {
2837 		warnx("scsiformat: error allocating ccb");
2838 		return(1);
2839 	}
2840 
2841 	bzero(&(&ccb->ccb_h)[1],
2842 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2843 
2844 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2845 		switch(c) {
2846 		case 'q':
2847 			quiet++;
2848 			break;
2849 		case 'w':
2850 			immediate = 0;
2851 			break;
2852 		case 'y':
2853 			ycount++;
2854 			break;
2855 		}
2856 	}
2857 
2858 	if (quiet == 0) {
2859 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
2860 			"following device:\n");
2861 
2862 		error = scsidoinquiry(device, argc, argv, combinedopt,
2863 				      retry_count, timeout);
2864 
2865 		if (error != 0) {
2866 			warnx("scsiformat: error sending inquiry");
2867 			goto scsiformat_bailout;
2868 		}
2869 	}
2870 
2871 	if (ycount == 0) {
2872 
2873 		do {
2874 			char str[1024];
2875 
2876 			fprintf(stdout, "Are you SURE you want to do "
2877 				"this? (yes/no) ");
2878 
2879 			if (fgets(str, sizeof(str), stdin) != NULL) {
2880 
2881 				if (strncasecmp(str, "yes", 3) == 0)
2882 					response = 1;
2883 				else if (strncasecmp(str, "no", 2) == 0)
2884 					response = -1;
2885 				else {
2886 					fprintf(stdout, "Please answer"
2887 						" \"yes\" or \"no\"\n");
2888 				}
2889 			}
2890 		} while (response == 0);
2891 
2892 		if (response == -1) {
2893 			error = 1;
2894 			goto scsiformat_bailout;
2895 		}
2896 	}
2897 
2898 	if (timeout != 0)
2899 		use_timeout = timeout;
2900 
2901 	if (quiet == 0) {
2902 		fprintf(stdout, "Current format timeout is %d seconds\n",
2903 			use_timeout / 1000);
2904 	}
2905 
2906 	/*
2907 	 * If the user hasn't disabled questions and didn't specify a
2908 	 * timeout on the command line, ask them if they want the current
2909 	 * timeout.
2910 	 */
2911 	if ((ycount == 0)
2912 	 && (timeout == 0)) {
2913 		char str[1024];
2914 		int new_timeout = 0;
2915 
2916 		fprintf(stdout, "Enter new timeout in seconds or press\n"
2917 			"return to keep the current timeout [%d] ",
2918 			use_timeout / 1000);
2919 
2920 		if (fgets(str, sizeof(str), stdin) != NULL) {
2921 			if (str[0] != '\0')
2922 				new_timeout = atoi(str);
2923 		}
2924 
2925 		if (new_timeout != 0) {
2926 			use_timeout = new_timeout * 1000;
2927 			fprintf(stdout, "Using new timeout value %d\n",
2928 				use_timeout / 1000);
2929 		}
2930 	}
2931 
2932 	/*
2933 	 * Keep this outside the if block below to silence any unused
2934 	 * variable warnings.
2935 	 */
2936 	bzero(&fh, sizeof(fh));
2937 
2938 	/*
2939 	 * If we're in immediate mode, we've got to include the format
2940 	 * header
2941 	 */
2942 	if (immediate != 0) {
2943 		fh.byte2 = FU_DLH_IMMED;
2944 		data_ptr = (u_int8_t *)&fh;
2945 		dxfer_len = sizeof(fh);
2946 		byte2 = FU_FMT_DATA;
2947 	} else if (quiet == 0) {
2948 		fprintf(stdout, "Formatting...");
2949 		fflush(stdout);
2950 	}
2951 
2952 	scsi_format_unit(&ccb->csio,
2953 			 /* retries */ retry_count,
2954 			 /* cbfcnp */ NULL,
2955 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
2956 			 /* byte2 */ byte2,
2957 			 /* ileave */ 0,
2958 			 /* data_ptr */ data_ptr,
2959 			 /* dxfer_len */ dxfer_len,
2960 			 /* sense_len */ SSD_FULL_SIZE,
2961 			 /* timeout */ use_timeout);
2962 
2963 	/* Disable freezing the device queue */
2964 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2965 
2966 	if (arglist & CAM_ARG_ERR_RECOVER)
2967 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2968 
2969 	if (((retval = cam_send_ccb(device, ccb)) < 0)
2970 	 || ((immediate == 0)
2971 	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
2972 		const char errstr[] = "error sending format command";
2973 
2974 		if (retval < 0)
2975 			warn(errstr);
2976 		else
2977 			warnx(errstr);
2978 
2979 		if (arglist & CAM_ARG_VERBOSE) {
2980 			cam_error_print(device, ccb, CAM_ESF_ALL,
2981 					CAM_EPF_ALL, stderr);
2982 		}
2983 		error = 1;
2984 		goto scsiformat_bailout;
2985 	}
2986 
2987 	/*
2988 	 * If we ran in non-immediate mode, we already checked for errors
2989 	 * above and printed out any necessary information.  If we're in
2990 	 * immediate mode, we need to loop through and get status
2991 	 * information periodically.
2992 	 */
2993 	if (immediate == 0) {
2994 		if (quiet == 0) {
2995 			fprintf(stdout, "Format Complete\n");
2996 		}
2997 		goto scsiformat_bailout;
2998 	}
2999 
3000 	do {
3001 		cam_status status;
3002 
3003 		bzero(&(&ccb->ccb_h)[1],
3004 		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3005 
3006 		/*
3007 		 * There's really no need to do error recovery or
3008 		 * retries here, since we're just going to sit in a
3009 		 * loop and wait for the device to finish formatting.
3010 		 */
3011 		scsi_test_unit_ready(&ccb->csio,
3012 				     /* retries */ 0,
3013 				     /* cbfcnp */ NULL,
3014 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
3015 				     /* sense_len */ SSD_FULL_SIZE,
3016 				     /* timeout */ 5000);
3017 
3018 		/* Disable freezing the device queue */
3019 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3020 
3021 		retval = cam_send_ccb(device, ccb);
3022 
3023 		/*
3024 		 * If we get an error from the ioctl, bail out.  SCSI
3025 		 * errors are expected.
3026 		 */
3027 		if (retval < 0) {
3028 			warn("error sending CAMIOCOMMAND ioctl");
3029 			if (arglist & CAM_ARG_VERBOSE) {
3030 				cam_error_print(device, ccb, CAM_ESF_ALL,
3031 						CAM_EPF_ALL, stderr);
3032 			}
3033 			error = 1;
3034 			goto scsiformat_bailout;
3035 		}
3036 
3037 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
3038 
3039 		if ((status != CAM_REQ_CMP)
3040 		 && (status == CAM_SCSI_STATUS_ERROR)
3041 		 && ((status & CAM_AUTOSNS_VALID) != 0)) {
3042 			struct scsi_sense_data *sense;
3043 			int error_code, sense_key, asc, ascq;
3044 
3045 			sense = &ccb->csio.sense_data;
3046 			scsi_extract_sense(sense, &error_code, &sense_key,
3047 					   &asc, &ascq);
3048 
3049 			/*
3050 			 * According to the SCSI-2 and SCSI-3 specs, a
3051 			 * drive that is in the middle of a format should
3052 			 * return NOT READY with an ASC of "logical unit
3053 			 * not ready, format in progress".  The sense key
3054 			 * specific bytes will then be a progress indicator.
3055 			 */
3056 			if ((sense_key == SSD_KEY_NOT_READY)
3057 			 && (asc == 0x04) && (ascq == 0x04)) {
3058 				if ((sense->extra_len >= 10)
3059 				 && ((sense->sense_key_spec[0] &
3060 				      SSD_SCS_VALID) != 0)
3061 				 && (quiet == 0)) {
3062 					int val;
3063 					u_int64_t percentage;
3064 
3065 					val = scsi_2btoul(
3066 						&sense->sense_key_spec[1]);
3067 					percentage = 10000 * val;
3068 
3069 					fprintf(stdout,
3070 						"\rFormatting:  %qd.%02qd %% "
3071 						"(%d/%d) done",
3072 						percentage / (0x10000 * 100),
3073 						(percentage / 0x10000) % 100,
3074 						val, 0x10000);
3075 					fflush(stdout);
3076 				} else if ((quiet == 0)
3077 					&& (++num_warnings <= 1)) {
3078 					warnx("Unexpected SCSI Sense Key "
3079 					      "Specific value returned "
3080 					      "during format:");
3081 					scsi_sense_print(device, &ccb->csio,
3082 							 stderr);
3083 					warnx("Unable to print status "
3084 					      "information, but format will "
3085 					      "proceed.");
3086 					warnx("will exit when format is "
3087 					      "complete");
3088 				}
3089 				sleep(1);
3090 			} else {
3091 				warnx("Unexpected SCSI error during format");
3092 				cam_error_print(device, ccb, CAM_ESF_ALL,
3093 						CAM_EPF_ALL, stderr);
3094 				error = 1;
3095 				goto scsiformat_bailout;
3096 			}
3097 
3098 		} else if (status != CAM_REQ_CMP) {
3099 			warnx("Unexpected CAM status %#x", status);
3100 			if (arglist & CAM_ARG_VERBOSE)
3101 				cam_error_print(device, ccb, CAM_ESF_ALL,
3102 						CAM_EPF_ALL, stderr);
3103 			error = 1;
3104 			goto scsiformat_bailout;
3105 		}
3106 
3107 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3108 
3109 	if (quiet == 0)
3110 		fprintf(stdout, "\nFormat Complete\n");
3111 
3112 scsiformat_bailout:
3113 
3114 	cam_freeccb(ccb);
3115 
3116 	return(error);
3117 }
3118 #endif /* MINIMALISTIC */
3119 
3120 void
3121 usage(int verbose)
3122 {
3123 	fprintf(verbose ? stdout : stderr,
3124 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
3125 "        camcontrol devlist    [-v]\n"
3126 #ifndef MINIMALISTIC
3127 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
3128 "        camcontrol tur        [dev_id][generic args]\n"
3129 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
3130 "        camcontrol start      [dev_id][generic args]\n"
3131 "        camcontrol stop       [dev_id][generic args]\n"
3132 "        camcontrol eject      [dev_id][generic args]\n"
3133 #endif /* MINIMALISTIC */
3134 "        camcontrol rescan     <all | bus[:target:lun]>\n"
3135 "        camcontrol reset      <all | bus[:target:lun]>\n"
3136 #ifndef MINIMALISTIC
3137 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
3138 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
3139 "                              [-P pagectl][-e | -b][-d]\n"
3140 "        camcontrol cmd        [dev_id][generic args] <-c cmd [args]>\n"
3141 "                              [-i len fmt|-o len fmt [args]]\n"
3142 "        camcontrol debug      [-I][-T][-S][-c] <all|bus[:target[:lun]]|off>\n"
3143 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
3144 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
3145 "                              [-D <enable|disable>][-O offset][-q]\n"
3146 "                              [-R syncrate][-v][-T <enable|disable>]\n"
3147 "                              [-U][-W bus_width]\n"
3148 "        camcontrol format     [dev_id][generic args][-q][-w][-y]\n"
3149 #endif /* MINIMALISTIC */
3150 "        camcontrol help\n");
3151 	if (!verbose)
3152 		return;
3153 #ifndef MINIMALISTIC
3154 	fprintf(stdout,
3155 "Specify one of the following options:\n"
3156 "devlist     list all CAM devices\n"
3157 "periphlist  list all CAM peripheral drivers attached to a device\n"
3158 "tur         send a test unit ready to the named device\n"
3159 "inquiry     send a SCSI inquiry command to the named device\n"
3160 "start       send a Start Unit command to the device\n"
3161 "stop        send a Stop Unit command to the device\n"
3162 "eject       send a Stop Unit command to the device with the eject bit set\n"
3163 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
3164 "reset       reset all busses, the given bus, or bus:target:lun\n"
3165 "defects     read the defect list of the specified device\n"
3166 "modepage    display or edit (-e) the given mode page\n"
3167 "cmd         send the given scsi command, may need -i or -o as well\n"
3168 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
3169 "tags        report or set the number of transaction slots for a device\n"
3170 "negotiate   report or set device negotiation parameters\n"
3171 "format      send the SCSI FORMAT UNIT command to the named device\n"
3172 "help        this message\n"
3173 "Device Identifiers:\n"
3174 "bus:target        specify the bus and target, lun defaults to 0\n"
3175 "bus:target:lun    specify the bus, target and lun\n"
3176 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
3177 "Generic arguments:\n"
3178 "-v                be verbose, print out sense information\n"
3179 "-t timeout        command timeout in seconds, overrides default timeout\n"
3180 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
3181 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
3182 "-E                have the kernel attempt to perform SCSI error recovery\n"
3183 "-C count          specify the SCSI command retry count (needs -E to work)\n"
3184 "modepage arguments:\n"
3185 "-l                list all available mode pages\n"
3186 "-m page           specify the mode page to view or edit\n"
3187 "-e                edit the specified mode page\n"
3188 "-b                force view to binary mode\n"
3189 "-d                disable block descriptors for mode sense\n"
3190 "-P pgctl          page control field 0-3\n"
3191 "defects arguments:\n"
3192 "-f format         specify defect list format (block, bfi or phys)\n"
3193 "-G                get the grown defect list\n"
3194 "-P                get the permanant defect list\n"
3195 "inquiry arguments:\n"
3196 "-D                get the standard inquiry data\n"
3197 "-S                get the serial number\n"
3198 "-R                get the transfer rate, etc.\n"
3199 "cmd arguments:\n"
3200 "-c cdb [args]     specify the SCSI CDB\n"
3201 "-i len fmt        specify input data and input data format\n"
3202 "-o len fmt [args] specify output data and output data fmt\n"
3203 "debug arguments:\n"
3204 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
3205 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
3206 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
3207 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
3208 "tags arguments:\n"
3209 "-N tags           specify the number of tags to use for this device\n"
3210 "-q                be quiet, don't report the number of tags\n"
3211 "-v                report a number of tag-related parameters\n"
3212 "negotiate arguments:\n"
3213 "-a                send a test unit ready after negotiation\n"
3214 "-c                report/set current negotiation settings\n"
3215 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
3216 "-O offset         set command delay offset\n"
3217 "-q                be quiet, don't report anything\n"
3218 "-R syncrate       synchronization rate in MHz\n"
3219 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
3220 "-U                report/set user negotiation settings\n"
3221 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
3222 "-v                also print a Path Inquiry CCB for the controller\n"
3223 "format arguments:\n"
3224 "-q                be quiet, don't print status messages\n"
3225 "-w                don't send immediate format command\n"
3226 "-y                don't ask any questions\n");
3227 #endif /* MINIMALISTIC */
3228 }
3229 
3230 int
3231 main(int argc, char **argv)
3232 {
3233 	int c;
3234 	char *device = NULL;
3235 	int unit = 0;
3236 	struct cam_device *cam_dev = NULL;
3237 	int timeout = 0, retry_count = 1;
3238 	camcontrol_optret optreturn;
3239 	char *tstr;
3240 	char *mainopt = "C:En:t:u:v";
3241 	char *subopt = NULL;
3242 	char combinedopt[256];
3243 	int error = 0, optstart = 2;
3244 	int devopen = 1;
3245 
3246 	arglist = CAM_ARG_NONE;
3247 
3248 	if (argc < 2) {
3249 		usage(0);
3250 		exit(1);
3251 	}
3252 
3253 	/*
3254 	 * Get the base option.
3255 	 */
3256 	optreturn = getoption(argv[1], &arglist, &subopt);
3257 
3258 	if (optreturn == CC_OR_AMBIGUOUS) {
3259 		warnx("ambiguous option %s", argv[1]);
3260 		usage(0);
3261 		exit(1);
3262 	} else if (optreturn == CC_OR_NOT_FOUND) {
3263 		warnx("option %s not found", argv[1]);
3264 		usage(0);
3265 		exit(1);
3266 	}
3267 
3268 	/*
3269 	 * Ahh, getopt(3) is a pain.
3270 	 *
3271 	 * This is a gross hack.  There really aren't many other good
3272 	 * options (excuse the pun) for parsing options in a situation like
3273 	 * this.  getopt is kinda braindead, so you end up having to run
3274 	 * through the options twice, and give each invocation of getopt
3275 	 * the option string for the other invocation.
3276 	 *
3277 	 * You would think that you could just have two groups of options.
3278 	 * The first group would get parsed by the first invocation of
3279 	 * getopt, and the second group would get parsed by the second
3280 	 * invocation of getopt.  It doesn't quite work out that way.  When
3281 	 * the first invocation of getopt finishes, it leaves optind pointing
3282 	 * to the argument _after_ the first argument in the second group.
3283 	 * So when the second invocation of getopt comes around, it doesn't
3284 	 * recognize the first argument it gets and then bails out.
3285 	 *
3286 	 * A nice alternative would be to have a flag for getopt that says
3287 	 * "just keep parsing arguments even when you encounter an unknown
3288 	 * argument", but there isn't one.  So there's no real clean way to
3289 	 * easily parse two sets of arguments without having one invocation
3290 	 * of getopt know about the other.
3291 	 *
3292 	 * Without this hack, the first invocation of getopt would work as
3293 	 * long as the generic arguments are first, but the second invocation
3294 	 * (in the subfunction) would fail in one of two ways.  In the case
3295 	 * where you don't set optreset, it would fail because optind may be
3296 	 * pointing to the argument after the one it should be pointing at.
3297 	 * In the case where you do set optreset, and reset optind, it would
3298 	 * fail because getopt would run into the first set of options, which
3299 	 * it doesn't understand.
3300 	 *
3301 	 * All of this would "sort of" work if you could somehow figure out
3302 	 * whether optind had been incremented one option too far.  The
3303 	 * mechanics of that, however, are more daunting than just giving
3304 	 * both invocations all of the expect options for either invocation.
3305 	 *
3306 	 * Needless to say, I wouldn't mind if someone invented a better
3307 	 * (non-GPL!) command line parsing interface than getopt.  I
3308 	 * wouldn't mind if someone added more knobs to getopt to make it
3309 	 * work better.  Who knows, I may talk myself into doing it someday,
3310 	 * if the standards weenies let me.  As it is, it just leads to
3311 	 * hackery like this and causes people to avoid it in some cases.
3312 	 *
3313 	 * KDM, September 8th, 1998
3314 	 */
3315 	if (subopt != NULL)
3316 		sprintf(combinedopt, "%s%s", mainopt, subopt);
3317 	else
3318 		sprintf(combinedopt, "%s", mainopt);
3319 
3320 	/*
3321 	 * For these options we do not parse optional device arguments and
3322 	 * we do not open a passthrough device.
3323 	 */
3324 	if (((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESCAN)
3325 	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESET)
3326 	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEVTREE)
3327 	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_USAGE)
3328 	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEBUG))
3329 		devopen = 0;
3330 
3331 #ifndef MINIMALISTIC
3332 	if ((devopen == 1)
3333 	 && (argc > 2 && argv[2][0] != '-')) {
3334 		char name[30];
3335 		int rv;
3336 
3337 		/*
3338 		 * First catch people who try to do things like:
3339 		 * camcontrol tur /dev/da0
3340 		 * camcontrol doesn't take device nodes as arguments.
3341 		 */
3342 		if (argv[2][0] == '/') {
3343 			warnx("%s is not a valid device identifier", argv[2]);
3344 			errx(1, "please read the camcontrol(8) man page");
3345 		} else if (isdigit(argv[2][0])) {
3346 			/* device specified as bus:target[:lun] */
3347 			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
3348 			if (rv < 2)
3349 				errx(1, "numeric device specification must "
3350 				     "be either bus:target, or "
3351 				     "bus:target:lun");
3352 			optstart++;
3353 		} else {
3354 			if (cam_get_device(argv[2], name, sizeof name, &unit)
3355 			    == -1)
3356 				errx(1, "%s", cam_errbuf);
3357 			device = strdup(name);
3358 			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
3359 			optstart++;
3360 		}
3361 	}
3362 #endif /* MINIMALISTIC */
3363 	/*
3364 	 * Start getopt processing at argv[2/3], since we've already
3365 	 * accepted argv[1..2] as the command name, and as a possible
3366 	 * device name.
3367 	 */
3368 	optind = optstart;
3369 
3370 	/*
3371 	 * Now we run through the argument list looking for generic
3372 	 * options, and ignoring options that possibly belong to
3373 	 * subfunctions.
3374 	 */
3375 	while ((c = getopt(argc, argv, combinedopt))!= -1){
3376 		switch(c) {
3377 			case 'C':
3378 				retry_count = strtol(optarg, NULL, 0);
3379 				if (retry_count < 0)
3380 					errx(1, "retry count %d is < 0",
3381 					     retry_count);
3382 				arglist |= CAM_ARG_RETRIES;
3383 				break;
3384 			case 'E':
3385 				arglist |= CAM_ARG_ERR_RECOVER;
3386 				break;
3387 			case 'n':
3388 				arglist |= CAM_ARG_DEVICE;
3389 				tstr = optarg;
3390 				while (isspace(*tstr) && (*tstr != '\0'))
3391 					tstr++;
3392 				device = (char *)strdup(tstr);
3393 				break;
3394 			case 't':
3395 				timeout = strtol(optarg, NULL, 0);
3396 				if (timeout < 0)
3397 					errx(1, "invalid timeout %d", timeout);
3398 				/* Convert the timeout from seconds to ms */
3399 				timeout *= 1000;
3400 				arglist |= CAM_ARG_TIMEOUT;
3401 				break;
3402 			case 'u':
3403 				arglist |= CAM_ARG_UNIT;
3404 				unit = strtol(optarg, NULL, 0);
3405 				break;
3406 			case 'v':
3407 				arglist |= CAM_ARG_VERBOSE;
3408 				break;
3409 			default:
3410 				break;
3411 		}
3412 	}
3413 
3414 #ifndef MINIMALISTIC
3415 	/*
3416 	 * For most commands we'll want to open the passthrough device
3417 	 * associated with the specified device.  In the case of the rescan
3418 	 * commands, we don't use a passthrough device at all, just the
3419 	 * transport layer device.
3420 	 */
3421 	if (devopen == 1) {
3422 		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
3423 		 && (((arglist & CAM_ARG_DEVICE) == 0)
3424 		  || ((arglist & CAM_ARG_UNIT) == 0))) {
3425 			errx(1, "subcommand \"%s\" requires a valid device "
3426 			     "identifier", argv[1]);
3427 		}
3428 
3429 		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
3430 				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
3431 				cam_open_spec_device(device,unit,O_RDWR,NULL)))
3432 		     == NULL)
3433 			errx(1,"%s", cam_errbuf);
3434 	}
3435 #endif /* MINIMALISTIC */
3436 
3437 	/*
3438 	 * Reset optind to 2, and reset getopt, so these routines can parse
3439 	 * the arguments again.
3440 	 */
3441 	optind = optstart;
3442 	optreset = 1;
3443 
3444 	switch(arglist & CAM_ARG_OPT_MASK) {
3445 #ifndef MINIMALISTIC
3446 		case CAM_ARG_DEVLIST:
3447 			error = getdevlist(cam_dev);
3448 			break;
3449 #endif /* MINIMALISTIC */
3450 		case CAM_ARG_DEVTREE:
3451 			error = getdevtree();
3452 			break;
3453 #ifndef MINIMALISTIC
3454 		case CAM_ARG_TUR:
3455 			error = testunitready(cam_dev, retry_count, timeout, 0);
3456 			break;
3457 		case CAM_ARG_INQUIRY:
3458 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
3459 					      retry_count, timeout);
3460 			break;
3461 		case CAM_ARG_STARTSTOP:
3462 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
3463 					  arglist & CAM_ARG_EJECT, retry_count,
3464 					  timeout);
3465 			break;
3466 #endif /* MINIMALISTIC */
3467 		case CAM_ARG_RESCAN:
3468 			error = dorescan_or_reset(argc, argv, 1);
3469 			break;
3470 		case CAM_ARG_RESET:
3471 			error = dorescan_or_reset(argc, argv, 0);
3472 			break;
3473 #ifndef MINIMALISTIC
3474 		case CAM_ARG_READ_DEFECTS:
3475 			error = readdefects(cam_dev, argc, argv, combinedopt,
3476 					    retry_count, timeout);
3477 			break;
3478 		case CAM_ARG_MODE_PAGE:
3479 			modepage(cam_dev, argc, argv, combinedopt,
3480 				 retry_count, timeout);
3481 			break;
3482 		case CAM_ARG_SCSI_CMD:
3483 			error = scsicmd(cam_dev, argc, argv, combinedopt,
3484 					retry_count, timeout);
3485 			break;
3486 		case CAM_ARG_DEBUG:
3487 			error = camdebug(argc, argv, combinedopt);
3488 			break;
3489 		case CAM_ARG_TAG:
3490 			error = tagcontrol(cam_dev, argc, argv, combinedopt);
3491 			break;
3492 		case CAM_ARG_RATE:
3493 			error = ratecontrol(cam_dev, retry_count, timeout,
3494 					    argc, argv, combinedopt);
3495 			break;
3496 		case CAM_ARG_FORMAT:
3497 			error = scsiformat(cam_dev, argc, argv,
3498 					   combinedopt, retry_count, timeout);
3499 			break;
3500 #endif /* MINIMALISTIC */
3501 		case CAM_ARG_USAGE:
3502 			usage(1);
3503 			break;
3504 		default:
3505 			usage(0);
3506 			error = 1;
3507 			break;
3508 	}
3509 
3510 	if (cam_dev != NULL)
3511 		cam_close_device(cam_dev);
3512 
3513 	exit(error);
3514 }
3515