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