xref: /dragonfly/sbin/camcontrol/camcontrol.c (revision 7bc7e232)
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: src/sbin/camcontrol/camcontrol.c,v 1.21.2.13 2003/01/08 17:55:02 njl Exp $
29  * $DragonFly: src/sbin/camcontrol/camcontrol.c,v 1.6 2007/11/24 01:38:46 pavalos Exp $
30  */
31 
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <ctype.h>
40 #include <err.h>
41 
42 #include <cam/cam.h>
43 #include <cam/cam_debug.h>
44 #include <cam/cam_ccb.h>
45 #include <cam/scsi/scsi_all.h>
46 #include <cam/scsi/scsi_da.h>
47 #include <cam/scsi/scsi_pass.h>
48 #include <cam/scsi/scsi_message.h>
49 #include <camlib.h>
50 #include "camcontrol.h"
51 
52 typedef enum {
53 	CAM_CMD_NONE		= 0x00000000,
54 	CAM_CMD_DEVLIST		= 0x00000001,
55 	CAM_CMD_TUR		= 0x00000002,
56 	CAM_CMD_INQUIRY		= 0x00000003,
57 	CAM_CMD_STARTSTOP	= 0x00000004,
58 	CAM_CMD_RESCAN		= 0x00000005,
59 	CAM_CMD_READ_DEFECTS	= 0x00000006,
60 	CAM_CMD_MODE_PAGE	= 0x00000007,
61 	CAM_CMD_SCSI_CMD	= 0x00000008,
62 	CAM_CMD_DEVTREE		= 0x00000009,
63 	CAM_CMD_USAGE		= 0x0000000a,
64 	CAM_CMD_DEBUG		= 0x0000000b,
65 	CAM_CMD_RESET		= 0x0000000c,
66 	CAM_CMD_FORMAT		= 0x0000000d,
67 	CAM_CMD_TAG		= 0x0000000e,
68 	CAM_CMD_RATE		= 0x0000000f,
69 	CAM_CMD_DETACH		= 0x00000010,
70 } cam_cmdmask;
71 
72 typedef enum {
73 	CAM_ARG_NONE		= 0x00000000,
74 	CAM_ARG_VERBOSE		= 0x00000001,
75 	CAM_ARG_DEVICE		= 0x00000002,
76 	CAM_ARG_BUS		= 0x00000004,
77 	CAM_ARG_TARGET		= 0x00000008,
78 	CAM_ARG_LUN		= 0x00000010,
79 	CAM_ARG_EJECT		= 0x00000020,
80 	CAM_ARG_UNIT		= 0x00000040,
81 	CAM_ARG_FORMAT_BLOCK	= 0x00000080,
82 	CAM_ARG_FORMAT_BFI	= 0x00000100,
83 	CAM_ARG_FORMAT_PHYS	= 0x00000200,
84 	CAM_ARG_PLIST		= 0x00000400,
85 	CAM_ARG_GLIST		= 0x00000800,
86 	CAM_ARG_GET_SERIAL	= 0x00001000,
87 	CAM_ARG_GET_STDINQ	= 0x00002000,
88 	CAM_ARG_GET_XFERRATE	= 0x00004000,
89 	CAM_ARG_INQ_MASK	= 0x00007000,
90 	CAM_ARG_MODE_EDIT	= 0x00008000,
91 	CAM_ARG_PAGE_CNTL	= 0x00010000,
92 	CAM_ARG_TIMEOUT		= 0x00020000,
93 	CAM_ARG_CMD_IN		= 0x00040000,
94 	CAM_ARG_CMD_OUT		= 0x00080000,
95 	CAM_ARG_DBD		= 0x00100000,
96 	CAM_ARG_ERR_RECOVER	= 0x00200000,
97 	CAM_ARG_RETRIES		= 0x00400000,
98 	CAM_ARG_START_UNIT	= 0x00800000,
99 	CAM_ARG_DEBUG_INFO	= 0x01000000,
100 	CAM_ARG_DEBUG_TRACE	= 0x02000000,
101 	CAM_ARG_DEBUG_SUBTRACE	= 0x04000000,
102 	CAM_ARG_DEBUG_CDB	= 0x08000000,
103 	CAM_ARG_DEBUG_XPT	= 0x10000000,
104 	CAM_ARG_DEBUG_PERIPH	= 0x20000000,
105 } cam_argmask;
106 
107 struct camcontrol_opts {
108 	const char 	*optname;
109 	cam_cmdmask	cmdnum;
110 	cam_argmask	argnum;
111 	const char	*subopt;
112 };
113 
114 #ifndef MINIMALISTIC
115 static const char scsicmd_opts[] = "c:i:o:";
116 static const char readdefect_opts[] = "f:GP";
117 static const char negotiate_opts[] = "acD:O:qR:T:UW:";
118 #endif
119 
120 struct camcontrol_opts option_table[] = {
121 #ifndef MINIMALISTIC
122 	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
123 	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
124 	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
125 	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
126 	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
127 	{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
128 #endif /* MINIMALISTIC */
129 	{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
130 	{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
131 #ifndef MINIMALISTIC
132 	{"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
133 	{"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
134 	{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
135 	{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
136 #endif /* MINIMALISTIC */
137 	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
138 #ifndef MINIMALISTIC
139 	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
140 	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
141 	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
142 	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
143 	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
144 	{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
145 	{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qwy"},
146 #endif /* MINIMALISTIC */
147 	{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
148 	{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
149 	{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
150 	{NULL, 0, 0, NULL}
151 };
152 
153 typedef enum {
154 	CC_OR_NOT_FOUND,
155 	CC_OR_AMBIGUOUS,
156 	CC_OR_FOUND
157 } camcontrol_optret;
158 
159 cam_cmdmask cmdlist;
160 cam_argmask arglist;
161 int bus, target, lun;
162 
163 
164 camcontrol_optret	getoption(char *, cam_cmdmask *, cam_argmask *,
165 				  const char **);
166 #ifndef MINIMALISTIC
167 static int	getdevlist(struct cam_device *);
168 static int	getdevtree(void);
169 static int	testunitready(struct cam_device *, int, int, int);
170 static int	scsistart(struct cam_device *, int, int, int, int);
171 static int	scsidoinquiry(struct cam_device *, int, char **, char *, int,
172 		int);
173 static int	scsiinquiry(struct cam_device *, int, int);
174 static int	scsiserial(struct cam_device *, int, int);
175 static int	scsixferrate(struct cam_device *);
176 #endif /* MINIMALISTIC */
177 static int	parse_btl(char *, int *, int *, int *, cam_argmask *);
178 static int	dorescan_or_reset(int, char **, int);
179 static int	rescan_or_reset_bus(int, int);
180 static int	scanlun_or_reset_dev(int, int, int, int);
181 #ifndef MINIMALISTIC
182 static int	readdefects(struct cam_device *, int, char **, char *, int,
183 		int);
184 static void	modepage(struct cam_device *, int, char **, char *, int, int);
185 static int	scsicmd(struct cam_device *, int, char **, char *, int, int);
186 static int	tagcontrol(struct cam_device *, int, char **, char *);
187 static void	cts_print(struct cam_device *device,
188 		struct ccb_trans_settings *);
189 static void	cpi_print(struct ccb_pathinq *);
190 static int	get_cpi(struct cam_device *, struct ccb_pathinq *);
191 static int	get_print_cts(struct cam_device *, int, int,
192 			 struct ccb_trans_settings *);
193 static int	ratecontrol(struct cam_device *, int, int, int, char **,
194 		char *);
195 static int	scsiformat(struct cam_device *, int, char **, char *, int, int);
196 #endif /* MINIMALISTIC */
197 
198 
199 camcontrol_optret
200 getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
201 	  const char **subopt)
202 {
203 	struct camcontrol_opts *opts;
204 	int num_matches = 0;
205 
206 	for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
207 	     opts++) {
208 		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
209 			*cmdnum = opts->cmdnum;
210 			*argnum = opts->argnum;
211 			*subopt = opts->subopt;
212 			if (++num_matches > 1)
213 				return(CC_OR_AMBIGUOUS);
214 		}
215 	}
216 
217 	if (num_matches > 0)
218 		return(CC_OR_FOUND);
219 	else
220 		return(CC_OR_NOT_FOUND);
221 }
222 
223 #ifndef MINIMALISTIC
224 static int
225 getdevlist(struct cam_device *device)
226 {
227 	union ccb *ccb;
228 	char status[32];
229 	int error = 0;
230 
231 	ccb = cam_getccb(device);
232 
233 	ccb->ccb_h.func_code = XPT_GDEVLIST;
234 	ccb->ccb_h.flags = CAM_DIR_NONE;
235 	ccb->ccb_h.retry_count = 1;
236 	ccb->cgdl.index = 0;
237 	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
238 	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
239 		if (cam_send_ccb(device, ccb) < 0) {
240 			perror("error getting device list");
241 			cam_freeccb(ccb);
242 			return(1);
243 		}
244 
245 		status[0] = '\0';
246 
247 		switch (ccb->cgdl.status) {
248 			case CAM_GDEVLIST_MORE_DEVS:
249 				strcpy(status, "MORE");
250 				break;
251 			case CAM_GDEVLIST_LAST_DEVICE:
252 				strcpy(status, "LAST");
253 				break;
254 			case CAM_GDEVLIST_LIST_CHANGED:
255 				strcpy(status, "CHANGED");
256 				break;
257 			case CAM_GDEVLIST_ERROR:
258 				strcpy(status, "ERROR");
259 				error = 1;
260 				break;
261 		}
262 
263 		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
264 			ccb->cgdl.periph_name,
265 			ccb->cgdl.unit_number,
266 			ccb->cgdl.generation,
267 			ccb->cgdl.index,
268 			status);
269 
270 		/*
271 		 * If the list has changed, we need to start over from the
272 		 * beginning.
273 		 */
274 		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
275 			ccb->cgdl.index = 0;
276 	}
277 
278 	cam_freeccb(ccb);
279 
280 	return(error);
281 }
282 #endif /* MINIMALISTIC */
283 
284 static int
285 getdevtree(void)
286 {
287 	union ccb ccb;
288 	int bufsize, fd;
289 	unsigned int i;
290 	int need_close = 0;
291 	int error = 0;
292 	int skip_device = 0;
293 
294 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
295 		warn("couldn't open %s", XPT_DEVICE);
296 		return(1);
297 	}
298 
299 	bzero(&(&ccb.ccb_h)[1],
300 	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
301 
302 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
303 	bufsize = sizeof(struct dev_match_result) * 100;
304 	ccb.cdm.match_buf_len = bufsize;
305 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
306 	if (ccb.cdm.matches == NULL) {
307 		warnx("can't malloc memory for matches");
308 		close(fd);
309 		return(1);
310 	}
311 	ccb.cdm.num_matches = 0;
312 
313 	/*
314 	 * We fetch all nodes, since we display most of them in the default
315 	 * case, and all in the verbose case.
316 	 */
317 	ccb.cdm.num_patterns = 0;
318 	ccb.cdm.pattern_buf_len = 0;
319 
320 	/*
321 	 * We do the ioctl multiple times if necessary, in case there are
322 	 * more than 100 nodes in the EDT.
323 	 */
324 	do {
325 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
326 			warn("error sending CAMIOCOMMAND ioctl");
327 			error = 1;
328 			break;
329 		}
330 
331 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
332 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
333 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
334 			warnx("got CAM error %#x, CDM error %d\n",
335 			      ccb.ccb_h.status, ccb.cdm.status);
336 			error = 1;
337 			break;
338 		}
339 
340 		for (i = 0; i < ccb.cdm.num_matches; i++) {
341 			switch (ccb.cdm.matches[i].type) {
342 			case DEV_MATCH_BUS: {
343 				struct bus_match_result *bus_result;
344 
345 				/*
346 				 * Only print the bus information if the
347 				 * user turns on the verbose flag.
348 				 */
349 				if ((arglist & CAM_ARG_VERBOSE) == 0)
350 					break;
351 
352 				bus_result =
353 					&ccb.cdm.matches[i].result.bus_result;
354 
355 				if (need_close) {
356 					fprintf(stdout, ")\n");
357 					need_close = 0;
358 				}
359 
360 				fprintf(stdout, "scbus%d on %s%d bus %d:\n",
361 					bus_result->path_id,
362 					bus_result->dev_name,
363 					bus_result->unit_number,
364 					bus_result->bus_id);
365 				break;
366 			}
367 			case DEV_MATCH_DEVICE: {
368 				struct device_match_result *dev_result;
369 				char vendor[16], product[48], revision[16];
370 				char tmpstr[256];
371 
372 				dev_result =
373 				     &ccb.cdm.matches[i].result.device_result;
374 
375 				if ((dev_result->flags
376 				     & DEV_RESULT_UNCONFIGURED)
377 				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
378 					skip_device = 1;
379 					break;
380 				} else
381 					skip_device = 0;
382 
383 				cam_strvis(vendor, dev_result->inq_data.vendor,
384 					   sizeof(dev_result->inq_data.vendor),
385 					   sizeof(vendor));
386 				cam_strvis(product,
387 					   dev_result->inq_data.product,
388 					   sizeof(dev_result->inq_data.product),
389 					   sizeof(product));
390 				cam_strvis(revision,
391 					   dev_result->inq_data.revision,
392 					  sizeof(dev_result->inq_data.revision),
393 					   sizeof(revision));
394 				sprintf(tmpstr, "<%s %s %s>", vendor, product,
395 					revision);
396 				if (need_close) {
397 					fprintf(stdout, ")\n");
398 					need_close = 0;
399 				}
400 
401 				fprintf(stdout, "%-33s  at scbus%d "
402 					"target %d lun %d (",
403 					tmpstr,
404 					dev_result->path_id,
405 					dev_result->target_id,
406 					dev_result->target_lun);
407 
408 				need_close = 1;
409 
410 				break;
411 			}
412 			case DEV_MATCH_PERIPH: {
413 				struct periph_match_result *periph_result;
414 
415 				periph_result =
416 				      &ccb.cdm.matches[i].result.periph_result;
417 
418 				if (skip_device != 0)
419 					break;
420 
421 				if (need_close > 1)
422 					fprintf(stdout, ",");
423 
424 				fprintf(stdout, "%s%d",
425 					periph_result->periph_name,
426 					periph_result->unit_number);
427 
428 				need_close++;
429 				break;
430 			}
431 			default:
432 				fprintf(stdout, "unknown match type\n");
433 				break;
434 			}
435 		}
436 
437 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
438 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
439 
440 	if (need_close)
441 		fprintf(stdout, ")\n");
442 
443 	close(fd);
444 
445 	return(error);
446 }
447 
448 #ifndef MINIMALISTIC
449 static int
450 testunitready(struct cam_device *device, int retry_count, int timeout,
451 	      int quiet)
452 {
453 	int error = 0;
454 	union ccb *ccb;
455 
456 	ccb = cam_getccb(device);
457 
458 	scsi_test_unit_ready(&ccb->csio,
459 			     /* retries */ retry_count,
460 			     /* cbfcnp */ NULL,
461 			     /* tag_action */ MSG_SIMPLE_Q_TAG,
462 			     /* sense_len */ SSD_FULL_SIZE,
463 			     /* timeout */ timeout ? timeout : 5000);
464 
465 	/* Disable freezing the device queue */
466 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
467 
468 	if (arglist & CAM_ARG_ERR_RECOVER)
469 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
470 
471 	if (cam_send_ccb(device, ccb) < 0) {
472 		if (quiet == 0)
473 			perror("error sending test unit ready");
474 
475 		if (arglist & CAM_ARG_VERBOSE) {
476 			cam_error_print(device, ccb, CAM_ESF_ALL,
477 					CAM_EPF_ALL, stderr);
478 		}
479 
480 		cam_freeccb(ccb);
481 		return(1);
482 	}
483 
484 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
485 		if (quiet == 0)
486 			fprintf(stdout, "Unit is ready\n");
487 	} else {
488 		if (quiet == 0)
489 			fprintf(stdout, "Unit is not ready\n");
490 		error = 1;
491 
492 		if (arglist & CAM_ARG_VERBOSE) {
493 			cam_error_print(device, ccb, CAM_ESF_ALL,
494 					CAM_EPF_ALL, stderr);
495 		}
496 	}
497 
498 	cam_freeccb(ccb);
499 
500 	return(error);
501 }
502 
503 static int
504 scsistart(struct cam_device *device, int startstop, int loadeject,
505 	  int retry_count, int timeout)
506 {
507 	union ccb *ccb;
508 	int error = 0;
509 
510 	ccb = cam_getccb(device);
511 
512 	/*
513 	 * If we're stopping, send an ordered tag so the drive in question
514 	 * will finish any previously queued writes before stopping.  If
515 	 * the device isn't capable of tagged queueing, or if tagged
516 	 * queueing is turned off, the tag action is a no-op.
517 	 */
518 	scsi_start_stop(&ccb->csio,
519 			/* retries */ retry_count,
520 			/* cbfcnp */ NULL,
521 			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
522 						     MSG_ORDERED_Q_TAG,
523 			/* start/stop */ startstop,
524 			/* load_eject */ loadeject,
525 			/* immediate */ 0,
526 			/* sense_len */ SSD_FULL_SIZE,
527 			/* timeout */ timeout ? timeout : 120000);
528 
529 	/* Disable freezing the device queue */
530 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
531 
532 	if (arglist & CAM_ARG_ERR_RECOVER)
533 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
534 
535 	if (cam_send_ccb(device, ccb) < 0) {
536 		perror("error sending start unit");
537 
538 		if (arglist & CAM_ARG_VERBOSE) {
539 			cam_error_print(device, ccb, CAM_ESF_ALL,
540 					CAM_EPF_ALL, stderr);
541 		}
542 
543 		cam_freeccb(ccb);
544 		return(1);
545 	}
546 
547 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
548 		if (startstop) {
549 			fprintf(stdout, "Unit started successfully");
550 			if (loadeject)
551 				fprintf(stdout,", Media loaded\n");
552 			else
553 				fprintf(stdout,"\n");
554 		} else {
555 			fprintf(stdout, "Unit stopped successfully");
556 			if (loadeject)
557 				fprintf(stdout, ", Media ejected\n");
558 			else
559 				fprintf(stdout, "\n");
560 		}
561 	else {
562 		error = 1;
563 		if (startstop)
564 			fprintf(stdout,
565 				"Error received from start unit command\n");
566 		else
567 			fprintf(stdout,
568 				"Error received from stop unit command\n");
569 
570 		if (arglist & CAM_ARG_VERBOSE) {
571 			cam_error_print(device, ccb, CAM_ESF_ALL,
572 					CAM_EPF_ALL, stderr);
573 		}
574 	}
575 
576 	cam_freeccb(ccb);
577 
578 	return(error);
579 }
580 
581 static int
582 scsidoinquiry(struct cam_device *device, int argc, char **argv,
583 	      char *combinedopt, int retry_count, int timeout)
584 {
585 	int c;
586 	int error = 0;
587 
588 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
589 		switch(c) {
590 		case 'D':
591 			arglist |= CAM_ARG_GET_STDINQ;
592 			break;
593 		case 'R':
594 			arglist |= CAM_ARG_GET_XFERRATE;
595 			break;
596 		case 'S':
597 			arglist |= CAM_ARG_GET_SERIAL;
598 			break;
599 		default:
600 			break;
601 		}
602 	}
603 
604 	/*
605 	 * If the user didn't specify any inquiry options, he wants all of
606 	 * them.
607 	 */
608 	if ((arglist & CAM_ARG_INQ_MASK) == 0)
609 		arglist |= CAM_ARG_INQ_MASK;
610 
611 	if (arglist & CAM_ARG_GET_STDINQ)
612 		error = scsiinquiry(device, retry_count, timeout);
613 
614 	if (error != 0)
615 		return(error);
616 
617 	if (arglist & CAM_ARG_GET_SERIAL)
618 		scsiserial(device, retry_count, timeout);
619 
620 	if (error != 0)
621 		return(error);
622 
623 	if (arglist & CAM_ARG_GET_XFERRATE)
624 		error = scsixferrate(device);
625 
626 	return(error);
627 }
628 
629 static int
630 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
631 {
632 	union ccb *ccb;
633 	struct scsi_inquiry_data *inq_buf;
634 	int error = 0;
635 
636 	ccb = cam_getccb(device);
637 
638 	if (ccb == NULL) {
639 		warnx("couldn't allocate CCB");
640 		return(1);
641 	}
642 
643 	/* cam_getccb cleans up the header, caller has to zero the payload */
644 	bzero(&(&ccb->ccb_h)[1],
645 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
646 
647 	inq_buf = (struct scsi_inquiry_data *)malloc(
648 		sizeof(struct scsi_inquiry_data));
649 
650 	if (inq_buf == NULL) {
651 		cam_freeccb(ccb);
652 		warnx("can't malloc memory for inquiry\n");
653 		return(1);
654 	}
655 	bzero(inq_buf, sizeof(*inq_buf));
656 
657 	/*
658 	 * Note that although the size of the inquiry buffer is the full
659 	 * 256 bytes specified in the SCSI spec, we only tell the device
660 	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
661 	 * two reasons for this:
662 	 *
663 	 *  - The SCSI spec says that when a length field is only 1 byte,
664 	 *    a value of 0 will be interpreted as 256.  Therefore
665 	 *    scsi_inquiry() will convert an inq_len (which is passed in as
666 	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
667 	 *    to 0.  Evidently, very few devices meet the spec in that
668 	 *    regard.  Some devices, like many Seagate disks, take the 0 as
669 	 *    0, and don't return any data.  One Pioneer DVD-R drive
670 	 *    returns more data than the command asked for.
671 	 *
672 	 *    So, since there are numerous devices that just don't work
673 	 *    right with the full inquiry size, we don't send the full size.
674 	 *
675 	 *  - The second reason not to use the full inquiry data length is
676 	 *    that we don't need it here.  The only reason we issue a
677 	 *    standard inquiry is to get the vendor name, device name,
678 	 *    and revision so scsi_print_inquiry() can print them.
679 	 *
680 	 * If, at some point in the future, more inquiry data is needed for
681 	 * some reason, this code should use a procedure similar to the
682 	 * probe code.  i.e., issue a short inquiry, and determine from
683 	 * the additional length passed back from the device how much
684 	 * inquiry data the device supports.  Once the amount the device
685 	 * supports is determined, issue an inquiry for that amount and no
686 	 * more.
687 	 *
688 	 * KDM, 2/18/2000
689 	 */
690 	scsi_inquiry(&ccb->csio,
691 		     /* retries */ retry_count,
692 		     /* cbfcnp */ NULL,
693 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
694 		     /* inq_buf */ (u_int8_t *)inq_buf,
695 		     /* inq_len */ SHORT_INQUIRY_LENGTH,
696 		     /* evpd */ 0,
697 		     /* page_code */ 0,
698 		     /* sense_len */ SSD_FULL_SIZE,
699 		     /* timeout */ timeout ? timeout : 5000);
700 
701 	/* Disable freezing the device queue */
702 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
703 
704 	if (arglist & CAM_ARG_ERR_RECOVER)
705 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
706 
707 	if (cam_send_ccb(device, ccb) < 0) {
708 		perror("error sending SCSI inquiry");
709 
710 		if (arglist & CAM_ARG_VERBOSE) {
711 			cam_error_print(device, ccb, CAM_ESF_ALL,
712 					CAM_EPF_ALL, stderr);
713 		}
714 
715 		cam_freeccb(ccb);
716 		return(1);
717 	}
718 
719 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
720 		error = 1;
721 
722 		if (arglist & CAM_ARG_VERBOSE) {
723 			cam_error_print(device, ccb, CAM_ESF_ALL,
724 					CAM_EPF_ALL, stderr);
725 		}
726 	}
727 
728 	cam_freeccb(ccb);
729 
730 	if (error != 0) {
731 		free(inq_buf);
732 		return(error);
733 	}
734 
735 	fprintf(stdout, "%s%d: ", device->device_name,
736 		device->dev_unit_num);
737 	scsi_print_inquiry(inq_buf);
738 
739 	free(inq_buf);
740 
741 	return(0);
742 }
743 
744 static int
745 scsiserial(struct cam_device *device, int retry_count, int timeout)
746 {
747 	union ccb *ccb;
748 	struct scsi_vpd_unit_serial_number *serial_buf;
749 	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
750 	int error = 0;
751 
752 	ccb = cam_getccb(device);
753 
754 	if (ccb == NULL) {
755 		warnx("couldn't allocate CCB");
756 		return(1);
757 	}
758 
759 	/* cam_getccb cleans up the header, caller has to zero the payload */
760 	bzero(&(&ccb->ccb_h)[1],
761 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
762 
763 	serial_buf = (struct scsi_vpd_unit_serial_number *)
764 		malloc(sizeof(*serial_buf));
765 
766 	if (serial_buf == NULL) {
767 		cam_freeccb(ccb);
768 		warnx("can't malloc memory for serial number");
769 		return(1);
770 	}
771 
772 	scsi_inquiry(&ccb->csio,
773 		     /*retries*/ retry_count,
774 		     /*cbfcnp*/ NULL,
775 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
776 		     /* inq_buf */ (u_int8_t *)serial_buf,
777 		     /* inq_len */ sizeof(*serial_buf),
778 		     /* evpd */ 1,
779 		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
780 		     /* sense_len */ SSD_FULL_SIZE,
781 		     /* timeout */ timeout ? timeout : 5000);
782 
783 	/* Disable freezing the device queue */
784 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
785 
786 	if (arglist & CAM_ARG_ERR_RECOVER)
787 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
788 
789 	if (cam_send_ccb(device, ccb) < 0) {
790 		warn("error getting serial number");
791 
792 		if (arglist & CAM_ARG_VERBOSE) {
793 			cam_error_print(device, ccb, CAM_ESF_ALL,
794 					CAM_EPF_ALL, stderr);
795 		}
796 
797 		cam_freeccb(ccb);
798 		free(serial_buf);
799 		return(1);
800 	}
801 
802 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
803 		error = 1;
804 
805 		if (arglist & CAM_ARG_VERBOSE) {
806 			cam_error_print(device, ccb, CAM_ESF_ALL,
807 					CAM_EPF_ALL, stderr);
808 		}
809 	}
810 
811 	cam_freeccb(ccb);
812 
813 	if (error != 0) {
814 		free(serial_buf);
815 		return(error);
816 	}
817 
818 	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
819 	serial_num[serial_buf->length] = '\0';
820 
821 	if ((arglist & CAM_ARG_GET_STDINQ)
822 	 || (arglist & CAM_ARG_GET_XFERRATE))
823 		fprintf(stdout, "%s%d: Serial Number ",
824 			device->device_name, device->dev_unit_num);
825 
826 	fprintf(stdout, "%.60s\n", serial_num);
827 
828 	free(serial_buf);
829 
830 	return(0);
831 }
832 
833 static int
834 scsixferrate(struct cam_device *device)
835 {
836 	u_int32_t freq;
837 	u_int32_t speed;
838 	union ccb *ccb;
839 	u_int mb;
840 	int retval = 0;
841 
842 	ccb = cam_getccb(device);
843 
844 	if (ccb == NULL) {
845 		warnx("couldn't allocate CCB");
846 		return(1);
847 	}
848 
849 	bzero(&(&ccb->ccb_h)[1],
850 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
851 
852 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
853 	ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
854 
855 	if (((retval = cam_send_ccb(device, ccb)) < 0)
856 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
857 		const char error_string[] = "error getting transfer settings";
858 
859 		if (retval < 0)
860 			warn(error_string);
861 		else
862 			warnx(error_string);
863 
864 		if (arglist & CAM_ARG_VERBOSE)
865 			cam_error_print(device, ccb, CAM_ESF_ALL,
866 					CAM_EPF_ALL, stderr);
867 
868 		retval = 1;
869 
870 		goto xferrate_bailout;
871 
872 	}
873 
874 	if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
875 	 && (ccb->cts.sync_offset != 0)) {
876 		freq = scsi_calc_syncsrate(ccb->cts.sync_period);
877 		speed = freq;
878 	} else {
879 		struct ccb_pathinq cpi;
880 
881 		retval = get_cpi(device, &cpi);
882 
883 		if (retval != 0)
884 			goto xferrate_bailout;
885 
886 		speed = cpi.base_transfer_speed;
887 		freq = 0;
888 	}
889 
890 	fprintf(stdout, "%s%d: ", device->device_name,
891 		device->dev_unit_num);
892 
893 	if ((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
894 		speed *= (0x01 << device->bus_width);
895 
896 	mb = speed / 1000;
897 
898 	if (mb > 0)
899 		fprintf(stdout, "%d.%03dMB/s transfers ",
900 			mb, speed % 1000);
901 	else
902 		fprintf(stdout, "%dKB/s transfers ",
903 			speed);
904 
905 	if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
906 	 && (ccb->cts.sync_offset != 0))
907                 fprintf(stdout, "(%d.%03dMHz, offset %d", freq / 1000,
908 			freq % 1000, ccb->cts.sync_offset);
909 
910 	if (((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
911 	 && (ccb->cts.bus_width > 0)) {
912 		if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
913 		 && (ccb->cts.sync_offset != 0)) {
914 			fprintf(stdout, ", ");
915 		} else {
916 			fprintf(stdout, " (");
917 		}
918 		fprintf(stdout, "%dbit)", 8 * (0x01 << ccb->cts.bus_width));
919 	} else if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
920 		&& (ccb->cts.sync_offset != 0)) {
921 		fprintf(stdout, ")");
922 	}
923 
924 	if (((ccb->cts.valid & CCB_TRANS_TQ_VALID) != 0)
925 	 && (ccb->cts.flags & CCB_TRANS_TAG_ENB))
926                 fprintf(stdout, ", Tagged Queueing Enabled");
927 
928         fprintf(stdout, "\n");
929 
930 xferrate_bailout:
931 
932 	cam_freeccb(ccb);
933 
934 	return(retval);
935 }
936 #endif /* MINIMALISTIC */
937 
938 /*
939  * Parse out a bus, or a bus, target and lun in the following
940  * format:
941  * bus
942  * bus:target
943  * bus:target:lun
944  *
945  * Returns the number of parsed components, or 0.
946  */
947 static int
948 parse_btl(char *tstr, int *mybus, int *mytarget, int *mylun,
949 	  cam_argmask *myarglist)
950 {
951 	char *tmpstr;
952 	int convs = 0;
953 
954 	while (isspace(*tstr) && (*tstr != '\0'))
955 		tstr++;
956 
957 	tmpstr = (char *)strtok(tstr, ":");
958 	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
959 		*mybus = strtol(tmpstr, NULL, 0);
960 		*myarglist |= CAM_ARG_BUS;
961 		convs++;
962 		tmpstr = (char *)strtok(NULL, ":");
963 		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
964 			*mytarget = strtol(tmpstr, NULL, 0);
965 			*myarglist |= CAM_ARG_TARGET;
966 			convs++;
967 			tmpstr = (char *)strtok(NULL, ":");
968 			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
969 				*mylun = strtol(tmpstr, NULL, 0);
970 				*myarglist |= CAM_ARG_LUN;
971 				convs++;
972 			}
973 		}
974 	}
975 
976 	return convs;
977 }
978 
979 static int
980 dorescan_or_reset(int argc, char **argv, int rescan)
981 {
982 	static const char must[] =
983 		"you must specify \"all\", a bus, or a bus:target:lun to %s";
984 	int rv, error = 0;
985 	int mybus = -1, mytarget = -1, mylun = -1;
986 	char *tstr;
987 
988 	if (argc < 3) {
989 		warnx(must, rescan? "rescan" : "reset");
990 		return(1);
991 	}
992 
993 	tstr = argv[optind];
994 	while (isspace(*tstr) && (*tstr != '\0'))
995 		tstr++;
996 	if (strncasecmp(tstr, "all", strlen("all")) == 0)
997 		arglist |= CAM_ARG_BUS;
998 	else {
999 		rv = parse_btl(argv[optind], &mybus, &mytarget, &mylun,
1000 			       &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(mybus, mytarget, mylun, rescan);
1011 	else
1012 		error = rescan_or_reset_bus(mybus, rescan);
1013 
1014 	return(error);
1015 }
1016 
1017 static int
1018 rescan_or_reset_bus(int mybus, 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 transport layer device %s", XPT_DEVICE);
1028 		warn("%s", XPT_DEVICE);
1029 		return(1);
1030 	}
1031 
1032 	if (mybus != -1) {
1033 		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1034 		ccb.ccb_h.path_id = mybus;
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", mybus);
1051 		} else {
1052 			fprintf(stdout, "%s of bus %d returned error %#x\n",
1053 				rescan ? "Re-scan" : "Reset", mybus,
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 mybus, int mytarget, int mylun, int scan)
1185 {
1186 	union ccb ccb;
1187 	struct cam_device *device;
1188 	int fd;
1189 
1190 	device = NULL;
1191 
1192 	if (mybus < 0) {
1193 		warnx("invalid bus number %d", mybus);
1194 		return(1);
1195 	}
1196 
1197 	if (mytarget < 0) {
1198 		warnx("invalid target number %d", mytarget);
1199 		return(1);
1200 	}
1201 
1202 	if (mylun < 0) {
1203 		warnx("invalid lun number %d", mylun);
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 transport layer device %s\n",
1214 			    XPT_DEVICE);
1215 			warn("%s", XPT_DEVICE);
1216 			return(1);
1217 		}
1218 	} else {
1219 		device = cam_open_btl(mybus, mytarget, mylun, 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 = mybus;
1228 	ccb.ccb_h.target_id = mytarget;
1229 	ccb.ccb_h.target_lun = mylun;
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", mybus, mytarget, mylun);
1263 		return(0);
1264 	} else {
1265 		fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1266 		    scan? "Re-scan" : "Reset", mybus, mytarget, mylun,
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 mybus = -1, mytarget = -1, mylun = -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 'P':
2013 			arglist |= CAM_ARG_DEBUG_PERIPH;
2014 			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2015 			break;
2016 		case 'S':
2017 			arglist |= CAM_ARG_DEBUG_SUBTRACE;
2018 			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2019 			break;
2020 		case 'T':
2021 			arglist |= CAM_ARG_DEBUG_TRACE;
2022 			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2023 			break;
2024 		case 'X':
2025 			arglist |= CAM_ARG_DEBUG_XPT;
2026 			ccb.cdbg.flags |= CAM_DEBUG_XPT;
2027 			break;
2028 		case 'c':
2029 			arglist |= CAM_ARG_DEBUG_CDB;
2030 			ccb.cdbg.flags |= CAM_DEBUG_CDB;
2031 			break;
2032 		default:
2033 			break;
2034 		}
2035 	}
2036 
2037 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2038 		warnx("error opening transport layer device %s", XPT_DEVICE);
2039 		warn("%s", XPT_DEVICE);
2040 		return(1);
2041 	}
2042 	argc -= optind;
2043 	argv += optind;
2044 
2045 	if (argc <= 0) {
2046 		warnx("you must specify \"off\", \"all\" or a bus,");
2047 		warnx("bus:target, or bus:target:lun");
2048 		close(fd);
2049 		return(1);
2050 	}
2051 
2052 	tstr = *argv;
2053 
2054 	while (isspace(*tstr) && (*tstr != '\0'))
2055 		tstr++;
2056 
2057 	if (strncmp(tstr, "off", 3) == 0) {
2058 		ccb.cdbg.flags = CAM_DEBUG_NONE;
2059 		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2060 			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2061 			     CAM_ARG_DEBUG_XPT);
2062 	} else if (strncmp(tstr, "all", 3) != 0) {
2063 		tmpstr = (char *)strtok(tstr, ":");
2064 		if ((tmpstr != NULL) && (*tmpstr != '\0')){
2065 			mybus = strtol(tmpstr, NULL, 0);
2066 			arglist |= CAM_ARG_BUS;
2067 			tmpstr = (char *)strtok(NULL, ":");
2068 			if ((tmpstr != NULL) && (*tmpstr != '\0')){
2069 				mytarget = strtol(tmpstr, NULL, 0);
2070 				arglist |= CAM_ARG_TARGET;
2071 				tmpstr = (char *)strtok(NULL, ":");
2072 				if ((tmpstr != NULL) && (*tmpstr != '\0')){
2073 					mylun = strtol(tmpstr, NULL, 0);
2074 					arglist |= CAM_ARG_LUN;
2075 				}
2076 			}
2077 		} else {
2078 			error = 1;
2079 			warnx("you must specify \"all\", \"off\", or a bus,");
2080 			warnx("bus:target, or bus:target:lun to debug");
2081 		}
2082 	}
2083 
2084 	if (error == 0) {
2085 
2086 		ccb.ccb_h.func_code = XPT_DEBUG;
2087 		ccb.ccb_h.path_id = mybus;
2088 		ccb.ccb_h.target_id = mytarget;
2089 		ccb.ccb_h.target_lun = mylun;
2090 
2091 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2092 			warn("CAMIOCOMMAND ioctl failed");
2093 			error = 1;
2094 		}
2095 
2096 		if (error == 0) {
2097 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2098 			     CAM_FUNC_NOTAVAIL) {
2099 				warnx("CAM debugging not available");
2100 				warnx("you need to put options CAMDEBUG in"
2101 				      " your kernel config file!");
2102 				error = 1;
2103 			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2104 				    CAM_REQ_CMP) {
2105 				warnx("XPT_DEBUG CCB failed with status %#x",
2106 				      ccb.ccb_h.status);
2107 				error = 1;
2108 			} else {
2109 				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2110 					fprintf(stderr,
2111 						"Debugging turned off\n");
2112 				} else {
2113 					fprintf(stderr,
2114 						"Debugging enabled for "
2115 						"%d:%d:%d\n",
2116 						mybus, mytarget, mylun);
2117 				}
2118 			}
2119 		}
2120 		close(fd);
2121 	}
2122 
2123 	return(error);
2124 }
2125 
2126 static int
2127 tagcontrol(struct cam_device *device, int argc, char **argv,
2128 	   char *combinedopt)
2129 {
2130 	int c;
2131 	union ccb *ccb;
2132 	int numtags = -1;
2133 	int retval = 0;
2134 	int quiet = 0;
2135 	char pathstr[1024];
2136 
2137 	ccb = cam_getccb(device);
2138 
2139 	if (ccb == NULL) {
2140 		warnx("tagcontrol: error allocating ccb");
2141 		return(1);
2142 	}
2143 
2144 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2145 		switch(c) {
2146 		case 'N':
2147 			numtags = strtol(optarg, NULL, 0);
2148 			if (numtags < 0) {
2149 				warnx("tag count %d is < 0", numtags);
2150 				retval = 1;
2151 				goto tagcontrol_bailout;
2152 			}
2153 			break;
2154 		case 'q':
2155 			quiet++;
2156 			break;
2157 		default:
2158 			break;
2159 		}
2160 	}
2161 
2162 	cam_path_string(device, pathstr, sizeof(pathstr));
2163 
2164 	if (numtags >= 0) {
2165 		bzero(&(&ccb->ccb_h)[1],
2166 		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2167 		ccb->ccb_h.func_code = XPT_REL_SIMQ;
2168 		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2169 		ccb->crs.openings = numtags;
2170 
2171 
2172 		if (cam_send_ccb(device, ccb) < 0) {
2173 			perror("error sending XPT_REL_SIMQ CCB");
2174 			retval = 1;
2175 			goto tagcontrol_bailout;
2176 		}
2177 
2178 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2179 			warnx("XPT_REL_SIMQ CCB failed");
2180 			cam_error_print(device, ccb, CAM_ESF_ALL,
2181 					CAM_EPF_ALL, stderr);
2182 			retval = 1;
2183 			goto tagcontrol_bailout;
2184 		}
2185 
2186 
2187 		if (quiet == 0)
2188 			fprintf(stdout, "%stagged openings now %d\n",
2189 				pathstr, ccb->crs.openings);
2190 	}
2191 
2192 	bzero(&(&ccb->ccb_h)[1],
2193 	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2194 
2195 	ccb->ccb_h.func_code = XPT_GDEV_STATS;
2196 
2197 	if (cam_send_ccb(device, ccb) < 0) {
2198 		perror("error sending XPT_GDEV_STATS CCB");
2199 		retval = 1;
2200 		goto tagcontrol_bailout;
2201 	}
2202 
2203 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2204 		warnx("XPT_GDEV_STATS CCB failed");
2205 		cam_error_print(device, ccb, CAM_ESF_ALL,
2206 				CAM_EPF_ALL, stderr);
2207 		retval = 1;
2208 		goto tagcontrol_bailout;
2209 	}
2210 
2211 	if (arglist & CAM_ARG_VERBOSE) {
2212 		fprintf(stdout, "%s", pathstr);
2213 		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2214 		fprintf(stdout, "%s", pathstr);
2215 		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2216 		fprintf(stdout, "%s", pathstr);
2217 		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2218 		fprintf(stdout, "%s", pathstr);
2219 		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2220 		fprintf(stdout, "%s", pathstr);
2221 		fprintf(stdout, "held          %d\n", ccb->cgds.held);
2222 		fprintf(stdout, "%s", pathstr);
2223 		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2224 		fprintf(stdout, "%s", pathstr);
2225 		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2226 	} else {
2227 		if (quiet == 0) {
2228 			fprintf(stdout, "%s", pathstr);
2229 			fprintf(stdout, "device openings: ");
2230 		}
2231 		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2232 			ccb->cgds.dev_active);
2233 	}
2234 
2235 tagcontrol_bailout:
2236 
2237 	cam_freeccb(ccb);
2238 	return(retval);
2239 }
2240 
2241 static void
2242 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2243 {
2244 	char pathstr[1024];
2245 
2246 	cam_path_string(device, pathstr, sizeof(pathstr));
2247 
2248 	if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
2249 
2250 		fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2251 			cts->sync_period);
2252 
2253 		if (cts->sync_offset != 0) {
2254 			u_int freq;
2255 
2256 			freq = scsi_calc_syncsrate(cts->sync_period);
2257 			fprintf(stdout, "%sfrequency: %d.%03dMHz\n", pathstr,
2258 				freq / 1000, freq % 1000);
2259 		}
2260 	}
2261 
2262 	if (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)
2263 		fprintf(stdout, "%soffset: %d\n", pathstr, cts->sync_offset);
2264 
2265 	if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID)
2266 		fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2267 			(0x01 << cts->bus_width) * 8);
2268 
2269 	if (cts->valid & CCB_TRANS_DISC_VALID)
2270 		fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2271 			(cts->flags & CCB_TRANS_DISC_ENB) ? "enabled" :
2272 			"disabled");
2273 
2274 	if (cts->valid & CCB_TRANS_TQ_VALID)
2275 		fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2276 			(cts->flags & CCB_TRANS_TAG_ENB) ? "enabled" :
2277 			"disabled");
2278 
2279 }
2280 
2281 /*
2282  * Get a path inquiry CCB for the specified device.
2283  */
2284 static int
2285 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2286 {
2287 	union ccb *ccb;
2288 	int retval = 0;
2289 
2290 	ccb = cam_getccb(device);
2291 
2292 	if (ccb == NULL) {
2293 		warnx("get_cpi: couldn't allocate CCB");
2294 		return(1);
2295 	}
2296 
2297 	bzero(&(&ccb->ccb_h)[1],
2298 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2299 
2300 	ccb->ccb_h.func_code = XPT_PATH_INQ;
2301 
2302 	if (cam_send_ccb(device, ccb) < 0) {
2303 		warn("get_cpi: error sending Path Inquiry CCB");
2304 
2305 		if (arglist & CAM_ARG_VERBOSE)
2306 			cam_error_print(device, ccb, CAM_ESF_ALL,
2307 					CAM_EPF_ALL, stderr);
2308 
2309 		retval = 1;
2310 
2311 		goto get_cpi_bailout;
2312 	}
2313 
2314 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2315 
2316 		if (arglist & CAM_ARG_VERBOSE)
2317 			cam_error_print(device, ccb, CAM_ESF_ALL,
2318 					CAM_EPF_ALL, stderr);
2319 
2320 		retval = 1;
2321 
2322 		goto get_cpi_bailout;
2323 	}
2324 
2325 	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2326 
2327 get_cpi_bailout:
2328 
2329 	cam_freeccb(ccb);
2330 
2331 	return(retval);
2332 }
2333 
2334 static void
2335 cpi_print(struct ccb_pathinq *cpi)
2336 {
2337 	char adapter_str[1024];
2338 	int i;
2339 
2340 	snprintf(adapter_str, sizeof(adapter_str),
2341 		 "%s%d:", cpi->dev_name, cpi->unit_number);
2342 
2343 	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2344 		cpi->version_num);
2345 
2346 	for (i = 1; i < 0xff; i = i << 1) {
2347 		const char *str;
2348 
2349 		if ((i & cpi->hba_inquiry) == 0)
2350 			continue;
2351 
2352 		fprintf(stdout, "%s supports ", adapter_str);
2353 
2354 		switch(i) {
2355 		case PI_MDP_ABLE:
2356 			str = "MDP message";
2357 			break;
2358 		case PI_WIDE_32:
2359 			str = "32 bit wide SCSI";
2360 			break;
2361 		case PI_WIDE_16:
2362 			str = "16 bit wide SCSI";
2363 			break;
2364 		case PI_SDTR_ABLE:
2365 			str = "SDTR message";
2366 			break;
2367 		case PI_LINKED_CDB:
2368 			str = "linked CDBs";
2369 			break;
2370 		case PI_TAG_ABLE:
2371 			str = "tag queue messages";
2372 			break;
2373 		case PI_SOFT_RST:
2374 			str = "soft reset alternative";
2375 			break;
2376 		default:
2377 			str = "unknown PI bit set";
2378 			break;
2379 		}
2380 		fprintf(stdout, "%s\n", str);
2381 	}
2382 
2383 	for (i = 1; i < 0xff; i = i << 1) {
2384 		const char *str;
2385 
2386 		if ((i & cpi->hba_misc) == 0)
2387 			continue;
2388 
2389 		fprintf(stdout, "%s ", adapter_str);
2390 
2391 		switch(i) {
2392 		case PIM_SCANHILO:
2393 			str = "bus scans from high ID to low ID";
2394 			break;
2395 		case PIM_NOREMOVE:
2396 			str = "removable devices not included in scan";
2397 			break;
2398 		case PIM_NOINITIATOR:
2399 			str = "initiator role not supported";
2400 			break;
2401 		case PIM_NOBUSRESET:
2402 			str = "user has disabled initial BUS RESET or"
2403 			      " controller is in target/mixed mode";
2404 			break;
2405 		default:
2406 			str = "unknown PIM bit set";
2407 			break;
2408 		}
2409 		fprintf(stdout, "%s\n", str);
2410 	}
2411 
2412 	for (i = 1; i < 0xff; i = i << 1) {
2413 		const char *str;
2414 
2415 		if ((i & cpi->target_sprt) == 0)
2416 			continue;
2417 
2418 		fprintf(stdout, "%s supports ", adapter_str);
2419 		switch(i) {
2420 		case PIT_PROCESSOR:
2421 			str = "target mode processor mode";
2422 			break;
2423 		case PIT_PHASE:
2424 			str = "target mode phase cog. mode";
2425 			break;
2426 		case PIT_DISCONNECT:
2427 			str = "disconnects in target mode";
2428 			break;
2429 		case PIT_TERM_IO:
2430 			str = "terminate I/O message in target mode";
2431 			break;
2432 		case PIT_GRP_6:
2433 			str = "group 6 commands in target mode";
2434 			break;
2435 		case PIT_GRP_7:
2436 			str = "group 7 commands in target mode";
2437 			break;
2438 		default:
2439 			str = "unknown PIT bit set";
2440 			break;
2441 		}
2442 
2443 		fprintf(stdout, "%s\n", str);
2444 	}
2445 	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
2446 		cpi->hba_eng_cnt);
2447 	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
2448 		cpi->max_target);
2449 	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
2450 		cpi->max_lun);
2451 	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
2452 		adapter_str, cpi->hpath_id);
2453 	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
2454 		cpi->initiator_id);
2455 	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
2456 	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
2457 	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
2458 	fprintf(stdout, "%s base transfer speed: ", adapter_str);
2459 	if (cpi->base_transfer_speed > 1000)
2460 		fprintf(stdout, "%d.%03dMB/sec\n",
2461 			cpi->base_transfer_speed / 1000,
2462 			cpi->base_transfer_speed % 1000);
2463 	else
2464 		fprintf(stdout, "%dKB/sec\n",
2465 			(cpi->base_transfer_speed % 1000) * 1000);
2466 }
2467 
2468 static int
2469 get_print_cts(struct cam_device *device, int user_settings, int quiet,
2470 	      struct ccb_trans_settings *cts)
2471 {
2472 	int retval;
2473 	union ccb *ccb;
2474 
2475 	retval = 0;
2476 	ccb = cam_getccb(device);
2477 
2478 	if (ccb == NULL) {
2479 		warnx("get_print_cts: error allocating ccb");
2480 		return(1);
2481 	}
2482 
2483 	bzero(&(&ccb->ccb_h)[1],
2484 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2485 
2486 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
2487 
2488 	if (user_settings == 0)
2489 		ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
2490 	else
2491 		ccb->cts.flags = CCB_TRANS_USER_SETTINGS;
2492 
2493 	if (cam_send_ccb(device, ccb) < 0) {
2494 		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
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 ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2503 		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
2504 		if (arglist & CAM_ARG_VERBOSE)
2505 			cam_error_print(device, ccb, CAM_ESF_ALL,
2506 					CAM_EPF_ALL, stderr);
2507 		retval = 1;
2508 		goto get_print_cts_bailout;
2509 	}
2510 
2511 	if (quiet == 0)
2512 		cts_print(device, &ccb->cts);
2513 
2514 	if (cts != NULL)
2515 		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
2516 
2517 get_print_cts_bailout:
2518 
2519 	cam_freeccb(ccb);
2520 
2521 	return(retval);
2522 }
2523 
2524 static int
2525 ratecontrol(struct cam_device *device, int retry_count, int timeout,
2526 	    int argc, char **argv, char *combinedopt)
2527 {
2528 	int c;
2529 	union ccb *ccb;
2530 	int user_settings = 0;
2531 	int retval = 0;
2532 	int disc_enable = -1, tag_enable = -1;
2533 	int offset = -1;
2534 	double syncrate = -1;
2535 	int bus_width = -1;
2536 	int quiet = 0;
2537 	int change_settings = 0, send_tur = 0;
2538 	struct ccb_pathinq cpi;
2539 
2540 	ccb = cam_getccb(device);
2541 
2542 	if (ccb == NULL) {
2543 		warnx("ratecontrol: error allocating ccb");
2544 		return(1);
2545 	}
2546 
2547 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2548 		switch(c){
2549 		case 'a':
2550 			send_tur = 1;
2551 			break;
2552 		case 'c':
2553 			user_settings = 0;
2554 			break;
2555 		case 'D':
2556 			if (strncasecmp(optarg, "enable", 6) == 0)
2557 				disc_enable = 1;
2558 			else if (strncasecmp(optarg, "disable", 7) == 0)
2559 				disc_enable = 0;
2560 			else {
2561 				warnx("-D argument \"%s\" is unknown", optarg);
2562 				retval = 1;
2563 				goto ratecontrol_bailout;
2564 			}
2565 			change_settings = 1;
2566 			break;
2567 		case 'O':
2568 			offset = strtol(optarg, NULL, 0);
2569 			if (offset < 0) {
2570 				warnx("offset value %d is < 0", offset);
2571 				retval = 1;
2572 				goto ratecontrol_bailout;
2573 			}
2574 			change_settings = 1;
2575 			break;
2576 		case 'q':
2577 			quiet++;
2578 			break;
2579 		case 'R':
2580 			syncrate = atof(optarg);
2581 
2582 			if (syncrate < 0) {
2583 				warnx("sync rate %f is < 0", syncrate);
2584 				retval = 1;
2585 				goto ratecontrol_bailout;
2586 			}
2587 			change_settings = 1;
2588 			break;
2589 		case 'T':
2590 			if (strncasecmp(optarg, "enable", 6) == 0)
2591 				tag_enable = 1;
2592 			else if (strncasecmp(optarg, "disable", 7) == 0)
2593 				tag_enable = 0;
2594 			else {
2595 				warnx("-T argument \"%s\" is unknown", optarg);
2596 				retval = 1;
2597 				goto ratecontrol_bailout;
2598 			}
2599 			change_settings = 1;
2600 			break;
2601 		case 'U':
2602 			user_settings = 1;
2603 			break;
2604 		case 'W':
2605 			bus_width = strtol(optarg, NULL, 0);
2606 			if (bus_width < 0) {
2607 				warnx("bus width %d is < 0", bus_width);
2608 				retval = 1;
2609 				goto ratecontrol_bailout;
2610 			}
2611 			change_settings = 1;
2612 			break;
2613 		default:
2614 			break;
2615 		}
2616 	}
2617 
2618 	bzero(&(&ccb->ccb_h)[1],
2619 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2620 
2621 	/*
2622 	 * Grab path inquiry information, so we can determine whether
2623 	 * or not the initiator is capable of the things that the user
2624 	 * requests.
2625 	 */
2626 	ccb->ccb_h.func_code = XPT_PATH_INQ;
2627 
2628 	if (cam_send_ccb(device, ccb) < 0) {
2629 		perror("error sending XPT_PATH_INQ CCB");
2630 		if (arglist & CAM_ARG_VERBOSE) {
2631 			cam_error_print(device, ccb, CAM_ESF_ALL,
2632 					CAM_EPF_ALL, stderr);
2633 		}
2634 		retval = 1;
2635 		goto ratecontrol_bailout;
2636 	}
2637 
2638 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2639 		warnx("XPT_PATH_INQ CCB failed");
2640 		if (arglist & CAM_ARG_VERBOSE) {
2641 			cam_error_print(device, ccb, CAM_ESF_ALL,
2642 					CAM_EPF_ALL, stderr);
2643 		}
2644 		retval = 1;
2645 		goto ratecontrol_bailout;
2646 	}
2647 
2648 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
2649 
2650 	bzero(&(&ccb->ccb_h)[1],
2651 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2652 
2653 	if (quiet == 0)
2654 		fprintf(stdout, "Current Parameters:\n");
2655 
2656 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
2657 
2658 	if (retval != 0)
2659 		goto ratecontrol_bailout;
2660 
2661 	if (arglist & CAM_ARG_VERBOSE)
2662 		cpi_print(&cpi);
2663 
2664 	if (change_settings) {
2665 		if (disc_enable != -1) {
2666 			ccb->cts.valid |= CCB_TRANS_DISC_VALID;
2667 			if (disc_enable == 0)
2668 				ccb->cts.flags &= ~CCB_TRANS_DISC_ENB;
2669 			else
2670 				ccb->cts.flags |= CCB_TRANS_DISC_ENB;
2671 		} else
2672 			ccb->cts.valid &= ~CCB_TRANS_DISC_VALID;
2673 
2674 		if (tag_enable != -1) {
2675 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
2676 				warnx("HBA does not support tagged queueing, "
2677 				      "so you cannot modify tag settings");
2678 				retval = 1;
2679 				goto ratecontrol_bailout;
2680 			}
2681 
2682 			ccb->cts.valid |= CCB_TRANS_TQ_VALID;
2683 
2684 			if (tag_enable == 0)
2685 				ccb->cts.flags &= ~CCB_TRANS_TAG_ENB;
2686 			else
2687 				ccb->cts.flags |= CCB_TRANS_TAG_ENB;
2688 		} else
2689 			ccb->cts.valid &= ~CCB_TRANS_TQ_VALID;
2690 
2691 		if (offset != -1) {
2692 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2693 				warnx("HBA at %s%d is not cable of changing "
2694 				      "offset", cpi.dev_name,
2695 				      cpi.unit_number);
2696 				retval = 1;
2697 				goto ratecontrol_bailout;
2698 			}
2699 			ccb->cts.valid |= CCB_TRANS_SYNC_OFFSET_VALID;
2700 			ccb->cts.sync_offset = offset;
2701 		} else
2702 			ccb->cts.valid &= ~CCB_TRANS_SYNC_OFFSET_VALID;
2703 
2704 		if (syncrate != -1) {
2705 			int prelim_sync_period;
2706 			u_int freq;
2707 
2708 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2709 				warnx("HBA at %s%d is not cable of changing "
2710 				      "transfer rates", cpi.dev_name,
2711 				      cpi.unit_number);
2712 				retval = 1;
2713 				goto ratecontrol_bailout;
2714 			}
2715 
2716 			ccb->cts.valid |= CCB_TRANS_SYNC_RATE_VALID;
2717 
2718 			/*
2719 			 * The sync rate the user gives us is in MHz.
2720 			 * We need to translate it into KHz for this
2721 			 * calculation.
2722 			 */
2723 			syncrate *= 1000;
2724 
2725 			/*
2726 			 * Next, we calculate a "preliminary" sync period
2727 			 * in tenths of a nanosecond.
2728 			 */
2729 			if (syncrate == 0)
2730 				prelim_sync_period = 0;
2731 			else
2732 				prelim_sync_period = 10000000 / syncrate;
2733 
2734 			ccb->cts.sync_period =
2735 				scsi_calc_syncparam(prelim_sync_period);
2736 
2737 			freq = scsi_calc_syncsrate(ccb->cts.sync_period);
2738 		} else
2739 			ccb->cts.valid &= ~CCB_TRANS_SYNC_RATE_VALID;
2740 
2741 		/*
2742 		 * The bus_width argument goes like this:
2743 		 * 0 == 8 bit
2744 		 * 1 == 16 bit
2745 		 * 2 == 32 bit
2746 		 * Therefore, if you shift the number of bits given on the
2747 		 * command line right by 4, you should get the correct
2748 		 * number.
2749 		 */
2750 		if (bus_width != -1) {
2751 
2752 			/*
2753 			 * We might as well validate things here with a
2754 			 * decipherable error message, rather than what
2755 			 * will probably be an indecipherable error message
2756 			 * by the time it gets back to us.
2757 			 */
2758 			if ((bus_width == 16)
2759 			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
2760 				warnx("HBA does not support 16 bit bus width");
2761 				retval = 1;
2762 				goto ratecontrol_bailout;
2763 			} else if ((bus_width == 32)
2764 				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
2765 				warnx("HBA does not support 32 bit bus width");
2766 				retval = 1;
2767 				goto ratecontrol_bailout;
2768 			} else if ((bus_width != 8)
2769 				&& (bus_width != 16)
2770 				&& (bus_width != 32)) {
2771 				warnx("Invalid bus width %d", bus_width);
2772 				retval = 1;
2773 				goto ratecontrol_bailout;
2774 			}
2775 
2776 			ccb->cts.valid |= CCB_TRANS_BUS_WIDTH_VALID;
2777 			ccb->cts.bus_width = bus_width >> 4;
2778 		} else
2779 			ccb->cts.valid &= ~CCB_TRANS_BUS_WIDTH_VALID;
2780 
2781 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
2782 
2783 		if (cam_send_ccb(device, ccb) < 0) {
2784 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
2785 			if (arglist & CAM_ARG_VERBOSE) {
2786 				cam_error_print(device, ccb, CAM_ESF_ALL,
2787 						CAM_EPF_ALL, stderr);
2788 			}
2789 			retval = 1;
2790 			goto ratecontrol_bailout;
2791 		}
2792 
2793 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2794 			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
2795 			if (arglist & CAM_ARG_VERBOSE) {
2796 				cam_error_print(device, ccb, CAM_ESF_ALL,
2797 						CAM_EPF_ALL, stderr);
2798 			}
2799 			retval = 1;
2800 			goto ratecontrol_bailout;
2801 		}
2802 	}
2803 
2804 	if (send_tur) {
2805 		retval = testunitready(device, retry_count, timeout,
2806 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
2807 
2808 		/*
2809 		 * If the TUR didn't succeed, just bail.
2810 		 */
2811 		if (retval != 0) {
2812 			if (quiet == 0)
2813 				fprintf(stderr, "Test Unit Ready failed\n");
2814 			goto ratecontrol_bailout;
2815 		}
2816 
2817 		/*
2818 		 * If the user wants things quiet, there's no sense in
2819 		 * getting the transfer settings, if we're not going
2820 		 * to print them.
2821 		 */
2822 		if (quiet != 0)
2823 			goto ratecontrol_bailout;
2824 
2825 		fprintf(stdout, "New Parameters:\n");
2826 		retval = get_print_cts(device, user_settings, 0, NULL);
2827 	}
2828 
2829 ratecontrol_bailout:
2830 
2831 	cam_freeccb(ccb);
2832 	return(retval);
2833 }
2834 
2835 static int
2836 scsiformat(struct cam_device *device, int argc, char **argv,
2837 	   char *combinedopt, int retry_count, int timeout)
2838 {
2839 	union ccb *ccb;
2840 	int c;
2841 	int ycount = 0, quiet = 0;
2842 	int error = 0, response = 0, retval = 0;
2843 	int use_timeout = 10800 * 1000;
2844 	int immediate = 1;
2845 	struct format_defect_list_header fh;
2846 	u_int8_t *data_ptr = NULL;
2847 	u_int32_t dxfer_len = 0;
2848 	u_int8_t byte2 = 0;
2849 	int num_warnings = 0;
2850 
2851 	ccb = cam_getccb(device);
2852 
2853 	if (ccb == NULL) {
2854 		warnx("scsiformat: error allocating ccb");
2855 		return(1);
2856 	}
2857 
2858 	bzero(&(&ccb->ccb_h)[1],
2859 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2860 
2861 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2862 		switch(c) {
2863 		case 'q':
2864 			quiet++;
2865 			break;
2866 		case 'w':
2867 			immediate = 0;
2868 			break;
2869 		case 'y':
2870 			ycount++;
2871 			break;
2872 		}
2873 	}
2874 
2875 	if (quiet == 0) {
2876 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
2877 			"following device:\n");
2878 
2879 		error = scsidoinquiry(device, argc, argv, combinedopt,
2880 				      retry_count, timeout);
2881 
2882 		if (error != 0) {
2883 			warnx("scsiformat: error sending inquiry");
2884 			goto scsiformat_bailout;
2885 		}
2886 	}
2887 
2888 	if (ycount == 0) {
2889 
2890 		do {
2891 			char str[1024];
2892 
2893 			fprintf(stdout, "Are you SURE you want to do "
2894 				"this? (yes/no) ");
2895 
2896 			if (fgets(str, sizeof(str), stdin) != NULL) {
2897 
2898 				if (strncasecmp(str, "yes", 3) == 0)
2899 					response = 1;
2900 				else if (strncasecmp(str, "no", 2) == 0)
2901 					response = -1;
2902 				else {
2903 					fprintf(stdout, "Please answer"
2904 						" \"yes\" or \"no\"\n");
2905 				}
2906 			}
2907 		} while (response == 0);
2908 
2909 		if (response == -1) {
2910 			error = 1;
2911 			goto scsiformat_bailout;
2912 		}
2913 	}
2914 
2915 	if (timeout != 0)
2916 		use_timeout = timeout;
2917 
2918 	if (quiet == 0) {
2919 		fprintf(stdout, "Current format timeout is %d seconds\n",
2920 			use_timeout / 1000);
2921 	}
2922 
2923 	/*
2924 	 * If the user hasn't disabled questions and didn't specify a
2925 	 * timeout on the command line, ask them if they want the current
2926 	 * timeout.
2927 	 */
2928 	if ((ycount == 0)
2929 	 && (timeout == 0)) {
2930 		char str[1024];
2931 		int new_timeout = 0;
2932 
2933 		fprintf(stdout, "Enter new timeout in seconds or press\n"
2934 			"return to keep the current timeout [%d] ",
2935 			use_timeout / 1000);
2936 
2937 		if (fgets(str, sizeof(str), stdin) != NULL) {
2938 			if (str[0] != '\0')
2939 				new_timeout = atoi(str);
2940 		}
2941 
2942 		if (new_timeout != 0) {
2943 			use_timeout = new_timeout * 1000;
2944 			fprintf(stdout, "Using new timeout value %d\n",
2945 				use_timeout / 1000);
2946 		}
2947 	}
2948 
2949 	/*
2950 	 * Keep this outside the if block below to silence any unused
2951 	 * variable warnings.
2952 	 */
2953 	bzero(&fh, sizeof(fh));
2954 
2955 	/*
2956 	 * If we're in immediate mode, we've got to include the format
2957 	 * header
2958 	 */
2959 	if (immediate != 0) {
2960 		fh.byte2 = FU_DLH_IMMED;
2961 		data_ptr = (u_int8_t *)&fh;
2962 		dxfer_len = sizeof(fh);
2963 		byte2 = FU_FMT_DATA;
2964 	} else if (quiet == 0) {
2965 		fprintf(stdout, "Formatting...");
2966 		fflush(stdout);
2967 	}
2968 
2969 	scsi_format_unit(&ccb->csio,
2970 			 /* retries */ retry_count,
2971 			 /* cbfcnp */ NULL,
2972 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
2973 			 /* byte2 */ byte2,
2974 			 /* ileave */ 0,
2975 			 /* data_ptr */ data_ptr,
2976 			 /* dxfer_len */ dxfer_len,
2977 			 /* sense_len */ SSD_FULL_SIZE,
2978 			 /* timeout */ use_timeout);
2979 
2980 	/* Disable freezing the device queue */
2981 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2982 
2983 	if (arglist & CAM_ARG_ERR_RECOVER)
2984 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2985 
2986 	if (((retval = cam_send_ccb(device, ccb)) < 0)
2987 	 || ((immediate == 0)
2988 	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
2989 		const char errstr[] = "error sending format command";
2990 
2991 		if (retval < 0)
2992 			warn(errstr);
2993 		else
2994 			warnx(errstr);
2995 
2996 		if (arglist & CAM_ARG_VERBOSE) {
2997 			cam_error_print(device, ccb, CAM_ESF_ALL,
2998 					CAM_EPF_ALL, stderr);
2999 		}
3000 		error = 1;
3001 		goto scsiformat_bailout;
3002 	}
3003 
3004 	/*
3005 	 * If we ran in non-immediate mode, we already checked for errors
3006 	 * above and printed out any necessary information.  If we're in
3007 	 * immediate mode, we need to loop through and get status
3008 	 * information periodically.
3009 	 */
3010 	if (immediate == 0) {
3011 		if (quiet == 0) {
3012 			fprintf(stdout, "Format Complete\n");
3013 		}
3014 		goto scsiformat_bailout;
3015 	}
3016 
3017 	do {
3018 		cam_status status;
3019 
3020 		bzero(&(&ccb->ccb_h)[1],
3021 		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3022 
3023 		/*
3024 		 * There's really no need to do error recovery or
3025 		 * retries here, since we're just going to sit in a
3026 		 * loop and wait for the device to finish formatting.
3027 		 */
3028 		scsi_test_unit_ready(&ccb->csio,
3029 				     /* retries */ 0,
3030 				     /* cbfcnp */ NULL,
3031 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
3032 				     /* sense_len */ SSD_FULL_SIZE,
3033 				     /* timeout */ 5000);
3034 
3035 		/* Disable freezing the device queue */
3036 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3037 
3038 		retval = cam_send_ccb(device, ccb);
3039 
3040 		/*
3041 		 * If we get an error from the ioctl, bail out.  SCSI
3042 		 * errors are expected.
3043 		 */
3044 		if (retval < 0) {
3045 			warn("error sending CAMIOCOMMAND ioctl");
3046 			if (arglist & CAM_ARG_VERBOSE) {
3047 				cam_error_print(device, ccb, CAM_ESF_ALL,
3048 						CAM_EPF_ALL, stderr);
3049 			}
3050 			error = 1;
3051 			goto scsiformat_bailout;
3052 		}
3053 
3054 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
3055 
3056 		if ((status != CAM_REQ_CMP)
3057 		 && (status == CAM_SCSI_STATUS_ERROR)
3058 		 && ((status & CAM_AUTOSNS_VALID) != 0)) {
3059 			struct scsi_sense_data *sense;
3060 			int error_code, sense_key, asc, ascq;
3061 
3062 			sense = &ccb->csio.sense_data;
3063 			scsi_extract_sense(sense, &error_code, &sense_key,
3064 					   &asc, &ascq);
3065 
3066 			/*
3067 			 * According to the SCSI-2 and SCSI-3 specs, a
3068 			 * drive that is in the middle of a format should
3069 			 * return NOT READY with an ASC of "logical unit
3070 			 * not ready, format in progress".  The sense key
3071 			 * specific bytes will then be a progress indicator.
3072 			 */
3073 			if ((sense_key == SSD_KEY_NOT_READY)
3074 			 && (asc == 0x04) && (ascq == 0x04)) {
3075 				if ((sense->extra_len >= 10)
3076 				 && ((sense->sense_key_spec[0] &
3077 				      SSD_SCS_VALID) != 0)
3078 				 && (quiet == 0)) {
3079 					int val;
3080 					u_int64_t percentage;
3081 
3082 					val = scsi_2btoul(
3083 						&sense->sense_key_spec[1]);
3084 					percentage = 10000 * val;
3085 
3086 					fprintf(stdout,
3087 						"\rFormatting:  %qd.%02qd %% "
3088 						"(%d/%d) done",
3089 						percentage / (0x10000 * 100),
3090 						(percentage / 0x10000) % 100,
3091 						val, 0x10000);
3092 					fflush(stdout);
3093 				} else if ((quiet == 0)
3094 					&& (++num_warnings <= 1)) {
3095 					warnx("Unexpected SCSI Sense Key "
3096 					      "Specific value returned "
3097 					      "during format:");
3098 					scsi_sense_print(device, &ccb->csio,
3099 							 stderr);
3100 					warnx("Unable to print status "
3101 					      "information, but format will "
3102 					      "proceed.");
3103 					warnx("will exit when format is "
3104 					      "complete");
3105 				}
3106 				sleep(1);
3107 			} else {
3108 				warnx("Unexpected SCSI error during format");
3109 				cam_error_print(device, ccb, CAM_ESF_ALL,
3110 						CAM_EPF_ALL, stderr);
3111 				error = 1;
3112 				goto scsiformat_bailout;
3113 			}
3114 
3115 		} else if (status != CAM_REQ_CMP) {
3116 			warnx("Unexpected CAM status %#x", status);
3117 			if (arglist & CAM_ARG_VERBOSE)
3118 				cam_error_print(device, ccb, CAM_ESF_ALL,
3119 						CAM_EPF_ALL, stderr);
3120 			error = 1;
3121 			goto scsiformat_bailout;
3122 		}
3123 
3124 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3125 
3126 	if (quiet == 0)
3127 		fprintf(stdout, "\nFormat Complete\n");
3128 
3129 scsiformat_bailout:
3130 
3131 	cam_freeccb(ccb);
3132 
3133 	return(error);
3134 }
3135 #endif /* MINIMALISTIC */
3136 
3137 void
3138 usage(int verbose)
3139 {
3140 	fprintf(verbose ? stdout : stderr,
3141 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
3142 "        camcontrol devlist    [-v]\n"
3143 #ifndef MINIMALISTIC
3144 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
3145 "        camcontrol tur        [dev_id][generic args]\n"
3146 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
3147 "        camcontrol start      [dev_id][generic args]\n"
3148 "        camcontrol stop       [dev_id][generic args]\n"
3149 "        camcontrol load       [dev_id][generic args]\n"
3150 "        camcontrol eject      [dev_id][generic args]\n"
3151 #endif /* MINIMALISTIC */
3152 "        camcontrol rescan     <all | bus[:target:lun]>\n"
3153 "        camcontrol reset      <all | bus[:target:lun]>\n"
3154 #ifndef MINIMALISTIC
3155 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
3156 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
3157 "                              [-P pagectl][-e | -b][-d]\n"
3158 "        camcontrol cmd        [dev_id][generic args] <-c cmd [args]>\n"
3159 "                              [-i len fmt|-o len fmt [args]]\n"
3160 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
3161 "                              <all|bus[:target[:lun]]|off>\n"
3162 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
3163 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
3164 "                              [-D <enable|disable>][-O offset][-q]\n"
3165 "                              [-R syncrate][-v][-T <enable|disable>]\n"
3166 "                              [-U][-W bus_width]\n"
3167 "        camcontrol format     [dev_id][generic args][-q][-w][-y]\n"
3168 #endif /* MINIMALISTIC */
3169 "        camcontrol help\n");
3170 	if (!verbose)
3171 		return;
3172 #ifndef MINIMALISTIC
3173 	fprintf(stdout,
3174 "Specify one of the following options:\n"
3175 "devlist     list all CAM devices\n"
3176 "periphlist  list all CAM peripheral drivers attached to a device\n"
3177 "tur         send a test unit ready to the named device\n"
3178 "inquiry     send a SCSI inquiry command to the named device\n"
3179 "start       send a Start Unit command to the device\n"
3180 "stop        send a Stop Unit command to the device\n"
3181 "load        send a Start Unit command to the device with the load bit set\n"
3182 "eject       send a Stop Unit command to the device with the eject bit set\n"
3183 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
3184 "reset       reset all busses, the given bus, or bus:target:lun\n"
3185 "defects     read the defect list of the specified device\n"
3186 "modepage    display or edit (-e) the given mode page\n"
3187 "cmd         send the given scsi command, may need -i or -o as well\n"
3188 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
3189 "tags        report or set the number of transaction slots for a device\n"
3190 "negotiate   report or set device negotiation parameters\n"
3191 "format      send the SCSI FORMAT UNIT command to the named device\n"
3192 "help        this message\n"
3193 "Device Identifiers:\n"
3194 "bus:target        specify the bus and target, lun defaults to 0\n"
3195 "bus:target:lun    specify the bus, target and lun\n"
3196 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
3197 "Generic arguments:\n"
3198 "-v                be verbose, print out sense information\n"
3199 "-t timeout        command timeout in seconds, overrides default timeout\n"
3200 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
3201 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
3202 "-E                have the kernel attempt to perform SCSI error recovery\n"
3203 "-C count          specify the SCSI command retry count (needs -E to work)\n"
3204 "modepage arguments:\n"
3205 "-l                list all available mode pages\n"
3206 "-m page           specify the mode page to view or edit\n"
3207 "-e                edit the specified mode page\n"
3208 "-b                force view to binary mode\n"
3209 "-d                disable block descriptors for mode sense\n"
3210 "-P pgctl          page control field 0-3\n"
3211 "defects arguments:\n"
3212 "-f format         specify defect list format (block, bfi or phys)\n"
3213 "-G                get the grown defect list\n"
3214 "-P                get the permanant defect list\n"
3215 "inquiry arguments:\n"
3216 "-D                get the standard inquiry data\n"
3217 "-S                get the serial number\n"
3218 "-R                get the transfer rate, etc.\n"
3219 "cmd arguments:\n"
3220 "-c cdb [args]     specify the SCSI CDB\n"
3221 "-i len fmt        specify input data and input data format\n"
3222 "-o len fmt [args] specify output data and output data fmt\n"
3223 "debug arguments:\n"
3224 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
3225 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
3226 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
3227 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
3228 "tags arguments:\n"
3229 "-N tags           specify the number of tags to use for this device\n"
3230 "-q                be quiet, don't report the number of tags\n"
3231 "-v                report a number of tag-related parameters\n"
3232 "negotiate arguments:\n"
3233 "-a                send a test unit ready after negotiation\n"
3234 "-c                report/set current negotiation settings\n"
3235 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
3236 "-O offset         set command delay offset\n"
3237 "-q                be quiet, don't report anything\n"
3238 "-R syncrate       synchronization rate in MHz\n"
3239 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
3240 "-U                report/set user negotiation settings\n"
3241 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
3242 "-v                also print a Path Inquiry CCB for the controller\n"
3243 "format arguments:\n"
3244 "-q                be quiet, don't print status messages\n"
3245 "-w                don't send immediate format command\n"
3246 "-y                don't ask any questions\n");
3247 #endif /* MINIMALISTIC */
3248 }
3249 
3250 int
3251 main(int argc, char **argv)
3252 {
3253 	int c;
3254 	char *device = NULL;
3255 	int unit = 0;
3256 	struct cam_device *cam_dev = NULL;
3257 	int timeout = 0, retry_count = 1;
3258 	camcontrol_optret optreturn;
3259 	char *tstr;
3260 	const char *mainopt = "C:En:t:u:v";
3261 	const char *subopt = NULL;
3262 	char combinedopt[256];
3263 	int error = 0, optstart = 2;
3264 	int devopen = 1;
3265 
3266 	cmdlist = CAM_CMD_NONE;
3267 	arglist = CAM_ARG_NONE;
3268 
3269 	if (argc < 2) {
3270 		usage(0);
3271 		exit(1);
3272 	}
3273 
3274 	/*
3275 	 * Get the base option.
3276 	 */
3277 	optreturn = getoption(argv[1], &cmdlist, &arglist, &subopt);
3278 
3279 	if (optreturn == CC_OR_AMBIGUOUS) {
3280 		warnx("ambiguous option %s", argv[1]);
3281 		usage(0);
3282 		exit(1);
3283 	} else if (optreturn == CC_OR_NOT_FOUND) {
3284 		warnx("option %s not found", argv[1]);
3285 		usage(0);
3286 		exit(1);
3287 	}
3288 
3289 	/*
3290 	 * Ahh, getopt(3) is a pain.
3291 	 *
3292 	 * This is a gross hack.  There really aren't many other good
3293 	 * options (excuse the pun) for parsing options in a situation like
3294 	 * this.  getopt is kinda braindead, so you end up having to run
3295 	 * through the options twice, and give each invocation of getopt
3296 	 * the option string for the other invocation.
3297 	 *
3298 	 * You would think that you could just have two groups of options.
3299 	 * The first group would get parsed by the first invocation of
3300 	 * getopt, and the second group would get parsed by the second
3301 	 * invocation of getopt.  It doesn't quite work out that way.  When
3302 	 * the first invocation of getopt finishes, it leaves optind pointing
3303 	 * to the argument _after_ the first argument in the second group.
3304 	 * So when the second invocation of getopt comes around, it doesn't
3305 	 * recognize the first argument it gets and then bails out.
3306 	 *
3307 	 * A nice alternative would be to have a flag for getopt that says
3308 	 * "just keep parsing arguments even when you encounter an unknown
3309 	 * argument", but there isn't one.  So there's no real clean way to
3310 	 * easily parse two sets of arguments without having one invocation
3311 	 * of getopt know about the other.
3312 	 *
3313 	 * Without this hack, the first invocation of getopt would work as
3314 	 * long as the generic arguments are first, but the second invocation
3315 	 * (in the subfunction) would fail in one of two ways.  In the case
3316 	 * where you don't set optreset, it would fail because optind may be
3317 	 * pointing to the argument after the one it should be pointing at.
3318 	 * In the case where you do set optreset, and reset optind, it would
3319 	 * fail because getopt would run into the first set of options, which
3320 	 * it doesn't understand.
3321 	 *
3322 	 * All of this would "sort of" work if you could somehow figure out
3323 	 * whether optind had been incremented one option too far.  The
3324 	 * mechanics of that, however, are more daunting than just giving
3325 	 * both invocations all of the expect options for either invocation.
3326 	 *
3327 	 * Needless to say, I wouldn't mind if someone invented a better
3328 	 * (non-GPL!) command line parsing interface than getopt.  I
3329 	 * wouldn't mind if someone added more knobs to getopt to make it
3330 	 * work better.  Who knows, I may talk myself into doing it someday,
3331 	 * if the standards weenies let me.  As it is, it just leads to
3332 	 * hackery like this and causes people to avoid it in some cases.
3333 	 *
3334 	 * KDM, September 8th, 1998
3335 	 */
3336 	if (subopt != NULL)
3337 		sprintf(combinedopt, "%s%s", mainopt, subopt);
3338 	else
3339 		sprintf(combinedopt, "%s", mainopt);
3340 
3341 	/*
3342 	 * For these options we do not parse optional device arguments and
3343 	 * we do not open a passthrough device.
3344 	 */
3345 	if ((cmdlist == CAM_CMD_RESCAN)
3346 	 || (cmdlist == CAM_CMD_RESET)
3347 	 || (cmdlist == CAM_CMD_DEVTREE)
3348 	 || (cmdlist == CAM_CMD_USAGE)
3349 	 || (cmdlist == CAM_CMD_DEBUG))
3350 		devopen = 0;
3351 
3352 #ifndef MINIMALISTIC
3353 	if ((devopen == 1)
3354 	 && (argc > 2 && argv[2][0] != '-')) {
3355 		char name[30];
3356 		int rv;
3357 
3358 		/*
3359 		 * First catch people who try to do things like:
3360 		 * camcontrol tur /dev/da0
3361 		 * camcontrol doesn't take device nodes as arguments.
3362 		 */
3363 		if (argv[2][0] == '/') {
3364 			warnx("%s is not a valid device identifier", argv[2]);
3365 			errx(1, "please read the camcontrol(8) man page");
3366 		} else if (isdigit(argv[2][0])) {
3367 			/* device specified as bus:target[:lun] */
3368 			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
3369 			if (rv < 2)
3370 				errx(1, "numeric device specification must "
3371 				     "be either bus:target, or "
3372 				     "bus:target:lun");
3373 			optstart++;
3374 		} else {
3375 			if (cam_get_device(argv[2], name, sizeof name, &unit)
3376 			    == -1)
3377 				errx(1, "%s", cam_errbuf);
3378 			device = strdup(name);
3379 			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
3380 			optstart++;
3381 		}
3382 	}
3383 #endif /* MINIMALISTIC */
3384 	/*
3385 	 * Start getopt processing at argv[2/3], since we've already
3386 	 * accepted argv[1..2] as the command name, and as a possible
3387 	 * device name.
3388 	 */
3389 	optind = optstart;
3390 
3391 	/*
3392 	 * Now we run through the argument list looking for generic
3393 	 * options, and ignoring options that possibly belong to
3394 	 * subfunctions.
3395 	 */
3396 	while ((c = getopt(argc, argv, combinedopt))!= -1){
3397 		switch(c) {
3398 			case 'C':
3399 				retry_count = strtol(optarg, NULL, 0);
3400 				if (retry_count < 0)
3401 					errx(1, "retry count %d is < 0",
3402 					     retry_count);
3403 				arglist |= CAM_ARG_RETRIES;
3404 				break;
3405 			case 'E':
3406 				arglist |= CAM_ARG_ERR_RECOVER;
3407 				break;
3408 			case 'n':
3409 				arglist |= CAM_ARG_DEVICE;
3410 				tstr = optarg;
3411 				while (isspace(*tstr) && (*tstr != '\0'))
3412 					tstr++;
3413 				device = (char *)strdup(tstr);
3414 				break;
3415 			case 't':
3416 				timeout = strtol(optarg, NULL, 0);
3417 				if (timeout < 0)
3418 					errx(1, "invalid timeout %d", timeout);
3419 				/* Convert the timeout from seconds to ms */
3420 				timeout *= 1000;
3421 				arglist |= CAM_ARG_TIMEOUT;
3422 				break;
3423 			case 'u':
3424 				arglist |= CAM_ARG_UNIT;
3425 				unit = strtol(optarg, NULL, 0);
3426 				break;
3427 			case 'v':
3428 				arglist |= CAM_ARG_VERBOSE;
3429 				break;
3430 			default:
3431 				break;
3432 		}
3433 	}
3434 
3435 #ifndef MINIMALISTIC
3436 	/*
3437 	 * For most commands we'll want to open the passthrough device
3438 	 * associated with the specified device.  In the case of the rescan
3439 	 * commands, we don't use a passthrough device at all, just the
3440 	 * transport layer device.
3441 	 */
3442 	if (devopen == 1) {
3443 		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
3444 		 && (((arglist & CAM_ARG_DEVICE) == 0)
3445 		  || ((arglist & CAM_ARG_UNIT) == 0))) {
3446 			errx(1, "subcommand \"%s\" requires a valid device "
3447 			     "identifier", argv[1]);
3448 		}
3449 
3450 		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
3451 				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
3452 				cam_open_spec_device(device,unit,O_RDWR,NULL)))
3453 		     == NULL)
3454 			errx(1,"%s", cam_errbuf);
3455 	}
3456 #endif /* MINIMALISTIC */
3457 
3458 	/*
3459 	 * Reset optind to 2, and reset getopt, so these routines can parse
3460 	 * the arguments again.
3461 	 */
3462 	optind = optstart;
3463 	optreset = 1;
3464 
3465 	switch(cmdlist) {
3466 #ifndef MINIMALISTIC
3467 		case CAM_CMD_DEVLIST:
3468 			error = getdevlist(cam_dev);
3469 			break;
3470 #endif /* MINIMALISTIC */
3471 		case CAM_CMD_DEVTREE:
3472 			error = getdevtree();
3473 			break;
3474 #ifndef MINIMALISTIC
3475 		case CAM_CMD_TUR:
3476 			error = testunitready(cam_dev, retry_count, timeout, 0);
3477 			break;
3478 		case CAM_CMD_INQUIRY:
3479 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
3480 					      retry_count, timeout);
3481 			break;
3482 		case CAM_CMD_STARTSTOP:
3483 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
3484 					  arglist & CAM_ARG_EJECT, retry_count,
3485 					  timeout);
3486 			break;
3487 #endif /* MINIMALISTIC */
3488 		case CAM_CMD_RESCAN:
3489 			error = dorescan_or_reset(argc, argv, 1);
3490 			break;
3491 		case CAM_CMD_RESET:
3492 			error = dorescan_or_reset(argc, argv, 0);
3493 			break;
3494 #ifndef MINIMALISTIC
3495 		case CAM_CMD_READ_DEFECTS:
3496 			error = readdefects(cam_dev, argc, argv, combinedopt,
3497 					    retry_count, timeout);
3498 			break;
3499 		case CAM_CMD_MODE_PAGE:
3500 			modepage(cam_dev, argc, argv, combinedopt,
3501 				 retry_count, timeout);
3502 			break;
3503 		case CAM_CMD_SCSI_CMD:
3504 			error = scsicmd(cam_dev, argc, argv, combinedopt,
3505 					retry_count, timeout);
3506 			break;
3507 		case CAM_CMD_DEBUG:
3508 			error = camdebug(argc, argv, combinedopt);
3509 			break;
3510 		case CAM_CMD_TAG:
3511 			error = tagcontrol(cam_dev, argc, argv, combinedopt);
3512 			break;
3513 		case CAM_CMD_RATE:
3514 			error = ratecontrol(cam_dev, retry_count, timeout,
3515 					    argc, argv, combinedopt);
3516 			break;
3517 		case CAM_CMD_FORMAT:
3518 			error = scsiformat(cam_dev, argc, argv,
3519 					   combinedopt, retry_count, timeout);
3520 			break;
3521 #endif /* MINIMALISTIC */
3522 		case CAM_CMD_USAGE:
3523 			usage(1);
3524 			break;
3525 		default:
3526 			usage(0);
3527 			error = 1;
3528 			break;
3529 	}
3530 
3531 	if (cam_dev != NULL)
3532 		cam_close_device(cam_dev);
3533 
3534 	exit(error);
3535 }
3536