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