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