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