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