xref: /freebsd/sbin/camcontrol/camcontrol.c (revision 23f282aa31e9b6fceacd449020e936e98d6f2298)
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 #define DEFAULT_DEVICE "da"
52 #define DEFAULT_UNIT 	0
53 
54 typedef enum {
55 	CAM_ARG_NONE		= 0x00000000,
56 	CAM_ARG_DEVLIST		= 0x00000001,
57 	CAM_ARG_TUR		= 0x00000002,
58 	CAM_ARG_INQUIRY		= 0x00000003,
59 	CAM_ARG_STARTSTOP	= 0x00000004,
60 	CAM_ARG_RESCAN		= 0x00000005,
61 	CAM_ARG_READ_DEFECTS	= 0x00000006,
62 	CAM_ARG_MODE_PAGE	= 0x00000007,
63 	CAM_ARG_SCSI_CMD	= 0x00000008,
64 	CAM_ARG_DEVTREE		= 0x00000009,
65 	CAM_ARG_USAGE		= 0x0000000a,
66 	CAM_ARG_DEBUG		= 0x0000000b,
67 	CAM_ARG_RESET		= 0x0000000c,
68 	CAM_ARG_FORMAT		= 0x0000000d,
69 	CAM_ARG_TAG		= 0x0000000e,
70 	CAM_ARG_RATE		= 0x0000000f,
71 	CAM_ARG_OPT_MASK	= 0x0000000f,
72 	CAM_ARG_VERBOSE		= 0x00000010,
73 	CAM_ARG_DEVICE		= 0x00000020,
74 	CAM_ARG_BUS		= 0x00000040,
75 	CAM_ARG_TARGET		= 0x00000080,
76 	CAM_ARG_LUN		= 0x00000100,
77 	CAM_ARG_EJECT		= 0x00000200,
78 	CAM_ARG_UNIT		= 0x00000400,
79 	CAM_ARG_FORMAT_BLOCK	= 0x00000800,
80 	CAM_ARG_FORMAT_BFI	= 0x00001000,
81 	CAM_ARG_FORMAT_PHYS	= 0x00002000,
82 	CAM_ARG_PLIST		= 0x00004000,
83 	CAM_ARG_GLIST		= 0x00008000,
84 	CAM_ARG_GET_SERIAL	= 0x00010000,
85 	CAM_ARG_GET_STDINQ	= 0x00020000,
86 	CAM_ARG_GET_XFERRATE	= 0x00040000,
87 	CAM_ARG_INQ_MASK	= 0x00070000,
88 	CAM_ARG_MODE_EDIT	= 0x00080000,
89 	CAM_ARG_PAGE_CNTL	= 0x00100000,
90 	CAM_ARG_TIMEOUT		= 0x00200000,
91 	CAM_ARG_CMD_IN		= 0x00400000,
92 	CAM_ARG_CMD_OUT		= 0x00800000,
93 	CAM_ARG_DBD		= 0x01000000,
94 	CAM_ARG_ERR_RECOVER	= 0x02000000,
95 	CAM_ARG_RETRIES		= 0x04000000,
96 	CAM_ARG_START_UNIT	= 0x08000000,
97 	CAM_ARG_DEBUG_INFO	= 0x10000000,
98 	CAM_ARG_DEBUG_TRACE	= 0x20000000,
99 	CAM_ARG_DEBUG_SUBTRACE	= 0x40000000,
100 	CAM_ARG_DEBUG_CDB	= 0x80000000,
101 	CAM_ARG_FLAG_MASK	= 0xfffffff0
102 } cam_argmask;
103 
104 struct camcontrol_opts {
105 	char 		*optname;
106 	cam_argmask	argnum;
107 	const char	*subopt;
108 };
109 
110 extern int optreset;
111 
112 static const char scsicmd_opts[] = "c:i:o:";
113 static const char readdefect_opts[] = "f:GP";
114 static const char negotiate_opts[] = "acD:O:qR:T:UW:";
115 
116 struct camcontrol_opts option_table[] = {
117 	{"tur", CAM_ARG_TUR, NULL},
118 	{"inquiry", CAM_ARG_INQUIRY, "DSR"},
119 	{"start", CAM_ARG_STARTSTOP | CAM_ARG_START_UNIT, NULL},
120 	{"stop", CAM_ARG_STARTSTOP, NULL},
121 	{"eject", CAM_ARG_STARTSTOP | CAM_ARG_EJECT, NULL},
122 	{"rescan", CAM_ARG_RESCAN, NULL},
123 	{"reset", CAM_ARG_RESET, NULL},
124 	{"cmd", CAM_ARG_SCSI_CMD, scsicmd_opts},
125 	{"command", CAM_ARG_SCSI_CMD, scsicmd_opts},
126 	{"defects", CAM_ARG_READ_DEFECTS, readdefect_opts},
127 	{"defectlist", CAM_ARG_READ_DEFECTS, readdefect_opts},
128 	{"devlist", CAM_ARG_DEVTREE, NULL},
129 	{"periphlist", CAM_ARG_DEVLIST, NULL},
130 	{"modepage", CAM_ARG_MODE_PAGE, "dem:P:"},
131 	{"tags", CAM_ARG_TAG, "N:q"},
132 	{"negotiate", CAM_ARG_RATE, negotiate_opts},
133 	{"rate", CAM_ARG_RATE, negotiate_opts},
134 	{"debug", CAM_ARG_DEBUG, "ITSc"},
135 	{"help", CAM_ARG_USAGE, NULL},
136 	{"-?", CAM_ARG_USAGE, NULL},
137 	{"-h", CAM_ARG_USAGE, NULL},
138 	{NULL, 0, NULL}
139 };
140 
141 typedef enum {
142 	CC_OR_NOT_FOUND,
143 	CC_OR_AMBIGUOUS,
144 	CC_OR_FOUND
145 } camcontrol_optret;
146 
147 cam_argmask arglist;
148 int bus, target, lun;
149 
150 
151 camcontrol_optret getoption(char *arg, cam_argmask *argnum, char **subopt);
152 static int getdevlist(struct cam_device *device);
153 static int getdevtree(void);
154 static int testunitready(struct cam_device *device, int retry_count,
155 			 int timeout, int quiet);
156 static int scsistart(struct cam_device *device, int startstop, int loadeject,
157 		     int retry_count, int timeout);
158 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
159 			 char *combinedopt, int retry_count, int timeout);
160 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
161 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
162 static int scsixferrate(struct cam_device *device);
163 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
164 		     cam_argmask *arglist);
165 static int dorescan_or_reset(int argc, char **argv, int rescan);
166 static int rescan_or_reset_bus(int bus, int rescan);
167 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
168 static int readdefects(struct cam_device *device, int argc, char **argv,
169 		       char *combinedopt, int retry_count, int timeout);
170 static void modepage(struct cam_device *device, int argc, char **argv,
171 		     char *combinedopt, int retry_count, int timeout);
172 static int scsicmd(struct cam_device *device, int argc, char **argv,
173 		   char *combinedopt, int retry_count, int timeout);
174 static int tagcontrol(struct cam_device *device, int argc, char **argv,
175 		      char *combinedopt);
176 static void cts_print(struct cam_device *device,
177 		      struct ccb_trans_settings *cts);
178 static void cpi_print(struct ccb_pathinq *cpi);
179 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
180 static int get_print_cts(struct cam_device *device, int user_settings,
181 			 int quiet, struct ccb_trans_settings *cts);
182 static int ratecontrol(struct cam_device *device, int retry_count,
183 		       int timeout, int argc, char **argv, char *combinedopt);
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 % 1000) * 1000);
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 (device->inq_data.flags & SID_CmdQue)
936                 fprintf(stdout, ", Tagged Queueing Enabled");
937 
938         fprintf(stdout, "\n");
939 
940 xferrate_bailout:
941 
942 	cam_freeccb(ccb);
943 
944 	return(retval);
945 }
946 
947 /*
948  * Parse out a bus, or a bus, target and lun in the following
949  * format:
950  * bus
951  * bus:target
952  * bus:target:lun
953  *
954  * Returns the number of parsed components, or 0.
955  */
956 static int
957 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglist)
958 {
959 	char *tmpstr;
960 	int convs = 0;
961 
962 	while (isspace(*tstr) && (*tstr != '\0'))
963 		tstr++;
964 
965 	tmpstr = (char *)strtok(tstr, ":");
966 	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
967 		*bus = strtol(tmpstr, NULL, 0);
968 		*arglist |= CAM_ARG_BUS;
969 		convs++;
970 		tmpstr = (char *)strtok(NULL, ":");
971 		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
972 			*target = strtol(tmpstr, NULL, 0);
973 			*arglist |= CAM_ARG_TARGET;
974 			convs++;
975 			tmpstr = (char *)strtok(NULL, ":");
976 			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
977 				*lun = strtol(tmpstr, NULL, 0);
978 				*arglist |= CAM_ARG_LUN;
979 				convs++;
980 			}
981 		}
982 	}
983 
984 	return convs;
985 }
986 
987 static int
988 dorescan_or_reset(int argc, char **argv, int rescan)
989 {
990 	static const char *must =
991 		"you must specify a bus, or a bus:target:lun to %s";
992 	int rv, error = 0;
993 	int bus = -1, target = -1, lun = -1;
994 
995 	if (argc < 3) {
996 		warnx(must, rescan? "rescan" : "reset");
997 		return(1);
998 	}
999 	rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1000 	if (rv != 1 && rv != 3) {
1001 		warnx(must, rescan? "rescan" : "reset");
1002 		return(1);
1003 	}
1004 
1005 	if ((arglist & CAM_ARG_BUS)
1006 	    && (arglist & CAM_ARG_TARGET)
1007 	    && (arglist & CAM_ARG_LUN))
1008 		error = scanlun_or_reset_dev(bus, target, lun, rescan);
1009 	else
1010 		error = rescan_or_reset_bus(bus, rescan);
1011 
1012 	return(error);
1013 }
1014 
1015 static int
1016 rescan_or_reset_bus(int bus, int rescan)
1017 {
1018 	union ccb ccb;
1019 	int fd;
1020 
1021 	if (bus < 0) {
1022 		warnx("invalid bus number %d", bus);
1023 		return(1);
1024 	}
1025 
1026 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1027 		warnx("error opening tranport layer device %s", XPT_DEVICE);
1028 		warn("%s", XPT_DEVICE);
1029 		return(1);
1030 	}
1031 
1032 	ccb.ccb_h.func_code = rescan? XPT_SCAN_BUS : XPT_RESET_BUS;
1033 	ccb.ccb_h.path_id = bus;
1034 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1035 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1036 	ccb.crcn.flags = CAM_FLAG_NONE;
1037 
1038 	/* run this at a low priority */
1039 	ccb.ccb_h.pinfo.priority = 5;
1040 
1041 	if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1042 		warn("CAMIOCOMMAND ioctl failed");
1043 		close(fd);
1044 		return(1);
1045 	}
1046 
1047 	close(fd);
1048 
1049 	if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1050 		fprintf(stdout, "%s of bus %d was successful\n",
1051 		    rescan? "Re-scan" : "Reset", bus);
1052 		return(0);
1053 	} else {
1054 		fprintf(stdout, "%s of bus %d returned error %#x\n",
1055 		    rescan? "Re-scan" : "Reset", bus,
1056 		    ccb.ccb_h.status & CAM_STATUS_MASK);
1057 		return(1);
1058 	}
1059 }
1060 
1061 static int
1062 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1063 {
1064 	union ccb ccb;
1065 	struct cam_device *device;
1066 	int fd;
1067 
1068 	if (bus < 0) {
1069 		warnx("invalid bus number %d", bus);
1070 		return(1);
1071 	}
1072 
1073 	if (target < 0) {
1074 		warnx("invalid target number %d", target);
1075 		return(1);
1076 	}
1077 
1078 	if (lun < 0) {
1079 		warnx("invalid lun number %d", lun);
1080 		return(1);
1081 	}
1082 
1083 	fd = -1;
1084 
1085 	bzero(&ccb, sizeof(union ccb));
1086 
1087 	if (scan) {
1088 		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1089 			warnx("error opening tranport layer device %s\n",
1090 			    XPT_DEVICE);
1091 			warn("%s", XPT_DEVICE);
1092 			return(1);
1093 		}
1094 	} else {
1095 		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1096 		if (device == NULL) {
1097 			warnx("%s", cam_errbuf);
1098 			return(1);
1099 		}
1100 	}
1101 
1102 	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1103 	ccb.ccb_h.path_id = bus;
1104 	ccb.ccb_h.target_id = target;
1105 	ccb.ccb_h.target_lun = lun;
1106 	ccb.ccb_h.timeout = 5000;
1107 	ccb.crcn.flags = CAM_FLAG_NONE;
1108 
1109 	/* run this at a low priority */
1110 	ccb.ccb_h.pinfo.priority = 5;
1111 
1112 	if (scan) {
1113 		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1114 			warn("CAMIOCOMMAND ioctl failed");
1115 			close(fd);
1116 			return(1);
1117 		}
1118 	} else {
1119 		if (cam_send_ccb(device, &ccb) < 0) {
1120 			warn("error sending XPT_RESET_DEV CCB");
1121 			cam_close_device(device);
1122 			return(1);
1123 		}
1124 	}
1125 
1126 	if (scan)
1127 		close(fd);
1128 	else
1129 		cam_close_device(device);
1130 
1131 	/*
1132 	 * An error code of CAM_BDR_SENT is normal for a BDR request.
1133 	 */
1134 	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1135 	 || ((!scan)
1136 	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1137 		fprintf(stdout, "%s of %d:%d:%d was successful\n",
1138 		    scan? "Re-scan" : "Reset", bus, target, lun);
1139 		return(0);
1140 	} else {
1141 		fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1142 		    scan? "Re-scan" : "Reset", bus, target, lun,
1143 		    ccb.ccb_h.status & CAM_STATUS_MASK);
1144 		return(1);
1145 	}
1146 }
1147 
1148 static int
1149 readdefects(struct cam_device *device, int argc, char **argv,
1150 	    char *combinedopt, int retry_count, int timeout)
1151 {
1152 	union ccb *ccb = NULL;
1153 	struct scsi_read_defect_data_10 *rdd_cdb;
1154 	u_int8_t *defect_list = NULL;
1155 	u_int32_t dlist_length = 65000;
1156 	u_int32_t returned_length = 0;
1157 	u_int32_t num_returned = 0;
1158 	u_int8_t returned_format;
1159 	register int i;
1160 	int c, error = 0;
1161 	int lists_specified = 0;
1162 
1163 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1164 		switch(c){
1165 		case 'f':
1166 		{
1167 			char *tstr;
1168 			tstr = optarg;
1169 			while (isspace(*tstr) && (*tstr != '\0'))
1170 				tstr++;
1171 			if (strcmp(tstr, "block") == 0)
1172 				arglist |= CAM_ARG_FORMAT_BLOCK;
1173 			else if (strcmp(tstr, "bfi") == 0)
1174 				arglist |= CAM_ARG_FORMAT_BFI;
1175 			else if (strcmp(tstr, "phys") == 0)
1176 				arglist |= CAM_ARG_FORMAT_PHYS;
1177 			else {
1178 				error = 1;
1179 				warnx("invalid defect format %s", tstr);
1180 				goto defect_bailout;
1181 			}
1182 			break;
1183 		}
1184 		case 'G':
1185 			arglist |= CAM_ARG_GLIST;
1186 			break;
1187 		case 'P':
1188 			arglist |= CAM_ARG_PLIST;
1189 			break;
1190 		default:
1191 			break;
1192 		}
1193 	}
1194 
1195 	ccb = cam_getccb(device);
1196 
1197 	/*
1198 	 * Hopefully 65000 bytes is enough to hold the defect list.  If it
1199 	 * isn't, the disk is probably dead already.  We'd have to go with
1200 	 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1201 	 * to hold them all.
1202 	 */
1203 	defect_list = malloc(dlist_length);
1204 
1205 	rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1206 
1207 	/*
1208 	 * cam_getccb() zeros the CCB header only.  So we need to zero the
1209 	 * payload portion of the ccb.
1210 	 */
1211 	bzero(&(&ccb->ccb_h)[1],
1212 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1213 
1214 	cam_fill_csio(&ccb->csio,
1215 		      /*retries*/ retry_count,
1216 		      /*cbfcnp*/ NULL,
1217 		      /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1218 					      CAM_PASS_ERR_RECOVER : 0),
1219 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
1220 		      /*data_ptr*/ defect_list,
1221 		      /*dxfer_len*/ dlist_length,
1222 		      /*sense_len*/ SSD_FULL_SIZE,
1223 		      /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1224 		      /*timeout*/ timeout ? timeout : 5000);
1225 
1226 	rdd_cdb->opcode = READ_DEFECT_DATA_10;
1227 	if (arglist & CAM_ARG_FORMAT_BLOCK)
1228 		rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1229 	else if (arglist & CAM_ARG_FORMAT_BFI)
1230 		rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1231 	else if (arglist & CAM_ARG_FORMAT_PHYS)
1232 		rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1233 	else {
1234 		error = 1;
1235 		warnx("no defect list format specified");
1236 		goto defect_bailout;
1237 	}
1238 	if (arglist & CAM_ARG_PLIST) {
1239 		rdd_cdb->format |= SRDD10_PLIST;
1240 		lists_specified++;
1241 	}
1242 
1243 	if (arglist & CAM_ARG_GLIST) {
1244 		rdd_cdb->format |= SRDD10_GLIST;
1245 		lists_specified++;
1246 	}
1247 
1248 	scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1249 
1250 	/* Disable freezing the device queue */
1251 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1252 
1253 	if (cam_send_ccb(device, ccb) < 0) {
1254 		perror("error reading defect list");
1255 
1256 		if (arglist & CAM_ARG_VERBOSE) {
1257 		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1258 			    CAM_SCSI_STATUS_ERROR)
1259 				scsi_sense_print(device, &ccb->csio, stderr);
1260 			else
1261 				fprintf(stderr, "CAM status is %#x\n",
1262 					ccb->ccb_h.status);
1263 		}
1264 
1265 		error = 1;
1266 		goto defect_bailout;
1267 	}
1268 
1269 	if (arglist & CAM_ARG_VERBOSE)
1270 		scsi_sense_print(device, &ccb->csio, stderr);
1271 
1272 	returned_length = scsi_2btoul(((struct
1273 		scsi_read_defect_data_hdr_10 *)defect_list)->length);
1274 
1275 	returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1276 			defect_list)->format;
1277 
1278 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1279 		struct scsi_sense_data *sense;
1280 		int error_code, sense_key, asc, ascq;
1281 
1282 		sense = &ccb->csio.sense_data;
1283 		scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1284 
1285 		/*
1286 		 * According to the SCSI spec, if the disk doesn't support
1287 		 * the requested format, it will generally return a sense
1288 		 * key of RECOVERED ERROR, and an additional sense code
1289 		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1290 		 * also check to make sure that the returned length is
1291 		 * greater than 0, and then print out whatever format the
1292 		 * disk gave us.
1293 		 */
1294 		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1295 		 && (asc == 0x1c) && (ascq == 0x00)
1296 		 && (returned_length > 0)) {
1297 			warnx("requested defect format not available");
1298 			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1299 			case SRDD10_BLOCK_FORMAT:
1300 				warnx("Device returned block format");
1301 				break;
1302 			case SRDD10_BYTES_FROM_INDEX_FORMAT:
1303 				warnx("Device returned bytes from index"
1304 				      " format");
1305 				break;
1306 			case SRDD10_PHYSICAL_SECTOR_FORMAT:
1307 				warnx("Device returned physical sector format");
1308 				break;
1309 			default:
1310 				error = 1;
1311 				warnx("Device returned unknown defect"
1312 				     " data format %#x", returned_format);
1313 				goto defect_bailout;
1314 				break; /* NOTREACHED */
1315 			}
1316 		} else {
1317 			error = 1;
1318 			warnx("Error returned from read defect data command");
1319 			goto defect_bailout;
1320 		}
1321 	}
1322 
1323 	/*
1324 	 * XXX KDM  I should probably clean up the printout format for the
1325 	 * disk defects.
1326 	 */
1327 	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1328 		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1329 		{
1330 			struct scsi_defect_desc_phys_sector *dlist;
1331 
1332 			dlist = (struct scsi_defect_desc_phys_sector *)
1333 				(defect_list +
1334 				sizeof(struct scsi_read_defect_data_hdr_10));
1335 
1336 			num_returned = returned_length /
1337 				sizeof(struct scsi_defect_desc_phys_sector);
1338 
1339 			fprintf(stderr, "Got %d defect", num_returned);
1340 
1341 			if ((lists_specified == 0) || (num_returned == 0)) {
1342 				fprintf(stderr, "s.\n");
1343 				break;
1344 			} else if (num_returned == 1)
1345 				fprintf(stderr, ":\n");
1346 			else
1347 				fprintf(stderr, "s:\n");
1348 
1349 			for (i = 0; i < num_returned; i++) {
1350 				fprintf(stdout, "%d:%d:%d\n",
1351 					scsi_3btoul(dlist[i].cylinder),
1352 					dlist[i].head,
1353 					scsi_4btoul(dlist[i].sector));
1354 			}
1355 			break;
1356 		}
1357 		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1358 		{
1359 			struct scsi_defect_desc_bytes_from_index *dlist;
1360 
1361 			dlist = (struct scsi_defect_desc_bytes_from_index *)
1362 				(defect_list +
1363 				sizeof(struct scsi_read_defect_data_hdr_10));
1364 
1365 			num_returned = returned_length /
1366 			      sizeof(struct scsi_defect_desc_bytes_from_index);
1367 
1368 			fprintf(stderr, "Got %d defect", num_returned);
1369 
1370 			if ((lists_specified == 0) || (num_returned == 0)) {
1371 				fprintf(stderr, "s.\n");
1372 				break;
1373 			} else if (num_returned == 1)
1374 				fprintf(stderr, ":\n");
1375 			else
1376 				fprintf(stderr, "s:\n");
1377 
1378 			for (i = 0; i < num_returned; i++) {
1379 				fprintf(stdout, "%d:%d:%d\n",
1380 					scsi_3btoul(dlist[i].cylinder),
1381 					dlist[i].head,
1382 					scsi_4btoul(dlist[i].bytes_from_index));
1383 			}
1384 			break;
1385 		}
1386 		case SRDDH10_BLOCK_FORMAT:
1387 		{
1388 			struct scsi_defect_desc_block *dlist;
1389 
1390 			dlist = (struct scsi_defect_desc_block *)(defect_list +
1391 				sizeof(struct scsi_read_defect_data_hdr_10));
1392 
1393 			num_returned = returned_length /
1394 			      sizeof(struct scsi_defect_desc_block);
1395 
1396 			fprintf(stderr, "Got %d defect", num_returned);
1397 
1398 			if ((lists_specified == 0) || (num_returned == 0)) {
1399 				fprintf(stderr, "s.\n");
1400 				break;
1401 			} else if (num_returned == 1)
1402 				fprintf(stderr, ":\n");
1403 			else
1404 				fprintf(stderr, "s:\n");
1405 
1406 			for (i = 0; i < num_returned; i++)
1407 				fprintf(stdout, "%u\n",
1408 					scsi_4btoul(dlist[i].address));
1409 			break;
1410 		}
1411 		default:
1412 			fprintf(stderr, "Unknown defect format %d\n",
1413 				returned_format & SRDDH10_DLIST_FORMAT_MASK);
1414 			error = 1;
1415 			break;
1416 	}
1417 defect_bailout:
1418 
1419 	if (defect_list != NULL)
1420 		free(defect_list);
1421 
1422 	if (ccb != NULL)
1423 		cam_freeccb(ccb);
1424 
1425 	return(error);
1426 }
1427 
1428 #if 0
1429 void
1430 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
1431 {
1432 	union ccb *ccb;
1433 
1434 	ccb = cam_getccb(device);
1435 
1436 	cam_freeccb(ccb);
1437 }
1438 #endif
1439 
1440 void
1441 mode_sense(struct cam_device *device, int mode_page, int page_control,
1442 	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
1443 {
1444 	union ccb *ccb;
1445 	int retval;
1446 
1447 	ccb = cam_getccb(device);
1448 
1449 	if (ccb == NULL)
1450 		errx(1, "mode_sense: couldn't allocate CCB");
1451 
1452 	bzero(&(&ccb->ccb_h)[1],
1453 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1454 
1455 	scsi_mode_sense(&ccb->csio,
1456 			/* retries */ retry_count,
1457 			/* cbfcnp */ NULL,
1458 			/* tag_action */ MSG_SIMPLE_Q_TAG,
1459 			/* dbd */ dbd,
1460 			/* page_code */ page_control << 6,
1461 			/* page */ mode_page,
1462 			/* param_buf */ data,
1463 			/* param_len */ datalen,
1464 			/* sense_len */ SSD_FULL_SIZE,
1465 			/* timeout */ timeout ? timeout : 5000);
1466 
1467 	if (arglist & CAM_ARG_ERR_RECOVER)
1468 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1469 
1470 	/* Disable freezing the device queue */
1471 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1472 
1473 	if (((retval = cam_send_ccb(device, ccb)) < 0)
1474 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1475 		if (arglist & CAM_ARG_VERBOSE) {
1476 		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1477 			    CAM_SCSI_STATUS_ERROR)
1478 				scsi_sense_print(device, &ccb->csio, stderr);
1479 			else
1480 				fprintf(stderr, "CAM status is %#x\n",
1481 					ccb->ccb_h.status);
1482 		}
1483 		cam_freeccb(ccb);
1484 		cam_close_device(device);
1485 		if (retval < 0)
1486 			err(1, "error sending mode sense command");
1487 		else
1488 			errx(1, "error sending mode sense command");
1489 	}
1490 
1491 	cam_freeccb(ccb);
1492 }
1493 
1494 void
1495 mode_select(struct cam_device *device, int save_pages, int retry_count,
1496 	   int timeout, u_int8_t *data, int datalen)
1497 {
1498 	union ccb *ccb;
1499 	int retval;
1500 
1501 	ccb = cam_getccb(device);
1502 
1503 	if (ccb == NULL)
1504 		errx(1, "mode_select: couldn't allocate CCB");
1505 
1506 	bzero(&(&ccb->ccb_h)[1],
1507 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1508 
1509 	scsi_mode_select(&ccb->csio,
1510 			 /* retries */ retry_count,
1511 			 /* cbfcnp */ NULL,
1512 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
1513 			 /* scsi_page_fmt */ 1,
1514 			 /* save_pages */ save_pages,
1515 			 /* param_buf */ data,
1516 			 /* param_len */ datalen,
1517 			 /* sense_len */ SSD_FULL_SIZE,
1518 			 /* timeout */ timeout ? timeout : 5000);
1519 
1520 	if (arglist & CAM_ARG_ERR_RECOVER)
1521 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1522 
1523 	/* Disable freezing the device queue */
1524 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1525 
1526 	if (((retval = cam_send_ccb(device, ccb)) < 0)
1527 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1528 		if (arglist & CAM_ARG_VERBOSE) {
1529 		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1530 			    CAM_SCSI_STATUS_ERROR)
1531 				scsi_sense_print(device, &ccb->csio, stderr);
1532 			else
1533 				fprintf(stderr, "CAM status is %#x\n",
1534 					ccb->ccb_h.status);
1535 		}
1536 		cam_freeccb(ccb);
1537 		cam_close_device(device);
1538 
1539 		if (retval < 0)
1540 			err(1, "error sending mode select command");
1541 		else
1542 			errx(1, "error sending mode select command");
1543 
1544 	}
1545 
1546 	cam_freeccb(ccb);
1547 }
1548 
1549 void
1550 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
1551 	 int retry_count, int timeout)
1552 {
1553 	int c, mode_page = -1, page_control = 0;
1554 
1555 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1556 		switch(c) {
1557 		case 'd':
1558 			arglist |= CAM_ARG_DBD;
1559 			break;
1560 		case 'e':
1561 			arglist |= CAM_ARG_MODE_EDIT;
1562 			break;
1563 		case 'm':
1564 			mode_page = strtol(optarg, NULL, 0);
1565 			if (mode_page < 0)
1566 				errx(1, "invalid mode page %d", mode_page);
1567 			break;
1568 		case 'P':
1569 			page_control = strtol(optarg, NULL, 0);
1570 			if ((page_control < 0) || (page_control > 3))
1571 				errx(1, "invalid page control field %d",
1572 				     page_control);
1573 			arglist |= CAM_ARG_PAGE_CNTL;
1574 			break;
1575 		default:
1576 			break;
1577 		}
1578 	}
1579 
1580 	if (mode_page == -1)
1581 		errx(1, "you must specify a mode page!");
1582 
1583 	mode_edit(device, mode_page, page_control, arglist & CAM_ARG_DBD,
1584 		  arglist & CAM_ARG_MODE_EDIT, retry_count, timeout);
1585 }
1586 
1587 static int
1588 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
1589 	int retry_count, int timeout)
1590 {
1591 	union ccb *ccb;
1592 	u_int32_t flags = CAM_DIR_NONE;
1593 	u_int8_t *data_ptr = NULL;
1594 	u_int8_t cdb[20];
1595 	struct get_hook hook;
1596 	int c, data_bytes = 0;
1597 	int cdb_len = 0;
1598 	char *datastr = NULL, *tstr;
1599 	int error = 0;
1600 	int fd_data = 0;
1601 	int retval;
1602 
1603 	ccb = cam_getccb(device);
1604 
1605 	if (ccb == NULL) {
1606 		warnx("scsicmd: error allocating ccb");
1607 		return(1);
1608 	}
1609 
1610 	bzero(&(&ccb->ccb_h)[1],
1611 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1612 
1613 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1614 		switch(c) {
1615 		case 'c':
1616 			tstr = optarg;
1617 			while (isspace(*tstr) && (*tstr != '\0'))
1618 				tstr++;
1619 			hook.argc = argc - optind;
1620 			hook.argv = argv + optind;
1621 			hook.got = 0;
1622 			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
1623 						    iget, &hook);
1624 			/*
1625 			 * Increment optind by the number of arguments the
1626 			 * encoding routine processed.  After each call to
1627 			 * getopt(3), optind points to the argument that
1628 			 * getopt should process _next_.  In this case,
1629 			 * that means it points to the first command string
1630 			 * argument, if there is one.  Once we increment
1631 			 * this, it should point to either the next command
1632 			 * line argument, or it should be past the end of
1633 			 * the list.
1634 			 */
1635 			optind += hook.got;
1636 			break;
1637 		case 'i':
1638 			if (arglist & CAM_ARG_CMD_OUT) {
1639 				warnx("command must either be "
1640 				      "read or write, not both");
1641 				error = 1;
1642 				goto scsicmd_bailout;
1643 			}
1644 			arglist |= CAM_ARG_CMD_IN;
1645 			flags = CAM_DIR_IN;
1646 			data_bytes = strtol(optarg, NULL, 0);
1647 			if (data_bytes <= 0) {
1648 				warnx("invalid number of input bytes %d",
1649 				      data_bytes);
1650 				error = 1;
1651 				goto scsicmd_bailout;
1652 			}
1653 			hook.argc = argc - optind;
1654 			hook.argv = argv + optind;
1655 			hook.got = 0;
1656 			optind++;
1657 			datastr = cget(&hook, NULL);
1658 			/*
1659 			 * If the user supplied "-" instead of a format, he
1660 			 * wants the data to be written to stdout.
1661 			 */
1662 			if ((datastr != NULL)
1663 			 && (datastr[0] == '-'))
1664 				fd_data = 1;
1665 
1666 			data_ptr = (u_int8_t *)malloc(data_bytes);
1667 			break;
1668 		case 'o':
1669 			if (arglist & CAM_ARG_CMD_IN) {
1670 				warnx("command must either be "
1671 				      "read or write, not both");
1672 				error = 1;
1673 				goto scsicmd_bailout;
1674 			}
1675 			arglist |= CAM_ARG_CMD_OUT;
1676 			flags = CAM_DIR_OUT;
1677 			data_bytes = strtol(optarg, NULL, 0);
1678 			if (data_bytes <= 0) {
1679 				warnx("invalid number of output bytes %d",
1680 				      data_bytes);
1681 				error = 1;
1682 				goto scsicmd_bailout;
1683 			}
1684 			hook.argc = argc - optind;
1685 			hook.argv = argv + optind;
1686 			hook.got = 0;
1687 			datastr = cget(&hook, NULL);
1688 			data_ptr = (u_int8_t *)malloc(data_bytes);
1689 			/*
1690 			 * If the user supplied "-" instead of a format, he
1691 			 * wants the data to be read from stdin.
1692 			 */
1693 			if ((datastr != NULL)
1694 			 && (datastr[0] == '-'))
1695 				fd_data = 1;
1696 			else
1697 				buff_encode_visit(data_ptr, data_bytes, datastr,
1698 						  iget, &hook);
1699 			optind += hook.got;
1700 			break;
1701 		default:
1702 			break;
1703 		}
1704 	}
1705 
1706 	/*
1707 	 * If fd_data is set, and we're writing to the device, we need to
1708 	 * read the data the user wants written from stdin.
1709 	 */
1710 	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
1711 		size_t amt_read;
1712 		int amt_to_read = data_bytes;
1713 		u_int8_t *buf_ptr = data_ptr;
1714 
1715 		for (amt_read = 0; amt_to_read > 0;
1716 		     amt_read = read(0, buf_ptr, amt_to_read)) {
1717 			if (amt_read == -1) {
1718 				warn("error reading data from stdin");
1719 				error = 1;
1720 				goto scsicmd_bailout;
1721 			}
1722 			amt_to_read -= amt_read;
1723 			buf_ptr += amt_read;
1724 		}
1725 	}
1726 
1727 	if (arglist & CAM_ARG_ERR_RECOVER)
1728 		flags |= CAM_PASS_ERR_RECOVER;
1729 
1730 	/* Disable freezing the device queue */
1731 	flags |= CAM_DEV_QFRZDIS;
1732 
1733 	/*
1734 	 * This is taken from the SCSI-3 draft spec.
1735 	 * (T10/1157D revision 0.3)
1736 	 * The top 3 bits of an opcode are the group code.  The next 5 bits
1737 	 * are the command code.
1738 	 * Group 0:  six byte commands
1739 	 * Group 1:  ten byte commands
1740 	 * Group 2:  ten byte commands
1741 	 * Group 3:  reserved
1742 	 * Group 4:  sixteen byte commands
1743 	 * Group 5:  twelve byte commands
1744 	 * Group 6:  vendor specific
1745 	 * Group 7:  vendor specific
1746 	 */
1747 	switch((cdb[0] >> 5) & 0x7) {
1748 		case 0:
1749 			cdb_len = 6;
1750 			break;
1751 		case 1:
1752 		case 2:
1753 			cdb_len = 10;
1754 			break;
1755 		case 3:
1756 		case 6:
1757 		case 7:
1758 		        /* computed by buff_encode_visit */
1759 			break;
1760 		case 4:
1761 			cdb_len = 16;
1762 			break;
1763 		case 5:
1764 			cdb_len = 12;
1765 			break;
1766 	}
1767 
1768 	/*
1769 	 * We should probably use csio_build_visit or something like that
1770 	 * here, but it's easier to encode arguments as you go.  The
1771 	 * alternative would be skipping the CDB argument and then encoding
1772 	 * it here, since we've got the data buffer argument by now.
1773 	 */
1774 	bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
1775 
1776 	cam_fill_csio(&ccb->csio,
1777 		      /*retries*/ retry_count,
1778 		      /*cbfcnp*/ NULL,
1779 		      /*flags*/ flags,
1780 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
1781 		      /*data_ptr*/ data_ptr,
1782 		      /*dxfer_len*/ data_bytes,
1783 		      /*sense_len*/ SSD_FULL_SIZE,
1784 		      /*cdb_len*/ cdb_len,
1785 		      /*timeout*/ timeout ? timeout : 5000);
1786 
1787 	if (((retval = cam_send_ccb(device, ccb)) < 0)
1788 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1789 		if (retval < 0)
1790 			warn("error sending command");
1791 		else
1792 			warnx("error sending command");
1793 
1794 		if (arglist & CAM_ARG_VERBOSE) {
1795 		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1796 			    CAM_SCSI_STATUS_ERROR)
1797 				scsi_sense_print(device, &ccb->csio, stderr);
1798 			else
1799 				fprintf(stderr, "CAM status is %#x\n",
1800 					ccb->ccb_h.status);
1801 		}
1802 
1803 		error = 1;
1804 		goto scsicmd_bailout;
1805 	}
1806 
1807 
1808 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1809 	 && (arglist & CAM_ARG_CMD_IN)
1810 	 && (data_bytes > 0)) {
1811 		if (fd_data == 0) {
1812 			buff_decode_visit(data_ptr, data_bytes, datastr,
1813 					  arg_put, NULL);
1814 			fprintf(stdout, "\n");
1815 		} else {
1816 			size_t amt_written;
1817 			int amt_to_write = data_bytes;
1818 			u_int8_t *buf_ptr = data_ptr;
1819 
1820 			for (amt_written = 0; (amt_to_write > 0) &&
1821 			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
1822 				amt_to_write -= amt_written;
1823 				buf_ptr += amt_written;
1824 			}
1825 			if (amt_written == -1) {
1826 				warn("error writing data to stdout");
1827 				error = 1;
1828 				goto scsicmd_bailout;
1829 			} else if ((amt_written == 0)
1830 				&& (amt_to_write > 0)) {
1831 				warnx("only wrote %u bytes out of %u",
1832 				      data_bytes - amt_to_write, data_bytes);
1833 			}
1834 		}
1835 	}
1836 
1837 scsicmd_bailout:
1838 
1839 	if ((data_bytes > 0) && (data_ptr != NULL))
1840 		free(data_ptr);
1841 
1842 	cam_freeccb(ccb);
1843 
1844 	return(error);
1845 }
1846 
1847 static int
1848 camdebug(int argc, char **argv, char *combinedopt)
1849 {
1850 	int c, fd;
1851 	int bus = -1, target = -1, lun = -1;
1852 	char *tstr, *tmpstr = NULL;
1853 	union ccb ccb;
1854 	int error = 0;
1855 
1856 	bzero(&ccb, sizeof(union ccb));
1857 
1858 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1859 		switch(c) {
1860 		case 'I':
1861 			arglist |= CAM_ARG_DEBUG_INFO;
1862 			ccb.cdbg.flags |= CAM_DEBUG_INFO;
1863 			break;
1864 		case 'S':
1865 			arglist |= CAM_ARG_DEBUG_SUBTRACE;
1866 			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
1867 			break;
1868 		case 'T':
1869 			arglist |= CAM_ARG_DEBUG_TRACE;
1870 			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
1871 			break;
1872 		case 'c':
1873 			arglist |= CAM_ARG_DEBUG_CDB;
1874 			ccb.cdbg.flags |= CAM_DEBUG_CDB;
1875 			break;
1876 		default:
1877 			break;
1878 		}
1879 	}
1880 
1881 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1882 		warnx("error opening transport layer device %s", XPT_DEVICE);
1883 		warn("%s", XPT_DEVICE);
1884 		return(1);
1885 	}
1886 	argc -= optind;
1887 	argv += optind;
1888 
1889 	if (argc <= 0) {
1890 		warnx("you must specify \"off\", \"all\" or a bus,");
1891 		warnx("bus:target, or bus:target:lun");
1892 		close(fd);
1893 		return(1);
1894 	}
1895 
1896 	tstr = *argv;
1897 
1898 	while (isspace(*tstr) && (*tstr != '\0'))
1899 		tstr++;
1900 
1901 	if (strncmp(tstr, "off", 3) == 0) {
1902 		ccb.cdbg.flags = CAM_DEBUG_NONE;
1903 		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_TRACE|
1904 			     CAM_ARG_DEBUG_SUBTRACE);
1905 	} else if (strncmp(tstr, "all", 3) != 0) {
1906 		tmpstr = (char *)strtok(tstr, ":");
1907 		if ((tmpstr != NULL) && (*tmpstr != '\0')){
1908 			bus = strtol(tmpstr, NULL, 0);
1909 			arglist |= CAM_ARG_BUS;
1910 			tmpstr = (char *)strtok(NULL, ":");
1911 			if ((tmpstr != NULL) && (*tmpstr != '\0')){
1912 				target = strtol(tmpstr, NULL, 0);
1913 				arglist |= CAM_ARG_TARGET;
1914 				tmpstr = (char *)strtok(NULL, ":");
1915 				if ((tmpstr != NULL) && (*tmpstr != '\0')){
1916 					lun = strtol(tmpstr, NULL, 0);
1917 					arglist |= CAM_ARG_LUN;
1918 				}
1919 			}
1920 		} else {
1921 			error = 1;
1922 			warnx("you must specify \"all\", \"off\", or a bus,");
1923 			warnx("bus:target, or bus:target:lun to debug");
1924 		}
1925 	}
1926 
1927 	if (error == 0) {
1928 
1929 		ccb.ccb_h.func_code = XPT_DEBUG;
1930 		ccb.ccb_h.path_id = bus;
1931 		ccb.ccb_h.target_id = target;
1932 		ccb.ccb_h.target_lun = lun;
1933 
1934 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1935 			warn("CAMIOCOMMAND ioctl failed");
1936 			error = 1;
1937 		}
1938 
1939 		if (error == 0) {
1940 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
1941 			     CAM_FUNC_NOTAVAIL) {
1942 				warnx("CAM debugging not available");
1943 				warnx("you need to put options CAMDEBUG in"
1944 				      " your kernel config file!");
1945 				error = 1;
1946 			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
1947 				    CAM_REQ_CMP) {
1948 				warnx("XPT_DEBUG CCB failed with status %#x",
1949 				      ccb.ccb_h.status);
1950 				error = 1;
1951 			} else {
1952 				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
1953 					fprintf(stderr,
1954 						"Debugging turned off\n");
1955 				} else {
1956 					fprintf(stderr,
1957 						"Debugging enabled for "
1958 						"%d:%d:%d\n",
1959 						bus, target, lun);
1960 				}
1961 			}
1962 		}
1963 		close(fd);
1964 	}
1965 
1966 	return(error);
1967 }
1968 
1969 static int
1970 tagcontrol(struct cam_device *device, int argc, char **argv,
1971 	   char *combinedopt)
1972 {
1973 	int c;
1974 	union ccb *ccb;
1975 	int numtags = -1;
1976 	int retval = 0;
1977 	int quiet = 0;
1978 	char pathstr[1024];
1979 
1980 	ccb = cam_getccb(device);
1981 
1982 	if (ccb == NULL) {
1983 		warnx("tagcontrol: error allocating ccb");
1984 		return(1);
1985 	}
1986 
1987 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1988 		switch(c) {
1989 		case 'N':
1990 			numtags = strtol(optarg, NULL, 0);
1991 			if (numtags < 0) {
1992 				warnx("tag count %d is < 0", numtags);
1993 				retval = 1;
1994 				goto tagcontrol_bailout;
1995 			}
1996 			break;
1997 		case 'q':
1998 			quiet++;
1999 			break;
2000 		default:
2001 			break;
2002 		}
2003 	}
2004 
2005 	cam_path_string(device, pathstr, sizeof(pathstr));
2006 
2007 	if (numtags >= 0) {
2008 		bzero(&(&ccb->ccb_h)[1],
2009 		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2010 		ccb->ccb_h.func_code = XPT_REL_SIMQ;
2011 		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2012 		ccb->crs.openings = numtags;
2013 
2014 
2015 		if (cam_send_ccb(device, ccb) < 0) {
2016 			perror("error sending XPT_REL_SIMQ CCB");
2017 			retval = 1;
2018 			goto tagcontrol_bailout;
2019 		}
2020 
2021 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2022 			warnx("XPT_REL_SIMQ CCB failed, status %#x",
2023 			      ccb->ccb_h.status);
2024 			retval = 1;
2025 			goto tagcontrol_bailout;
2026 		}
2027 
2028 
2029 		if (quiet == 0)
2030 			fprintf(stdout, "%stagged openings now %d\n",
2031 				pathstr, ccb->crs.openings);
2032 	}
2033 
2034 	bzero(&(&ccb->ccb_h)[1],
2035 	      sizeof(struct ccb_getdev) - sizeof(struct ccb_hdr));
2036 
2037 	ccb->ccb_h.func_code = XPT_GDEV_STATS;
2038 
2039 	if (cam_send_ccb(device, ccb) < 0) {
2040 		perror("error sending XPT_GDEV_STATS CCB");
2041 		retval = 1;
2042 		goto tagcontrol_bailout;
2043 	}
2044 
2045 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2046 		warnx("XPT_GDEV_STATS CCB failed, status %#x",
2047 		      ccb->ccb_h.status);
2048 		retval = 1;
2049 		goto tagcontrol_bailout;
2050 	}
2051 
2052 	if (arglist & CAM_ARG_VERBOSE) {
2053 		fprintf(stdout, "%s", pathstr);
2054 		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2055 		fprintf(stdout, "%s", pathstr);
2056 		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2057 		fprintf(stdout, "%s", pathstr);
2058 		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2059 		fprintf(stdout, "%s", pathstr);
2060 		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2061 		fprintf(stdout, "%s", pathstr);
2062 		fprintf(stdout, "held          %d\n", ccb->cgds.held);
2063 		fprintf(stdout, "%s", pathstr);
2064 		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2065 		fprintf(stdout, "%s", pathstr);
2066 		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2067 	} else {
2068 		if (quiet == 0) {
2069 			fprintf(stdout, "%s", pathstr);
2070 			fprintf(stdout, "device openings: ");
2071 		}
2072 		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2073 			ccb->cgds.dev_active);
2074 	}
2075 
2076 tagcontrol_bailout:
2077 
2078 	cam_freeccb(ccb);
2079 	return(retval);
2080 }
2081 
2082 static void
2083 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2084 {
2085 	char pathstr[1024];
2086 
2087 	cam_path_string(device, pathstr, sizeof(pathstr));
2088 
2089 	if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
2090 
2091 		fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2092 			cts->sync_period);
2093 
2094 		if (cts->sync_offset != 0) {
2095 			u_int freq;
2096 
2097 			freq = scsi_calc_syncsrate(cts->sync_period);
2098 			fprintf(stdout, "%sfrequency: %d.%03dMHz\n", pathstr,
2099 				freq / 1000, freq % 1000);
2100 		}
2101 	}
2102 
2103 	if (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)
2104 		fprintf(stdout, "%soffset: %d\n", pathstr, cts->sync_offset);
2105 
2106 	if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID)
2107 		fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2108 			(0x01 << cts->bus_width) * 8);
2109 
2110 	if (cts->valid & CCB_TRANS_DISC_VALID)
2111 		fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2112 			(cts->flags & CCB_TRANS_DISC_ENB) ? "enabled" :
2113 			"disabled");
2114 
2115 	if (cts->valid & CCB_TRANS_TQ_VALID)
2116 		fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2117 			(cts->flags & CCB_TRANS_TAG_ENB) ? "enabled" :
2118 			"disabled");
2119 
2120 }
2121 
2122 /*
2123  * Get a path inquiry CCB for the specified device.
2124  */
2125 static int
2126 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2127 {
2128 	union ccb *ccb;
2129 	int retval = 0;
2130 
2131 	ccb = cam_getccb(device);
2132 
2133 	if (ccb == NULL) {
2134 		warnx("get_cpi: couldn't allocate CCB");
2135 		return(1);
2136 	}
2137 
2138 	bzero(&(&ccb->ccb_h)[1],
2139 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2140 
2141 	ccb->ccb_h.func_code = XPT_PATH_INQ;
2142 
2143 	if (cam_send_ccb(device, ccb) < 0) {
2144 		warn("get_cpi: error sending Path Inquiry CCB");
2145 
2146 		if (arglist & CAM_ARG_VERBOSE)
2147 			fprintf(stderr, "CAM status is %#x\n",
2148 				ccb->ccb_h.status);
2149 
2150 		retval = 1;
2151 
2152 		goto get_cpi_bailout;
2153 	}
2154 
2155 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2156 
2157 		if (arglist & CAM_ARG_VERBOSE)
2158 			fprintf(stderr, "get_cpi: CAM status is %#x\n",
2159 				ccb->ccb_h.status);
2160 
2161 		retval = 1;
2162 
2163 		goto get_cpi_bailout;
2164 	}
2165 
2166 	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2167 
2168 get_cpi_bailout:
2169 
2170 	cam_freeccb(ccb);
2171 
2172 	return(retval);
2173 }
2174 
2175 static void
2176 cpi_print(struct ccb_pathinq *cpi)
2177 {
2178 	char adapter_str[1024];
2179 	int i;
2180 
2181 	snprintf(adapter_str, sizeof(adapter_str),
2182 		 "%s%d:", cpi->dev_name, cpi->unit_number);
2183 
2184 	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2185 		cpi->version_num);
2186 
2187 	for (i = 1; i < 0xff; i = i << 1) {
2188 		char *str;
2189 
2190 		if ((i & cpi->hba_inquiry) == 0)
2191 			continue;
2192 
2193 		fprintf(stdout, "%s supports ", adapter_str);
2194 
2195 		switch(i) {
2196 		case PI_MDP_ABLE:
2197 			str = "MDP message";
2198 			break;
2199 		case PI_WIDE_32:
2200 			str = "32 bit wide SCSI";
2201 			break;
2202 		case PI_WIDE_16:
2203 			str = "16 bit wide SCSI";
2204 			break;
2205 		case PI_SDTR_ABLE:
2206 			str = "SDTR message";
2207 			break;
2208 		case PI_LINKED_CDB:
2209 			str = "linked CDBs";
2210 			break;
2211 		case PI_TAG_ABLE:
2212 			str = "tag queue messages";
2213 			break;
2214 		case PI_SOFT_RST:
2215 			str = "soft reset alternative";
2216 			break;
2217 		default:
2218 			str = "unknown PI bit set";
2219 			break;
2220 		}
2221 		fprintf(stdout, "%s\n", str);
2222 	}
2223 
2224 	for (i = 1; i < 0xff; i = i << 1) {
2225 		char *str;
2226 
2227 		if ((i & cpi->hba_misc) == 0)
2228 			continue;
2229 
2230 		fprintf(stdout, "%s ", adapter_str);
2231 
2232 		switch(i) {
2233 		case PIM_SCANHILO:
2234 			str = "bus scans from high ID to low ID";
2235 			break;
2236 		case PIM_NOREMOVE:
2237 			str = "removable devices not included in scan";
2238 			break;
2239 		case PIM_NOINITIATOR:
2240 			str = "initiator role not supported";
2241 			break;
2242 		case PIM_NOBUSRESET:
2243 			str = "user has disabled initial BUS RESET or"
2244 			      " controller is in target/mixed mode";
2245 			break;
2246 		default:
2247 			str = "unknown PIM bit set";
2248 			break;
2249 		}
2250 		fprintf(stdout, "%s\n", str);
2251 	}
2252 
2253 	for (i = 1; i < 0xff; i = i << 1) {
2254 		char *str;
2255 
2256 		if ((i & cpi->target_sprt) == 0)
2257 			continue;
2258 
2259 		fprintf(stdout, "%s supports ", adapter_str);
2260 		switch(i) {
2261 		case PIT_PROCESSOR:
2262 			str = "target mode processor mode";
2263 			break;
2264 		case PIT_PHASE:
2265 			str = "target mode phase cog. mode";
2266 			break;
2267 		case PIT_DISCONNECT:
2268 			str = "disconnects in target mode";
2269 			break;
2270 		case PIT_TERM_IO:
2271 			str = "terminate I/O message in target mode";
2272 			break;
2273 		case PIT_GRP_6:
2274 			str = "group 6 commands in target mode";
2275 			break;
2276 		case PIT_GRP_7:
2277 			str = "group 7 commands in target mode";
2278 			break;
2279 		default:
2280 			str = "unknown PIT bit set";
2281 			break;
2282 		}
2283 
2284 		fprintf(stdout, "%s\n", str);
2285 	}
2286 	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
2287 		cpi->hba_eng_cnt);
2288 	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
2289 		cpi->max_target);
2290 	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
2291 		cpi->max_lun);
2292 	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
2293 		adapter_str, cpi->hpath_id);
2294 	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
2295 	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
2296 	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
2297 	fprintf(stdout, "%s base transfer speed: ", adapter_str);
2298 	if (cpi->base_transfer_speed > 1000)
2299 		fprintf(stdout, "%d.%03dMB/sec\n",
2300 			cpi->base_transfer_speed / 1000,
2301 			cpi->base_transfer_speed % 1000);
2302 	else
2303 		fprintf(stdout, "%dKB/sec\n",
2304 			(cpi->base_transfer_speed % 1000) * 1000);
2305 }
2306 
2307 static int
2308 get_print_cts(struct cam_device *device, int user_settings, int quiet,
2309 	      struct ccb_trans_settings *cts)
2310 {
2311 	int retval;
2312 	union ccb *ccb;
2313 
2314 	retval = 0;
2315 	ccb = cam_getccb(device);
2316 
2317 	if (ccb == NULL) {
2318 		warnx("get_print_cts: error allocating ccb");
2319 		return(1);
2320 	}
2321 
2322 	bzero(&(&ccb->ccb_h)[1],
2323 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2324 
2325 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
2326 
2327 	if (user_settings == 0)
2328 		ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
2329 	else
2330 		ccb->cts.flags = CCB_TRANS_USER_SETTINGS;
2331 
2332 	if (cam_send_ccb(device, ccb) < 0) {
2333 		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
2334 		retval = 1;
2335 		goto get_print_cts_bailout;
2336 	}
2337 
2338 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2339 		warnx("XPT_GET_TRANS_SETTINGS CCB failed, status %#x",
2340 		      ccb->ccb_h.status);
2341 		retval = 1;
2342 		goto get_print_cts_bailout;
2343 	}
2344 
2345 	if (quiet == 0)
2346 		cts_print(device, &ccb->cts);
2347 
2348 	if (cts != NULL)
2349 		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
2350 
2351 get_print_cts_bailout:
2352 
2353 	cam_freeccb(ccb);
2354 
2355 	return(retval);
2356 }
2357 
2358 static int
2359 ratecontrol(struct cam_device *device, int retry_count, int timeout,
2360 	    int argc, char **argv, char *combinedopt)
2361 {
2362 	int c;
2363 	union ccb *ccb;
2364 	int user_settings = 0;
2365 	int retval = 0;
2366 	int disc_enable = -1, tag_enable = -1;
2367 	int offset = -1;
2368 	double syncrate = -1;
2369 	int bus_width = -1;
2370 	int quiet = 0;
2371 	int change_settings = 0, send_tur = 0;
2372 	struct ccb_pathinq cpi;
2373 
2374 	ccb = cam_getccb(device);
2375 
2376 	if (ccb == NULL) {
2377 		warnx("ratecontrol: error allocating ccb");
2378 		return(1);
2379 	}
2380 
2381 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2382 		switch(c){
2383 		case 'a':
2384 			send_tur = 1;
2385 			break;
2386 		case 'c':
2387 			user_settings = 0;
2388 			break;
2389 		case 'D':
2390 			if (strncasecmp(optarg, "enable", 6) == 0)
2391 				disc_enable = 1;
2392 			else if (strncasecmp(optarg, "disable", 7) == 0)
2393 				disc_enable = 0;
2394 			else {
2395 				warnx("-D argument \"%s\" is unknown", optarg);
2396 				retval = 1;
2397 				goto ratecontrol_bailout;
2398 			}
2399 			change_settings = 1;
2400 			break;
2401 		case 'O':
2402 			offset = strtol(optarg, NULL, 0);
2403 			if (offset < 0) {
2404 				warnx("offset value %d is < 0", offset);
2405 				retval = 1;
2406 				goto ratecontrol_bailout;
2407 			}
2408 			change_settings = 1;
2409 			break;
2410 		case 'q':
2411 			quiet++;
2412 			break;
2413 		case 'R':
2414 			syncrate = atof(optarg);
2415 
2416 			if (syncrate < 0) {
2417 				warnx("sync rate %f is < 0", syncrate);
2418 				retval = 1;
2419 				goto ratecontrol_bailout;
2420 			}
2421 			change_settings = 1;
2422 			break;
2423 		case 'T':
2424 			if (strncasecmp(optarg, "enable", 6) == 0)
2425 				tag_enable = 1;
2426 			else if (strncasecmp(optarg, "disable", 7) == 0)
2427 				tag_enable = 0;
2428 			else {
2429 				warnx("-T argument \"%s\" is unknown", optarg);
2430 				retval = 1;
2431 				goto ratecontrol_bailout;
2432 			}
2433 			change_settings = 1;
2434 			break;
2435 		case 'U':
2436 			user_settings = 1;
2437 			break;
2438 		case 'W':
2439 			bus_width = strtol(optarg, NULL, 0);
2440 			if (bus_width < 0) {
2441 				warnx("bus width %d is < 0", bus_width);
2442 				retval = 1;
2443 				goto ratecontrol_bailout;
2444 			}
2445 			change_settings = 1;
2446 			break;
2447 		default:
2448 			break;
2449 		}
2450 	}
2451 
2452 	bzero(&(&ccb->ccb_h)[1],
2453 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2454 
2455 	/*
2456 	 * Grab path inquiry information, so we can determine whether
2457 	 * or not the initiator is capable of the things that the user
2458 	 * requests.
2459 	 */
2460 	ccb->ccb_h.func_code = XPT_PATH_INQ;
2461 
2462 	if (cam_send_ccb(device, ccb) < 0) {
2463 		perror("error sending XPT_PATH_INQ CCB");
2464 		retval = 1;
2465 		goto ratecontrol_bailout;
2466 	}
2467 
2468 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2469 		warnx("XPT_PATH_INQ CCB failed, status %#x",
2470 		      ccb->ccb_h.status);
2471 		retval = 1;
2472 		goto ratecontrol_bailout;
2473 	}
2474 
2475 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
2476 
2477 	bzero(&(&ccb->ccb_h)[1],
2478 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2479 
2480 	if (quiet == 0)
2481 		fprintf(stdout, "Current Parameters:\n");
2482 
2483 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
2484 
2485 	if (retval != 0)
2486 		goto ratecontrol_bailout;
2487 
2488 	if (arglist & CAM_ARG_VERBOSE)
2489 		cpi_print(&cpi);
2490 
2491 	if (change_settings) {
2492 		if (disc_enable != -1) {
2493 			ccb->cts.valid |= CCB_TRANS_DISC_VALID;
2494 			if (disc_enable == 0)
2495 				ccb->cts.flags &= ~CCB_TRANS_DISC_ENB;
2496 			else
2497 				ccb->cts.flags |= CCB_TRANS_DISC_ENB;
2498 		} else
2499 			ccb->cts.valid &= ~CCB_TRANS_DISC_VALID;
2500 
2501 		if (tag_enable != -1) {
2502 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
2503 				warnx("HBA does not support tagged queueing, "
2504 				      "so you cannot modify tag settings");
2505 				retval = 1;
2506 				goto ratecontrol_bailout;
2507 			}
2508 
2509 			ccb->cts.valid |= CCB_TRANS_TQ_VALID;
2510 
2511 			if (tag_enable == 0)
2512 				ccb->cts.flags &= ~CCB_TRANS_TAG_ENB;
2513 			else
2514 				ccb->cts.flags |= CCB_TRANS_TAG_ENB;
2515 		} else
2516 			ccb->cts.valid &= ~CCB_TRANS_TQ_VALID;
2517 
2518 		if (offset != -1) {
2519 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2520 				warnx("HBA at %s%d is not cable of changing "
2521 				      "offset", cpi.dev_name,
2522 				      cpi.unit_number);
2523 				retval = 1;
2524 				goto ratecontrol_bailout;
2525 			}
2526 			ccb->cts.valid |= CCB_TRANS_SYNC_OFFSET_VALID;
2527 			ccb->cts.sync_offset = offset;
2528 		} else
2529 			ccb->cts.valid &= ~CCB_TRANS_SYNC_OFFSET_VALID;
2530 
2531 		if (syncrate != -1) {
2532 			int prelim_sync_period;
2533 			u_int freq;
2534 
2535 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2536 				warnx("HBA at %s%d is not cable of changing "
2537 				      "transfer rates", cpi.dev_name,
2538 				      cpi.unit_number);
2539 				retval = 1;
2540 				goto ratecontrol_bailout;
2541 			}
2542 
2543 			ccb->cts.valid |= CCB_TRANS_SYNC_RATE_VALID;
2544 
2545 			/*
2546 			 * The sync rate the user gives us is in MHz.
2547 			 * We need to translate it into KHz for this
2548 			 * calculation.
2549 			 */
2550 			syncrate *= 1000;
2551 
2552 			/*
2553 			 * Next, we calculate a "preliminary" sync period
2554 			 * in tenths of a nanosecond.
2555 			 */
2556 			if (syncrate == 0)
2557 				prelim_sync_period = 0;
2558 			else
2559 				prelim_sync_period = 10000000 / syncrate;
2560 
2561 			ccb->cts.sync_period =
2562 				scsi_calc_syncparam(prelim_sync_period);
2563 
2564 			freq = scsi_calc_syncsrate(ccb->cts.sync_period);
2565 		} else
2566 			ccb->cts.valid &= ~CCB_TRANS_SYNC_RATE_VALID;
2567 
2568 		/*
2569 		 * The bus_width argument goes like this:
2570 		 * 0 == 8 bit
2571 		 * 1 == 16 bit
2572 		 * 2 == 32 bit
2573 		 * Therefore, if you shift the number of bits given on the
2574 		 * command line right by 4, you should get the correct
2575 		 * number.
2576 		 */
2577 		if (bus_width != -1) {
2578 
2579 			/*
2580 			 * We might as well validate things here with a
2581 			 * decipherable error message, rather than what
2582 			 * will probably be an indecipherable error message
2583 			 * by the time it gets back to us.
2584 			 */
2585 			if ((bus_width == 16)
2586 			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
2587 				warnx("HBA does not support 16 bit bus width");
2588 				retval = 1;
2589 				goto ratecontrol_bailout;
2590 			} else if ((bus_width == 32)
2591 				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
2592 				warnx("HBA does not support 32 bit bus width");
2593 				retval = 1;
2594 				goto ratecontrol_bailout;
2595 			} else if ((bus_width != 8)
2596 				&& (bus_width != 16)
2597 				&& (bus_width != 32)) {
2598 				warnx("Invalid bus width %d", bus_width);
2599 				retval = 1;
2600 				goto ratecontrol_bailout;
2601 			}
2602 
2603 			ccb->cts.valid |= CCB_TRANS_BUS_WIDTH_VALID;
2604 			ccb->cts.bus_width = bus_width >> 4;
2605 		} else
2606 			ccb->cts.valid &= ~CCB_TRANS_BUS_WIDTH_VALID;
2607 
2608 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
2609 
2610 		if (cam_send_ccb(device, ccb) < 0) {
2611 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
2612 			retval = 1;
2613 			goto ratecontrol_bailout;
2614 		}
2615 
2616 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2617 			warnx("XPT_SET_TRANS_SETTINGS CCB failed, status %#x",
2618 			      ccb->ccb_h.status);
2619 			retval = 1;
2620 			goto ratecontrol_bailout;
2621 		}
2622 	}
2623 
2624 	if (send_tur) {
2625 		retval = testunitready(device, retry_count, timeout,
2626 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
2627 
2628 		/*
2629 		 * If the TUR didn't succeed, just bail.
2630 		 */
2631 		if (retval != 0) {
2632 			if (quiet == 0)
2633 				fprintf(stderr, "Test Unit Ready failed\n");
2634 			goto ratecontrol_bailout;
2635 		}
2636 
2637 		/*
2638 		 * If the user wants things quiet, there's no sense in
2639 		 * getting the transfer settings, if we're not going
2640 		 * to print them.
2641 		 */
2642 		if (quiet != 0)
2643 			goto ratecontrol_bailout;
2644 
2645 		fprintf(stdout, "New Parameters:\n");
2646 		retval = get_print_cts(device, user_settings, 0, NULL);
2647 	}
2648 
2649 ratecontrol_bailout:
2650 
2651 	cam_freeccb(ccb);
2652 	return(retval);
2653 }
2654 
2655 void
2656 usage(int verbose)
2657 {
2658 	fprintf(stderr,
2659 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
2660 "        camcontrol devlist    [-v]\n"
2661 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
2662 "        camcontrol tur        [dev_id][generic args]\n"
2663 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
2664 "        camcontrol start      [dev_id][generic args]\n"
2665 "        camcontrol stop       [dev_id][generic args]\n"
2666 "        camcontrol eject      [dev_id][generic args]\n"
2667 "        camcontrol rescan     <bus[:target:lun]>\n"
2668 "        camcontrol reset      <bus[:target:lun]>\n"
2669 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
2670 "        camcontrol modepage   [dev_id][generic args] <-m page> [-P pagectl]\n"
2671 "                              [-e][-d]\n"
2672 "        camcontrol cmd        [dev_id][generic args] <-c cmd [args]>\n"
2673 "                              [-i len fmt|-o len fmt [args]]\n"
2674 "        camcontrol debug      [-I][-T][-S][-c] <all|bus[:target[:lun]]|off>\n"
2675 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
2676 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
2677 "                              [-D <enable|disable>][-O offset][-q]\n"
2678 "                              [-R syncrate][-v][-T <enable|disable>]\n"
2679 "                              [-U][-W bus_width]\n"
2680 "        camcontrol help\n");
2681 	if (!verbose)
2682 		return;
2683 	fprintf(stderr,
2684 "Specify one of the following options:\n"
2685 "devlist     list all CAM devices\n"
2686 "periphlist  list all CAM peripheral drivers attached to a device\n"
2687 "tur         send a test unit ready to the named device\n"
2688 "inquiry     send a SCSI inquiry command to the named device\n"
2689 "start       send a Start Unit command to the device\n"
2690 "stop        send a Stop Unit command to the device\n"
2691 "eject       send a Stop Unit command to the device with the eject bit set\n"
2692 "rescan      rescan the given bus, or bus:target:lun\n"
2693 "reset       reset the given bus, or bus:target:lun\n"
2694 "defects     read the defect list of the specified device\n"
2695 "modepage    display or edit (-e) the given mode page\n"
2696 "cmd         send the given scsi command, may need -i or -o as well\n"
2697 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
2698 "tags        report or set the number of transaction slots for a device\n"
2699 "negotiate   report or set device negotiation parameters\n"
2700 "help        this message\n"
2701 "Device Identifiers:\n"
2702 "bus:target        specify the bus and target, lun defaults to 0\n"
2703 "bus:target:lun    specify the bus, target and lun\n"
2704 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
2705 "Generic arguments:\n"
2706 "-v                be verbose, print out sense information\n"
2707 "-t timeout        command timeout in seconds, overrides default timeout\n"
2708 "-n dev_name       specify device name (default is %s)\n"
2709 "-u unit           specify unit number (default is %d)\n"
2710 "-E                have the kernel attempt to perform SCSI error recovery\n"
2711 "-C count          specify the SCSI command retry count (needs -E to work)\n"
2712 "modepage arguments:\n"
2713 "-m page           specify the mode page to view or edit\n"
2714 "-e                edit the specified mode page\n"
2715 "-d                disable block descriptors for mode sense\n"
2716 "-P pgctl          page control field 0-3\n"
2717 "defects arguments:\n"
2718 "-f format         specify defect list format (block, bfi or phys)\n"
2719 "-G                get the grown defect list\n"
2720 "-P                get the permanant defect list\n"
2721 "inquiry arguments:\n"
2722 "-D                get the standard inquiry data\n"
2723 "-S                get the serial number\n"
2724 "-R                get the transfer rate, etc.\n"
2725 "cmd arguments:\n"
2726 "-c cdb [args]     specify the SCSI CDB\n"
2727 "-i len fmt        specify input data and input data format\n"
2728 "-o len fmt [args] specify output data and output data fmt\n"
2729 "debug arguments:\n"
2730 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
2731 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
2732 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
2733 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
2734 "tags arguments:\n"
2735 "-N tags           specify the number of tags to use for this device\n"
2736 "-q                be quiet, don't report the number of tags\n"
2737 "-v                report a number of tag-related parameters\n"
2738 "negotiate arguments:\n"
2739 "-a                send a test unit ready after negotiation\n"
2740 "-c                report/set current negotiation settings\n"
2741 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
2742 "-O offset         set command delay offset\n"
2743 "-q                be quiet, don't report anything\n"
2744 "-R syncrate       synchronization rate in MHz\n"
2745 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
2746 "-U                report/set user negotiation settings\n"
2747 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
2748 "-v                also print a Path Inquiry CCB for the controller\n",
2749 DEFAULT_DEVICE, DEFAULT_UNIT);
2750 }
2751 
2752 int
2753 main(int argc, char **argv)
2754 {
2755 	int c;
2756 	char *device = NULL;
2757 	int unit = 0;
2758 	struct cam_device *cam_dev = NULL;
2759 	int timeout = 0, retry_count = 1;
2760 	camcontrol_optret optreturn;
2761 	char *tstr;
2762 	char *mainopt = "C:En:t:u:v";
2763 	char *subopt = NULL;
2764 	char combinedopt[256];
2765 	int error = 0, optstart = 2;
2766 	int devopen = 1;
2767 
2768 	arglist = CAM_ARG_NONE;
2769 
2770 	if (argc < 2) {
2771 		usage(0);
2772 		exit(1);
2773 	}
2774 
2775 	/*
2776 	 * Get the base option.
2777 	 */
2778 	optreturn = getoption(argv[1], &arglist, &subopt);
2779 
2780 	if (optreturn == CC_OR_AMBIGUOUS) {
2781 		warnx("ambiguous option %s", argv[1]);
2782 		usage(0);
2783 		exit(1);
2784 	} else if (optreturn == CC_OR_NOT_FOUND) {
2785 		warnx("option %s not found", argv[1]);
2786 		usage(0);
2787 		exit(1);
2788 	}
2789 
2790 	/*
2791 	 * Ahh, getopt(3) is a pain.
2792 	 *
2793 	 * This is a gross hack.  There really aren't many other good
2794 	 * options (excuse the pun) for parsing options in a situation like
2795 	 * this.  getopt is kinda braindead, so you end up having to run
2796 	 * through the options twice, and give each invocation of getopt
2797 	 * the option string for the other invocation.
2798 	 *
2799 	 * You would think that you could just have two groups of options.
2800 	 * The first group would get parsed by the first invocation of
2801 	 * getopt, and the second group would get parsed by the second
2802 	 * invocation of getopt.  It doesn't quite work out that way.  When
2803 	 * the first invocation of getopt finishes, it leaves optind pointing
2804 	 * to the argument _after_ the first argument in the second group.
2805 	 * So when the second invocation of getopt comes around, it doesn't
2806 	 * recognize the first argument it gets and then bails out.
2807 	 *
2808 	 * A nice alternative would be to have a flag for getopt that says
2809 	 * "just keep parsing arguments even when you encounter an unknown
2810 	 * argument", but there isn't one.  So there's no real clean way to
2811 	 * easily parse two sets of arguments without having one invocation
2812 	 * of getopt know about the other.
2813 	 *
2814 	 * Without this hack, the first invocation of getopt would work as
2815 	 * long as the generic arguments are first, but the second invocation
2816 	 * (in the subfunction) would fail in one of two ways.  In the case
2817 	 * where you don't set optreset, it would fail because optind may be
2818 	 * pointing to the argument after the one it should be pointing at.
2819 	 * In the case where you do set optreset, and reset optind, it would
2820 	 * fail because getopt would run into the first set of options, which
2821 	 * it doesn't understand.
2822 	 *
2823 	 * All of this would "sort of" work if you could somehow figure out
2824 	 * whether optind had been incremented one option too far.  The
2825 	 * mechanics of that, however, are more daunting than just giving
2826 	 * both invocations all of the expect options for either invocation.
2827 	 *
2828 	 * Needless to say, I wouldn't mind if someone invented a better
2829 	 * (non-GPL!) command line parsing interface than getopt.  I
2830 	 * wouldn't mind if someone added more knobs to getopt to make it
2831 	 * work better.  Who knows, I may talk myself into doing it someday,
2832 	 * if the standards weenies let me.  As it is, it just leads to
2833 	 * hackery like this and causes people to avoid it in some cases.
2834 	 *
2835 	 * KDM, September 8th, 1998
2836 	 */
2837 	if (subopt != NULL)
2838 		sprintf(combinedopt, "%s%s", mainopt, subopt);
2839 	else
2840 		sprintf(combinedopt, "%s", mainopt);
2841 
2842 	/*
2843 	 * For these options we do not parse optional device arguments and
2844 	 * we do not open a passthrough device.
2845 	 */
2846 	if (((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESCAN)
2847 	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESET)
2848 	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEVTREE)
2849 	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_USAGE)
2850 	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEBUG))
2851 		devopen = 0;
2852 
2853 	if ((devopen == 1)
2854 	 && (argc > 2 && argv[2][0] != '-')) {
2855 		char name[30];
2856 		int rv;
2857 
2858 		/*
2859 		 * First catch people who try to do things like:
2860 		 * camcontrol tur /dev/rsd0.ctl
2861 		 * camcontrol doesn't take device nodes as arguments.
2862 		 */
2863 		if (argv[2][0] == '/') {
2864 			warnx("%s is not a valid device identifier", argv[2]);
2865 			errx(1, "please read the camcontrol(8) man page");
2866 		} else if (isdigit(argv[2][0])) {
2867 			/* device specified as bus:target[:lun] */
2868 			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
2869 			if (rv < 2)
2870 				errx(1, "numeric device specification must "
2871 				     "be either bus:target, or "
2872 				     "bus:target:lun");
2873 			optstart++;
2874 		} else {
2875 			if (cam_get_device(argv[2], name, sizeof name, &unit)
2876 			    == -1)
2877 				errx(1, "%s", cam_errbuf);
2878 			device = strdup(name);
2879 			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
2880 			optstart++;
2881 		}
2882 	}
2883 	/*
2884 	 * Start getopt processing at argv[2/3], since we've already
2885 	 * accepted argv[1..2] as the command name, and as a possible
2886 	 * device name.
2887 	 */
2888 	optind = optstart;
2889 
2890 	/*
2891 	 * Now we run through the argument list looking for generic
2892 	 * options, and ignoring options that possibly belong to
2893 	 * subfunctions.
2894 	 */
2895 	while ((c = getopt(argc, argv, combinedopt))!= -1){
2896 		switch(c) {
2897 			case 'C':
2898 				retry_count = strtol(optarg, NULL, 0);
2899 				if (retry_count < 0)
2900 					errx(1, "retry count %d is < 0",
2901 					     retry_count);
2902 				arglist |= CAM_ARG_RETRIES;
2903 				break;
2904 			case 'E':
2905 				arglist |= CAM_ARG_ERR_RECOVER;
2906 				break;
2907 			case 'n':
2908 				arglist |= CAM_ARG_DEVICE;
2909 				tstr = optarg;
2910 				while (isspace(*tstr) && (*tstr != '\0'))
2911 					tstr++;
2912 				device = (char *)strdup(tstr);
2913 				break;
2914 			case 't':
2915 				timeout = strtol(optarg, NULL, 0);
2916 				if (timeout < 0)
2917 					errx(1, "invalid timeout %d", timeout);
2918 				/* Convert the timeout from seconds to ms */
2919 				timeout *= 1000;
2920 				arglist |= CAM_ARG_TIMEOUT;
2921 				break;
2922 			case 'u':
2923 				arglist |= CAM_ARG_UNIT;
2924 				unit = strtol(optarg, NULL, 0);
2925 				break;
2926 			case 'v':
2927 				arglist |= CAM_ARG_VERBOSE;
2928 				break;
2929 			default:
2930 				break;
2931 		}
2932 	}
2933 
2934 	if ((arglist & CAM_ARG_DEVICE) == 0)
2935 		device = (char *)strdup(DEFAULT_DEVICE);
2936 
2937 	if ((arglist & CAM_ARG_UNIT) == 0)
2938 		unit = DEFAULT_UNIT;
2939 
2940 	/*
2941 	 * For most commands we'll want to open the passthrough device
2942 	 * associated with the specified device.  In the case of the rescan
2943 	 * commands, we don't use a passthrough device at all, just the
2944 	 * transport layer device.
2945 	 */
2946 	if (devopen == 1) {
2947 		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
2948 				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
2949 				cam_open_spec_device(device,unit,O_RDWR,NULL)))
2950 		     == NULL)
2951 			errx(1,"%s", cam_errbuf);
2952 	}
2953 
2954 	/*
2955 	 * Reset optind to 2, and reset getopt, so these routines can parse
2956 	 * the arguments again.
2957 	 */
2958 	optind = optstart;
2959 	optreset = 1;
2960 
2961 	switch(arglist & CAM_ARG_OPT_MASK) {
2962 		case CAM_ARG_DEVLIST:
2963 			error = getdevlist(cam_dev);
2964 			break;
2965 		case CAM_ARG_DEVTREE:
2966 			error = getdevtree();
2967 			break;
2968 		case CAM_ARG_TUR:
2969 			error = testunitready(cam_dev, retry_count, timeout, 0);
2970 			break;
2971 		case CAM_ARG_INQUIRY:
2972 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
2973 					      retry_count, timeout);
2974 			break;
2975 		case CAM_ARG_STARTSTOP:
2976 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
2977 					  arglist & CAM_ARG_EJECT, retry_count,
2978 					  timeout);
2979 			break;
2980 		case CAM_ARG_RESCAN:
2981 			error = dorescan_or_reset(argc, argv, 1);
2982 			break;
2983 		case CAM_ARG_RESET:
2984 			error = dorescan_or_reset(argc, argv, 0);
2985 			break;
2986 		case CAM_ARG_READ_DEFECTS:
2987 			error = readdefects(cam_dev, argc, argv, combinedopt,
2988 					    retry_count, timeout);
2989 			break;
2990 		case CAM_ARG_MODE_PAGE:
2991 			modepage(cam_dev, argc, argv, combinedopt,
2992 				 retry_count, timeout);
2993 			break;
2994 		case CAM_ARG_SCSI_CMD:
2995 			error = scsicmd(cam_dev, argc, argv, combinedopt,
2996 					retry_count, timeout);
2997 			break;
2998 		case CAM_ARG_DEBUG:
2999 			error = camdebug(argc, argv, combinedopt);
3000 			break;
3001 		case CAM_ARG_TAG:
3002 			error = tagcontrol(cam_dev, argc, argv, combinedopt);
3003 			break;
3004 		case CAM_ARG_RATE:
3005 			error = ratecontrol(cam_dev, retry_count, timeout,
3006 					    argc, argv, combinedopt);
3007 			break;
3008 		case CAM_ARG_USAGE:
3009 			usage(1);
3010 			break;
3011 		default:
3012 			usage(0);
3013 			error = 1;
3014 			break;
3015 	}
3016 
3017 	if (cam_dev != NULL)
3018 		cam_close_device(cam_dev);
3019 
3020 	exit(error);
3021 }
3022