camcontrol.c revision 62361
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 62361 2000-07-01 21:28:49Z n_hibma $
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
51typedef enum {
52	CAM_ARG_NONE		= 0x00000000,
53	CAM_ARG_DEVLIST		= 0x00000001,
54	CAM_ARG_TUR		= 0x00000002,
55	CAM_ARG_INQUIRY		= 0x00000003,
56	CAM_ARG_STARTSTOP	= 0x00000004,
57	CAM_ARG_RESCAN		= 0x00000005,
58	CAM_ARG_READ_DEFECTS	= 0x00000006,
59	CAM_ARG_MODE_PAGE	= 0x00000007,
60	CAM_ARG_SCSI_CMD	= 0x00000008,
61	CAM_ARG_DEVTREE		= 0x00000009,
62	CAM_ARG_USAGE		= 0x0000000a,
63	CAM_ARG_DEBUG		= 0x0000000b,
64	CAM_ARG_RESET		= 0x0000000c,
65	CAM_ARG_FORMAT		= 0x0000000d,
66	CAM_ARG_TAG		= 0x0000000e,
67	CAM_ARG_RATE		= 0x0000000f,
68	CAM_ARG_OPT_MASK	= 0x0000000f,
69	CAM_ARG_VERBOSE		= 0x00000010,
70	CAM_ARG_DEVICE		= 0x00000020,
71	CAM_ARG_BUS		= 0x00000040,
72	CAM_ARG_TARGET		= 0x00000080,
73	CAM_ARG_LUN		= 0x00000100,
74	CAM_ARG_EJECT		= 0x00000200,
75	CAM_ARG_UNIT		= 0x00000400,
76	CAM_ARG_FORMAT_BLOCK	= 0x00000800,
77	CAM_ARG_FORMAT_BFI	= 0x00001000,
78	CAM_ARG_FORMAT_PHYS	= 0x00002000,
79	CAM_ARG_PLIST		= 0x00004000,
80	CAM_ARG_GLIST		= 0x00008000,
81	CAM_ARG_GET_SERIAL	= 0x00010000,
82	CAM_ARG_GET_STDINQ	= 0x00020000,
83	CAM_ARG_GET_XFERRATE	= 0x00040000,
84	CAM_ARG_INQ_MASK	= 0x00070000,
85	CAM_ARG_MODE_EDIT	= 0x00080000,
86	CAM_ARG_PAGE_CNTL	= 0x00100000,
87	CAM_ARG_TIMEOUT		= 0x00200000,
88	CAM_ARG_CMD_IN		= 0x00400000,
89	CAM_ARG_CMD_OUT		= 0x00800000,
90	CAM_ARG_DBD		= 0x01000000,
91	CAM_ARG_ERR_RECOVER	= 0x02000000,
92	CAM_ARG_RETRIES		= 0x04000000,
93	CAM_ARG_START_UNIT	= 0x08000000,
94	CAM_ARG_DEBUG_INFO	= 0x10000000,
95	CAM_ARG_DEBUG_TRACE	= 0x20000000,
96	CAM_ARG_DEBUG_SUBTRACE	= 0x40000000,
97	CAM_ARG_DEBUG_CDB	= 0x80000000,
98	CAM_ARG_FLAG_MASK	= 0xfffffff0
99} cam_argmask;
100
101struct camcontrol_opts {
102	char 		*optname;
103	cam_argmask	argnum;
104	const char	*subopt;
105};
106
107extern int optreset;
108
109static const char scsicmd_opts[] = "c:i:o:";
110static const char readdefect_opts[] = "f:GP";
111static const char negotiate_opts[] = "acD:O:qR:T:UW:";
112
113struct camcontrol_opts option_table[] = {
114	{"tur", CAM_ARG_TUR, NULL},
115	{"inquiry", CAM_ARG_INQUIRY, "DSR"},
116	{"start", CAM_ARG_STARTSTOP | CAM_ARG_START_UNIT, NULL},
117	{"stop", CAM_ARG_STARTSTOP, NULL},
118	{"eject", CAM_ARG_STARTSTOP | CAM_ARG_EJECT, NULL},
119	{"rescan", CAM_ARG_RESCAN, NULL},
120	{"reset", CAM_ARG_RESET, NULL},
121	{"cmd", CAM_ARG_SCSI_CMD, scsicmd_opts},
122	{"command", CAM_ARG_SCSI_CMD, scsicmd_opts},
123	{"defects", CAM_ARG_READ_DEFECTS, readdefect_opts},
124	{"defectlist", CAM_ARG_READ_DEFECTS, readdefect_opts},
125	{"devlist", CAM_ARG_DEVTREE, NULL},
126	{"periphlist", CAM_ARG_DEVLIST, NULL},
127	{"modepage", CAM_ARG_MODE_PAGE, "dem:P:"},
128	{"tags", CAM_ARG_TAG, "N:q"},
129	{"negotiate", CAM_ARG_RATE, negotiate_opts},
130	{"rate", CAM_ARG_RATE, negotiate_opts},
131	{"debug", CAM_ARG_DEBUG, "ITSc"},
132	{"format", CAM_ARG_FORMAT, "qwy"},
133	{"help", CAM_ARG_USAGE, NULL},
134	{"-?", CAM_ARG_USAGE, NULL},
135	{"-h", CAM_ARG_USAGE, NULL},
136	{NULL, 0, NULL}
137};
138
139typedef enum {
140	CC_OR_NOT_FOUND,
141	CC_OR_AMBIGUOUS,
142	CC_OR_FOUND
143} camcontrol_optret;
144
145cam_argmask arglist;
146int bus, target, lun;
147
148
149camcontrol_optret getoption(char *arg, cam_argmask *argnum, char **subopt);
150static int getdevlist(struct cam_device *device);
151static int getdevtree(void);
152static int testunitready(struct cam_device *device, int retry_count,
153			 int timeout, int quiet);
154static int scsistart(struct cam_device *device, int startstop, int loadeject,
155		     int retry_count, int timeout);
156static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
157			 char *combinedopt, int retry_count, int timeout);
158static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
159static int scsiserial(struct cam_device *device, int retry_count, int timeout);
160static int scsixferrate(struct cam_device *device);
161static int parse_btl(char *tstr, int *bus, int *target, int *lun,
162		     cam_argmask *arglist);
163static int dorescan_or_reset(int argc, char **argv, int rescan);
164static int rescan_or_reset_bus(int bus, int rescan);
165static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
166static int readdefects(struct cam_device *device, int argc, char **argv,
167		       char *combinedopt, int retry_count, int timeout);
168static void modepage(struct cam_device *device, int argc, char **argv,
169		     char *combinedopt, int retry_count, int timeout);
170static int scsicmd(struct cam_device *device, int argc, char **argv,
171		   char *combinedopt, int retry_count, int timeout);
172static int tagcontrol(struct cam_device *device, int argc, char **argv,
173		      char *combinedopt);
174static void cts_print(struct cam_device *device,
175		      struct ccb_trans_settings *cts);
176static void cpi_print(struct ccb_pathinq *cpi);
177static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
178static int get_print_cts(struct cam_device *device, int user_settings,
179			 int quiet, struct ccb_trans_settings *cts);
180static int ratecontrol(struct cam_device *device, int retry_count,
181		       int timeout, int argc, char **argv, char *combinedopt);
182static int scsiformat(struct cam_device *device, int argc, char **argv,
183		      char *combinedopt, int retry_count, int timeout);
184
185camcontrol_optret
186getoption(char *arg, cam_argmask *argnum, char **subopt)
187{
188	struct camcontrol_opts *opts;
189	int num_matches = 0;
190
191	for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
192	     opts++) {
193		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
194			*argnum = opts->argnum;
195			*subopt = (char *)opts->subopt;
196			if (++num_matches > 1)
197				return(CC_OR_AMBIGUOUS);
198		}
199	}
200
201	if (num_matches > 0)
202		return(CC_OR_FOUND);
203	else
204		return(CC_OR_NOT_FOUND);
205}
206
207static int
208getdevlist(struct cam_device *device)
209{
210	union ccb *ccb;
211	char status[32];
212	int error = 0;
213
214	ccb = cam_getccb(device);
215
216	ccb->ccb_h.func_code = XPT_GDEVLIST;
217	ccb->ccb_h.flags = CAM_DIR_NONE;
218	ccb->ccb_h.retry_count = 1;
219	ccb->cgdl.index = 0;
220	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
221	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
222		if (cam_send_ccb(device, ccb) < 0) {
223			perror("error getting device list");
224			cam_freeccb(ccb);
225			return(1);
226		}
227
228		status[0] = '\0';
229
230		switch (ccb->cgdl.status) {
231			case CAM_GDEVLIST_MORE_DEVS:
232				strcpy(status, "MORE");
233				break;
234			case CAM_GDEVLIST_LAST_DEVICE:
235				strcpy(status, "LAST");
236				break;
237			case CAM_GDEVLIST_LIST_CHANGED:
238				strcpy(status, "CHANGED");
239				break;
240			case CAM_GDEVLIST_ERROR:
241				strcpy(status, "ERROR");
242				error = 1;
243				break;
244		}
245
246		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
247			ccb->cgdl.periph_name,
248			ccb->cgdl.unit_number,
249			ccb->cgdl.generation,
250			ccb->cgdl.index,
251			status);
252
253		/*
254		 * If the list has changed, we need to start over from the
255		 * beginning.
256		 */
257		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
258			ccb->cgdl.index = 0;
259	}
260
261	cam_freeccb(ccb);
262
263	return(error);
264}
265
266static int
267getdevtree(void)
268{
269	union ccb ccb;
270	int bufsize, i, fd;
271	int need_close = 0;
272	int error = 0;
273	int skip_device = 0;
274
275	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
276		warn("couldn't open %s", XPT_DEVICE);
277		return(1);
278	}
279
280	bzero(&(&ccb.ccb_h)[1],
281	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
282
283	ccb.ccb_h.func_code = XPT_DEV_MATCH;
284	bufsize = sizeof(struct dev_match_result) * 100;
285	ccb.cdm.match_buf_len = bufsize;
286	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
287	ccb.cdm.num_matches = 0;
288
289	/*
290	 * We fetch all nodes, since we display most of them in the default
291	 * case, and all in the verbose case.
292	 */
293	ccb.cdm.num_patterns = 0;
294	ccb.cdm.pattern_buf_len = 0;
295
296	/*
297	 * We do the ioctl multiple times if necessary, in case there are
298	 * more than 100 nodes in the EDT.
299	 */
300	do {
301		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
302			warn("error sending CAMIOCOMMAND ioctl");
303			error = 1;
304			break;
305		}
306
307		if ((ccb.ccb_h.status != CAM_REQ_CMP)
308		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
309		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
310			fprintf(stderr, "got CAM error %#x, CDM error %d\n",
311				ccb.ccb_h.status, ccb.cdm.status);
312			error = 1;
313			break;
314		}
315
316		for (i = 0; i < ccb.cdm.num_matches; i++) {
317			switch(ccb.cdm.matches[i].type) {
318			case DEV_MATCH_BUS: {
319				struct bus_match_result *bus_result;
320
321				/*
322				 * Only print the bus information if the
323				 * user turns on the verbose flag.
324				 */
325				if ((arglist & CAM_ARG_VERBOSE) == 0)
326					break;
327
328				bus_result =
329					&ccb.cdm.matches[i].result.bus_result;
330
331				if (need_close) {
332					fprintf(stdout, ")\n");
333					need_close = 0;
334				}
335
336				fprintf(stdout, "scbus%d on %s%d bus %d:\n",
337					bus_result->path_id,
338					bus_result->dev_name,
339					bus_result->unit_number,
340					bus_result->bus_id);
341				break;
342			}
343			case DEV_MATCH_DEVICE: {
344				struct device_match_result *dev_result;
345				char vendor[16], product[48], revision[16];
346				char tmpstr[256];
347
348				dev_result =
349				     &ccb.cdm.matches[i].result.device_result;
350
351				if ((dev_result->flags
352				     & DEV_RESULT_UNCONFIGURED)
353				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
354					skip_device = 1;
355					break;
356				} else
357					skip_device = 0;
358
359				cam_strvis(vendor, dev_result->inq_data.vendor,
360					   sizeof(dev_result->inq_data.vendor),
361					   sizeof(vendor));
362				cam_strvis(product,
363					   dev_result->inq_data.product,
364					   sizeof(dev_result->inq_data.product),
365					   sizeof(product));
366				cam_strvis(revision,
367					   dev_result->inq_data.revision,
368					  sizeof(dev_result->inq_data.revision),
369					   sizeof(revision));
370				sprintf(tmpstr, "<%s %s %s>", vendor, product,
371					revision);
372				if (need_close) {
373					fprintf(stdout, ")\n");
374					need_close = 0;
375				}
376
377				fprintf(stdout, "%-33s  at scbus%d "
378					"target %d lun %d (",
379					tmpstr,
380					dev_result->path_id,
381					dev_result->target_id,
382					dev_result->target_lun);
383
384				need_close = 1;
385
386				break;
387			}
388			case DEV_MATCH_PERIPH: {
389				struct periph_match_result *periph_result;
390
391				periph_result =
392				      &ccb.cdm.matches[i].result.periph_result;
393
394				if (skip_device != 0)
395					break;
396
397				if (need_close > 1)
398					fprintf(stdout, ",");
399
400				fprintf(stdout, "%s%d",
401					periph_result->periph_name,
402					periph_result->unit_number);
403
404				need_close++;
405				break;
406			}
407			default:
408				fprintf(stdout, "unknown match type\n");
409				break;
410			}
411		}
412
413	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
414		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
415
416	if (need_close)
417		fprintf(stdout, ")\n");
418
419	close(fd);
420
421	return(error);
422}
423
424static int
425testunitready(struct cam_device *device, int retry_count, int timeout,
426	      int quiet)
427{
428	int error = 0;
429	union ccb *ccb;
430
431	ccb = cam_getccb(device);
432
433	scsi_test_unit_ready(&ccb->csio,
434			     /* retries */ retry_count,
435			     /* cbfcnp */ NULL,
436			     /* tag_action */ MSG_SIMPLE_Q_TAG,
437			     /* sense_len */ SSD_FULL_SIZE,
438			     /* timeout */ timeout ? timeout : 5000);
439
440	/* Disable freezing the device queue */
441	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
442
443	if (arglist & CAM_ARG_ERR_RECOVER)
444		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
445
446	if (cam_send_ccb(device, ccb) < 0) {
447		if (quiet == 0)
448			perror("error sending test unit ready");
449
450		if (arglist & CAM_ARG_VERBOSE) {
451		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
452			    CAM_SCSI_STATUS_ERROR)
453				scsi_sense_print(device, &ccb->csio, stderr);
454			else
455				fprintf(stderr, "CAM status is %#x\n",
456					ccb->ccb_h.status);
457		}
458
459		cam_freeccb(ccb);
460		return(1);
461	}
462
463	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
464		if (quiet == 0)
465			fprintf(stdout, "Unit is ready\n");
466	} else {
467		if (quiet == 0)
468			fprintf(stdout, "Unit is not ready\n");
469		error = 1;
470
471		if (arglist & CAM_ARG_VERBOSE) {
472		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
473			    CAM_SCSI_STATUS_ERROR)
474				scsi_sense_print(device, &ccb->csio, stderr);
475			else
476				fprintf(stderr, "CAM status is %#x\n",
477					ccb->ccb_h.status);
478		}
479	}
480
481	cam_freeccb(ccb);
482
483	return(error);
484}
485
486static int
487scsistart(struct cam_device *device, int startstop, int loadeject,
488	  int retry_count, int timeout)
489{
490	union ccb *ccb;
491	int error = 0;
492
493	ccb = cam_getccb(device);
494
495	/*
496	 * If we're stopping, send an ordered tag so the drive in question
497	 * will finish any previously queued writes before stopping.  If
498	 * the device isn't capable of tagged queueing, or if tagged
499	 * queueing is turned off, the tag action is a no-op.
500	 */
501	scsi_start_stop(&ccb->csio,
502			/* retries */ retry_count,
503			/* cbfcnp */ NULL,
504			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
505						     MSG_ORDERED_Q_TAG,
506			/* start/stop */ startstop,
507			/* load_eject */ loadeject,
508			/* immediate */ 0,
509			/* sense_len */ SSD_FULL_SIZE,
510			/* timeout */ timeout ? timeout : 120000);
511
512	/* Disable freezing the device queue */
513	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
514
515	if (arglist & CAM_ARG_ERR_RECOVER)
516		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
517
518	if (cam_send_ccb(device, ccb) < 0) {
519		perror("error sending start unit");
520
521		if (arglist & CAM_ARG_VERBOSE) {
522		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
523			    CAM_SCSI_STATUS_ERROR)
524				scsi_sense_print(device, &ccb->csio, stderr);
525			else
526				fprintf(stderr, "CAM status is %#x\n",
527					ccb->ccb_h.status);
528		}
529
530		cam_freeccb(ccb);
531		return(1);
532	}
533
534	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
535		if (startstop) {
536			fprintf(stdout, "Unit started successfully");
537			if (loadeject)
538				fprintf(stdout,", Media loaded\n");
539			else
540				fprintf(stdout,"\n");
541		} else {
542			fprintf(stdout, "Unit stopped successfully");
543			if (loadeject)
544				fprintf(stdout, ", Media ejected\n");
545			else
546				fprintf(stdout, "\n");
547		}
548	else {
549		error = 1;
550		if (startstop)
551			fprintf(stdout,
552				"Error received from start unit command\n");
553		else
554			fprintf(stdout,
555				"Error received from stop unit command\n");
556
557		if (arglist & CAM_ARG_VERBOSE) {
558		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
559			    CAM_SCSI_STATUS_ERROR)
560				scsi_sense_print(device, &ccb->csio, stderr);
561			else
562				fprintf(stderr, "CAM status is %#x\n",
563					ccb->ccb_h.status);
564		}
565	}
566
567	cam_freeccb(ccb);
568
569	return(error);
570}
571
572static int
573scsidoinquiry(struct cam_device *device, int argc, char **argv,
574	      char *combinedopt, int retry_count, int timeout)
575{
576	int c;
577	int error = 0;
578
579	while ((c = getopt(argc, argv, combinedopt)) != -1) {
580		switch(c) {
581		case 'D':
582			arglist |= CAM_ARG_GET_STDINQ;
583			break;
584		case 'R':
585			arglist |= CAM_ARG_GET_XFERRATE;
586			break;
587		case 'S':
588			arglist |= CAM_ARG_GET_SERIAL;
589			break;
590		default:
591			break;
592		}
593	}
594
595	/*
596	 * If the user didn't specify any inquiry options, he wants all of
597	 * them.
598	 */
599	if ((arglist & CAM_ARG_INQ_MASK) == 0)
600		arglist |= CAM_ARG_INQ_MASK;
601
602	if (arglist & CAM_ARG_GET_STDINQ)
603		error = scsiinquiry(device, retry_count, timeout);
604
605	if (error != 0)
606		return(error);
607
608	if (arglist & CAM_ARG_GET_SERIAL)
609		scsiserial(device, retry_count, timeout);
610
611	if (error != 0)
612		return(error);
613
614	if (arglist & CAM_ARG_GET_XFERRATE)
615		error = scsixferrate(device);
616
617	return(error);
618}
619
620static int
621scsiinquiry(struct cam_device *device, int retry_count, int timeout)
622{
623	union ccb *ccb;
624	struct scsi_inquiry_data *inq_buf;
625	int error = 0;
626
627	ccb = cam_getccb(device);
628
629	if (ccb == NULL) {
630		warnx("couldn't allocate CCB");
631		return(1);
632	}
633
634	/* cam_getccb cleans up the header, caller has to zero the payload */
635	bzero(&(&ccb->ccb_h)[1],
636	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
637
638	inq_buf = (struct scsi_inquiry_data *)malloc(
639		sizeof(struct scsi_inquiry_data));
640
641	if (inq_buf == NULL) {
642		cam_freeccb(ccb);
643		warnx("can't malloc memory for inquiry\n");
644		return(1);
645	}
646	bzero(inq_buf, sizeof(*inq_buf));
647
648	/*
649	 * Note that although the size of the inquiry buffer is the full
650	 * 256 bytes specified in the SCSI spec, we only tell the device
651	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
652	 * two reasons for this:
653	 *
654	 *  - The SCSI spec says that when a length field is only 1 byte,
655	 *    a value of 0 will be interpreted as 256.  Therefore
656	 *    scsi_inquiry() will convert an inq_len (which is passed in as
657	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
658	 *    to 0.  Evidently, very few devices meet the spec in that
659	 *    regard.  Some devices, like many Seagate disks, take the 0 as
660	 *    0, and don't return any data.  One Pioneer DVD-R drive
661	 *    returns more data than the command asked for.
662	 *
663	 *    So, since there are numerous devices that just don't work
664	 *    right with the full inquiry size, we don't send the full size.
665	 *
666	 *  - The second reason not to use the full inquiry data length is
667	 *    that we don't need it here.  The only reason we issue a
668	 *    standard inquiry is to get the vendor name, device name,
669	 *    and revision so scsi_print_inquiry() can print them.
670	 *
671	 * If, at some point in the future, more inquiry data is needed for
672	 * some reason, this code should use a procedure similar to the
673	 * probe code.  i.e., issue a short inquiry, and determine from
674	 * the additional length passed back from the device how much
675	 * inquiry data the device supports.  Once the amount the device
676	 * supports is determined, issue an inquiry for that amount and no
677	 * more.
678	 *
679	 * KDM, 2/18/2000
680	 */
681	scsi_inquiry(&ccb->csio,
682		     /* retries */ retry_count,
683		     /* cbfcnp */ NULL,
684		     /* tag_action */ MSG_SIMPLE_Q_TAG,
685		     /* inq_buf */ (u_int8_t *)inq_buf,
686		     /* inq_len */ SHORT_INQUIRY_LENGTH,
687		     /* evpd */ 0,
688		     /* page_code */ 0,
689		     /* sense_len */ SSD_FULL_SIZE,
690		     /* timeout */ timeout ? timeout : 5000);
691
692	/* Disable freezing the device queue */
693	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
694
695	if (arglist & CAM_ARG_ERR_RECOVER)
696		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
697
698	if (cam_send_ccb(device, ccb) < 0) {
699		perror("error sending SCSI inquiry");
700
701		if (arglist & CAM_ARG_VERBOSE) {
702		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
703			    CAM_SCSI_STATUS_ERROR)
704				scsi_sense_print(device, &ccb->csio, stderr);
705			else
706				fprintf(stderr, "CAM status is %#x\n",
707					ccb->ccb_h.status);
708		}
709
710		cam_freeccb(ccb);
711		return(1);
712	}
713
714	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
715		error = 1;
716
717		if (arglist & CAM_ARG_VERBOSE) {
718		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
719			    CAM_SCSI_STATUS_ERROR)
720				scsi_sense_print(device, &ccb->csio, stderr);
721			else
722				fprintf(stderr, "CAM status is %#x\n",
723					ccb->ccb_h.status);
724		}
725	}
726
727	cam_freeccb(ccb);
728
729	if (error != 0) {
730		free(inq_buf);
731		return(error);
732	}
733
734	fprintf(stdout, "%s%d: ", device->device_name,
735		device->dev_unit_num);
736	scsi_print_inquiry(inq_buf);
737
738	free(inq_buf);
739
740	return(0);
741}
742
743static int
744scsiserial(struct cam_device *device, int retry_count, int timeout)
745{
746	union ccb *ccb;
747	struct scsi_vpd_unit_serial_number *serial_buf;
748	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
749	int error = 0;
750
751	ccb = cam_getccb(device);
752
753	if (ccb == NULL) {
754		warnx("couldn't allocate CCB");
755		return(1);
756	}
757
758	/* cam_getccb cleans up the header, caller has to zero the payload */
759	bzero(&(&ccb->ccb_h)[1],
760	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
761
762	serial_buf = (struct scsi_vpd_unit_serial_number *)
763		malloc(sizeof(*serial_buf));
764
765	if (serial_buf == NULL) {
766		cam_freeccb(ccb);
767		warnx("can't malloc memory for serial number");
768		return(1);
769	}
770
771	scsi_inquiry(&ccb->csio,
772		     /*retries*/ retry_count,
773		     /*cbfcnp*/ NULL,
774		     /* tag_action */ MSG_SIMPLE_Q_TAG,
775		     /* inq_buf */ (u_int8_t *)serial_buf,
776		     /* inq_len */ sizeof(*serial_buf),
777		     /* evpd */ 1,
778		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
779		     /* sense_len */ SSD_FULL_SIZE,
780		     /* timeout */ timeout ? timeout : 5000);
781
782	/* Disable freezing the device queue */
783	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
784
785	if (arglist & CAM_ARG_ERR_RECOVER)
786		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
787
788	if (cam_send_ccb(device, ccb) < 0) {
789		warn("error getting serial number");
790
791		if (arglist & CAM_ARG_VERBOSE) {
792		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
793			    CAM_SCSI_STATUS_ERROR)
794				scsi_sense_print(device, &ccb->csio, stderr);
795			else
796				fprintf(stderr, "CAM status is %#x\n",
797					ccb->ccb_h.status);
798		}
799
800		cam_freeccb(ccb);
801		free(serial_buf);
802		return(1);
803	}
804
805	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
806		error = 1;
807
808		if (arglist & CAM_ARG_VERBOSE) {
809		 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
810			    CAM_SCSI_STATUS_ERROR)
811				scsi_sense_print(device, &ccb->csio, stderr);
812			else
813				fprintf(stderr, "CAM status is %#x\n",
814					ccb->ccb_h.status);
815		}
816	}
817
818	cam_freeccb(ccb);
819
820	if (error != 0) {
821		free(serial_buf);
822		return(error);
823	}
824
825	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
826	serial_num[serial_buf->length] = '\0';
827
828	if ((arglist & CAM_ARG_GET_STDINQ)
829	 || (arglist & CAM_ARG_GET_XFERRATE))
830		fprintf(stdout, "%s%d: Serial Number ",
831			device->device_name, device->dev_unit_num);
832
833	fprintf(stdout, "%.60s\n", serial_num);
834
835	free(serial_buf);
836
837	return(0);
838}
839
840static int
841scsixferrate(struct cam_device *device)
842{
843	u_int32_t freq;
844	u_int32_t speed;
845	union ccb *ccb;
846	u_int mb;
847	int retval = 0;
848
849	ccb = cam_getccb(device);
850
851	if (ccb == NULL) {
852		warnx("couldn't allocate CCB");
853		return(1);
854	}
855
856	bzero(&(&ccb->ccb_h)[1],
857	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
858
859	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
860	ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
861
862	if (((retval = cam_send_ccb(device, ccb)) < 0)
863	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
864		char *error_string = "error getting transfer settings";
865
866		if (retval < 0)
867			warn(error_string);
868		else
869			warnx(error_string);
870
871		/*
872		 * If there is an error, it won't be a SCSI error since
873		 * this isn't a SCSI CCB.
874		 */
875		if (arglist & CAM_ARG_VERBOSE)
876			fprintf(stderr, "CAM status is %#x\n",
877				ccb->ccb_h.status);
878
879		retval = 1;
880
881		goto xferrate_bailout;
882
883	}
884
885	if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
886	 && (ccb->cts.sync_offset != 0)) {
887		freq = scsi_calc_syncsrate(ccb->cts.sync_period);
888		speed = freq;
889	} else {
890		struct ccb_pathinq cpi;
891
892		retval = get_cpi(device, &cpi);
893
894		if (retval != 0)
895			goto xferrate_bailout;
896
897		speed = cpi.base_transfer_speed;
898		freq = 0;
899	}
900
901	fprintf(stdout, "%s%d: ", device->device_name,
902		device->dev_unit_num);
903
904	if ((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
905		speed *= (0x01 << device->bus_width);
906
907	mb = speed / 1000;
908
909	if (mb > 0)
910		fprintf(stdout, "%d.%03dMB/s transfers ",
911			mb, speed % 1000);
912	else
913		fprintf(stdout, "%dKB/s transfers ",
914			speed);
915
916	if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
917	 && (ccb->cts.sync_offset != 0))
918                fprintf(stdout, "(%d.%03dMHz, offset %d", freq / 1000,
919			freq % 1000, ccb->cts.sync_offset);
920
921	if (((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
922	 && (ccb->cts.bus_width > 0)) {
923		if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
924		 && (ccb->cts.sync_offset != 0)) {
925			fprintf(stdout, ", ");
926		} else {
927			fprintf(stdout, " (");
928		}
929		fprintf(stdout, "%dbit)", 8 * (0x01 << ccb->cts.bus_width));
930	} else if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
931		&& (ccb->cts.sync_offset != 0)) {
932		fprintf(stdout, ")");
933	}
934
935	if (((ccb->cts.valid & CCB_TRANS_TQ_VALID) != 0)
936	 && (ccb->cts.flags & CCB_TRANS_TAG_ENB))
937                fprintf(stdout, ", Tagged Queueing Enabled");
938
939        fprintf(stdout, "\n");
940
941xferrate_bailout:
942
943	cam_freeccb(ccb);
944
945	return(retval);
946}
947
948/*
949 * Parse out a bus, or a bus, target and lun in the following
950 * format:
951 * bus
952 * bus:target
953 * bus:target:lun
954 *
955 * Returns the number of parsed components, or 0.
956 */
957static int
958parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglist)
959{
960	char *tmpstr;
961	int convs = 0;
962
963	while (isspace(*tstr) && (*tstr != '\0'))
964		tstr++;
965
966	tmpstr = (char *)strtok(tstr, ":");
967	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
968		*bus = strtol(tmpstr, NULL, 0);
969		*arglist |= CAM_ARG_BUS;
970		convs++;
971		tmpstr = (char *)strtok(NULL, ":");
972		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
973			*target = strtol(tmpstr, NULL, 0);
974			*arglist |= CAM_ARG_TARGET;
975			convs++;
976			tmpstr = (char *)strtok(NULL, ":");
977			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
978				*lun = strtol(tmpstr, NULL, 0);
979				*arglist |= CAM_ARG_LUN;
980				convs++;
981			}
982		}
983	}
984
985	return convs;
986}
987
988static int
989dorescan_or_reset(int argc, char **argv, int rescan)
990{
991	static const char *must =
992		"you must specify a bus, or a bus:target:lun to %s";
993	int rv, error = 0;
994	int bus = -1, target = -1, lun = -1;
995
996	if (argc < 3) {
997		warnx(must, rescan? "rescan" : "reset");
998		return(1);
999	}
1000	rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1001	if (rv != 1 && rv != 3) {
1002		warnx(must, rescan? "rescan" : "reset");
1003		return(1);
1004	}
1005
1006	if ((arglist & CAM_ARG_BUS)
1007	    && (arglist & CAM_ARG_TARGET)
1008	    && (arglist & CAM_ARG_LUN))
1009		error = scanlun_or_reset_dev(bus, target, lun, rescan);
1010	else
1011		error = rescan_or_reset_bus(bus, rescan);
1012
1013	return(error);
1014}
1015
1016static int
1017rescan_or_reset_bus(int bus, int rescan)
1018{
1019	union ccb ccb;
1020	int fd;
1021
1022	if (bus < 0) {
1023		warnx("invalid bus number %d", bus);
1024		return(1);
1025	}
1026
1027	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1028		warnx("error opening tranport layer device %s", XPT_DEVICE);
1029		warn("%s", XPT_DEVICE);
1030		return(1);
1031	}
1032
1033	ccb.ccb_h.func_code = rescan? XPT_SCAN_BUS : XPT_RESET_BUS;
1034	ccb.ccb_h.path_id = bus;
1035	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1036	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1037	ccb.crcn.flags = CAM_FLAG_NONE;
1038
1039	/* run this at a low priority */
1040	ccb.ccb_h.pinfo.priority = 5;
1041
1042	if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1043		warn("CAMIOCOMMAND ioctl failed");
1044		close(fd);
1045		return(1);
1046	}
1047
1048	close(fd);
1049
1050	if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1051		fprintf(stdout, "%s of bus %d was successful\n",
1052		    rescan? "Re-scan" : "Reset", bus);
1053		return(0);
1054	} else {
1055		fprintf(stdout, "%s of bus %d returned error %#x\n",
1056		    rescan? "Re-scan" : "Reset", bus,
1057		    ccb.ccb_h.status & CAM_STATUS_MASK);
1058		return(1);
1059	}
1060}
1061
1062static int
1063scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1064{
1065	union ccb ccb;
1066	struct cam_device *device;
1067	int fd;
1068
1069	device = NULL;
1070
1071	if (bus < 0) {
1072		warnx("invalid bus number %d", bus);
1073		return(1);
1074	}
1075
1076	if (target < 0) {
1077		warnx("invalid target number %d", target);
1078		return(1);
1079	}
1080
1081	if (lun < 0) {
1082		warnx("invalid lun number %d", lun);
1083		return(1);
1084	}
1085
1086	fd = -1;
1087
1088	bzero(&ccb, sizeof(union ccb));
1089
1090	if (scan) {
1091		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1092			warnx("error opening tranport layer device %s\n",
1093			    XPT_DEVICE);
1094			warn("%s", XPT_DEVICE);
1095			return(1);
1096		}
1097	} else {
1098		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1099		if (device == NULL) {
1100			warnx("%s", cam_errbuf);
1101			return(1);
1102		}
1103	}
1104
1105	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1106	ccb.ccb_h.path_id = bus;
1107	ccb.ccb_h.target_id = target;
1108	ccb.ccb_h.target_lun = lun;
1109	ccb.ccb_h.timeout = 5000;
1110	ccb.crcn.flags = CAM_FLAG_NONE;
1111
1112	/* run this at a low priority */
1113	ccb.ccb_h.pinfo.priority = 5;
1114
1115	if (scan) {
1116		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1117			warn("CAMIOCOMMAND ioctl failed");
1118			close(fd);
1119			return(1);
1120		}
1121	} else {
1122		if (cam_send_ccb(device, &ccb) < 0) {
1123			warn("error sending XPT_RESET_DEV CCB");
1124			cam_close_device(device);
1125			return(1);
1126		}
1127	}
1128
1129	if (scan)
1130		close(fd);
1131	else
1132		cam_close_device(device);
1133
1134	/*
1135	 * An error code of CAM_BDR_SENT is normal for a BDR request.
1136	 */
1137	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1138	 || ((!scan)
1139	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1140		fprintf(stdout, "%s of %d:%d:%d was successful\n",
1141		    scan? "Re-scan" : "Reset", bus, target, lun);
1142		return(0);
1143	} else {
1144		fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1145		    scan? "Re-scan" : "Reset", bus, target, lun,
1146		    ccb.ccb_h.status & CAM_STATUS_MASK);
1147		return(1);
1148	}
1149}
1150
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, e.g. \"da\", \"cd\"\n"
3019"-u unit           specify unit number, e.g. \"0\", \"5\"\n"
3020"-E                have the kernel attempt to perform SCSI error recovery\n"
3021"-C count          specify the SCSI command retry count (needs -E to work)\n"
3022"modepage arguments:\n"
3023"-m page           specify the mode page to view or edit\n"
3024"-e                edit the specified mode page\n"
3025"-d                disable block descriptors for mode sense\n"
3026"-P pgctl          page control field 0-3\n"
3027"defects arguments:\n"
3028"-f format         specify defect list format (block, bfi or phys)\n"
3029"-G                get the grown defect list\n"
3030"-P                get the permanant defect list\n"
3031"inquiry arguments:\n"
3032"-D                get the standard inquiry data\n"
3033"-S                get the serial number\n"
3034"-R                get the transfer rate, etc.\n"
3035"cmd arguments:\n"
3036"-c cdb [args]     specify the SCSI CDB\n"
3037"-i len fmt        specify input data and input data format\n"
3038"-o len fmt [args] specify output data and output data fmt\n"
3039"debug arguments:\n"
3040"-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
3041"-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
3042"-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
3043"-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
3044"tags arguments:\n"
3045"-N tags           specify the number of tags to use for this device\n"
3046"-q                be quiet, don't report the number of tags\n"
3047"-v                report a number of tag-related parameters\n"
3048"negotiate arguments:\n"
3049"-a                send a test unit ready after negotiation\n"
3050"-c                report/set current negotiation settings\n"
3051"-D <arg>          \"enable\" or \"disable\" disconnection\n"
3052"-O offset         set command delay offset\n"
3053"-q                be quiet, don't report anything\n"
3054"-R syncrate       synchronization rate in MHz\n"
3055"-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
3056"-U                report/set user negotiation settings\n"
3057"-W bus_width      set the bus width in bits (8, 16 or 32)\n"
3058"-v                also print a Path Inquiry CCB for the controller\n"
3059"format arguments:\n"
3060"-q                be quiet, don't print status messages\n"
3061"-w                don't send immediate format command\n"
3062"-y                don't ask any questions\n");
3063}
3064
3065int
3066main(int argc, char **argv)
3067{
3068	int c;
3069	char *device = NULL;
3070	int unit = 0;
3071	struct cam_device *cam_dev = NULL;
3072	int timeout = 0, retry_count = 1;
3073	camcontrol_optret optreturn;
3074	char *tstr;
3075	char *mainopt = "C:En:t:u:v";
3076	char *subopt = NULL;
3077	char combinedopt[256];
3078	int error = 0, optstart = 2;
3079	int devopen = 1;
3080
3081	arglist = CAM_ARG_NONE;
3082
3083	if (argc < 2) {
3084		usage(0);
3085		exit(1);
3086	}
3087
3088	/*
3089	 * Get the base option.
3090	 */
3091	optreturn = getoption(argv[1], &arglist, &subopt);
3092
3093	if (optreturn == CC_OR_AMBIGUOUS) {
3094		warnx("ambiguous option %s", argv[1]);
3095		usage(0);
3096		exit(1);
3097	} else if (optreturn == CC_OR_NOT_FOUND) {
3098		warnx("option %s not found", argv[1]);
3099		usage(0);
3100		exit(1);
3101	}
3102
3103	/*
3104	 * Ahh, getopt(3) is a pain.
3105	 *
3106	 * This is a gross hack.  There really aren't many other good
3107	 * options (excuse the pun) for parsing options in a situation like
3108	 * this.  getopt is kinda braindead, so you end up having to run
3109	 * through the options twice, and give each invocation of getopt
3110	 * the option string for the other invocation.
3111	 *
3112	 * You would think that you could just have two groups of options.
3113	 * The first group would get parsed by the first invocation of
3114	 * getopt, and the second group would get parsed by the second
3115	 * invocation of getopt.  It doesn't quite work out that way.  When
3116	 * the first invocation of getopt finishes, it leaves optind pointing
3117	 * to the argument _after_ the first argument in the second group.
3118	 * So when the second invocation of getopt comes around, it doesn't
3119	 * recognize the first argument it gets and then bails out.
3120	 *
3121	 * A nice alternative would be to have a flag for getopt that says
3122	 * "just keep parsing arguments even when you encounter an unknown
3123	 * argument", but there isn't one.  So there's no real clean way to
3124	 * easily parse two sets of arguments without having one invocation
3125	 * of getopt know about the other.
3126	 *
3127	 * Without this hack, the first invocation of getopt would work as
3128	 * long as the generic arguments are first, but the second invocation
3129	 * (in the subfunction) would fail in one of two ways.  In the case
3130	 * where you don't set optreset, it would fail because optind may be
3131	 * pointing to the argument after the one it should be pointing at.
3132	 * In the case where you do set optreset, and reset optind, it would
3133	 * fail because getopt would run into the first set of options, which
3134	 * it doesn't understand.
3135	 *
3136	 * All of this would "sort of" work if you could somehow figure out
3137	 * whether optind had been incremented one option too far.  The
3138	 * mechanics of that, however, are more daunting than just giving
3139	 * both invocations all of the expect options for either invocation.
3140	 *
3141	 * Needless to say, I wouldn't mind if someone invented a better
3142	 * (non-GPL!) command line parsing interface than getopt.  I
3143	 * wouldn't mind if someone added more knobs to getopt to make it
3144	 * work better.  Who knows, I may talk myself into doing it someday,
3145	 * if the standards weenies let me.  As it is, it just leads to
3146	 * hackery like this and causes people to avoid it in some cases.
3147	 *
3148	 * KDM, September 8th, 1998
3149	 */
3150	if (subopt != NULL)
3151		sprintf(combinedopt, "%s%s", mainopt, subopt);
3152	else
3153		sprintf(combinedopt, "%s", mainopt);
3154
3155	/*
3156	 * For these options we do not parse optional device arguments and
3157	 * we do not open a passthrough device.
3158	 */
3159	if (((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESCAN)
3160	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESET)
3161	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEVTREE)
3162	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_USAGE)
3163	 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEBUG))
3164		devopen = 0;
3165
3166	if ((devopen == 1)
3167	 && (argc > 2 && argv[2][0] != '-')) {
3168		char name[30];
3169		int rv;
3170
3171		/*
3172		 * First catch people who try to do things like:
3173		 * camcontrol tur /dev/rsd0.ctl
3174		 * camcontrol doesn't take device nodes as arguments.
3175		 */
3176		if (argv[2][0] == '/') {
3177			warnx("%s is not a valid device identifier", argv[2]);
3178			errx(1, "please read the camcontrol(8) man page");
3179		} else if (isdigit(argv[2][0])) {
3180			/* device specified as bus:target[:lun] */
3181			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
3182			if (rv < 2)
3183				errx(1, "numeric device specification must "
3184				     "be either bus:target, or "
3185				     "bus:target:lun");
3186			optstart++;
3187		} else {
3188			if (cam_get_device(argv[2], name, sizeof name, &unit)
3189			    == -1)
3190				errx(1, "%s", cam_errbuf);
3191			device = strdup(name);
3192			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
3193			optstart++;
3194		}
3195	}
3196	/*
3197	 * Start getopt processing at argv[2/3], since we've already
3198	 * accepted argv[1..2] as the command name, and as a possible
3199	 * device name.
3200	 */
3201	optind = optstart;
3202
3203	/*
3204	 * Now we run through the argument list looking for generic
3205	 * options, and ignoring options that possibly belong to
3206	 * subfunctions.
3207	 */
3208	while ((c = getopt(argc, argv, combinedopt))!= -1){
3209		switch(c) {
3210			case 'C':
3211				retry_count = strtol(optarg, NULL, 0);
3212				if (retry_count < 0)
3213					errx(1, "retry count %d is < 0",
3214					     retry_count);
3215				arglist |= CAM_ARG_RETRIES;
3216				break;
3217			case 'E':
3218				arglist |= CAM_ARG_ERR_RECOVER;
3219				break;
3220			case 'n':
3221				arglist |= CAM_ARG_DEVICE;
3222				tstr = optarg;
3223				while (isspace(*tstr) && (*tstr != '\0'))
3224					tstr++;
3225				device = (char *)strdup(tstr);
3226				break;
3227			case 't':
3228				timeout = strtol(optarg, NULL, 0);
3229				if (timeout < 0)
3230					errx(1, "invalid timeout %d", timeout);
3231				/* Convert the timeout from seconds to ms */
3232				timeout *= 1000;
3233				arglist |= CAM_ARG_TIMEOUT;
3234				break;
3235			case 'u':
3236				arglist |= CAM_ARG_UNIT;
3237				unit = strtol(optarg, NULL, 0);
3238				break;
3239			case 'v':
3240				arglist |= CAM_ARG_VERBOSE;
3241				break;
3242			default:
3243				break;
3244		}
3245	}
3246
3247	/*
3248	 * For most commands we'll want to open the passthrough device
3249	 * associated with the specified device.  In the case of the rescan
3250	 * commands, we don't use a passthrough device at all, just the
3251	 * transport layer device.
3252	 */
3253	if (devopen == 1) {
3254		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
3255		 && (((arglist & CAM_ARG_DEVICE) == 0)
3256		  || ((arglist & CAM_ARG_UNIT) == 0))) {
3257			errx(1, "subcommand \"%s\" requires a valid device "
3258			     "identifier", argv[1]);
3259		}
3260
3261		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
3262				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
3263				cam_open_spec_device(device,unit,O_RDWR,NULL)))
3264		     == NULL)
3265			errx(1,"%s", cam_errbuf);
3266	}
3267
3268	/*
3269	 * Reset optind to 2, and reset getopt, so these routines can parse
3270	 * the arguments again.
3271	 */
3272	optind = optstart;
3273	optreset = 1;
3274
3275	switch(arglist & CAM_ARG_OPT_MASK) {
3276		case CAM_ARG_DEVLIST:
3277			error = getdevlist(cam_dev);
3278			break;
3279		case CAM_ARG_DEVTREE:
3280			error = getdevtree();
3281			break;
3282		case CAM_ARG_TUR:
3283			error = testunitready(cam_dev, retry_count, timeout, 0);
3284			break;
3285		case CAM_ARG_INQUIRY:
3286			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
3287					      retry_count, timeout);
3288			break;
3289		case CAM_ARG_STARTSTOP:
3290			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
3291					  arglist & CAM_ARG_EJECT, retry_count,
3292					  timeout);
3293			break;
3294		case CAM_ARG_RESCAN:
3295			error = dorescan_or_reset(argc, argv, 1);
3296			break;
3297		case CAM_ARG_RESET:
3298			error = dorescan_or_reset(argc, argv, 0);
3299			break;
3300		case CAM_ARG_READ_DEFECTS:
3301			error = readdefects(cam_dev, argc, argv, combinedopt,
3302					    retry_count, timeout);
3303			break;
3304		case CAM_ARG_MODE_PAGE:
3305			modepage(cam_dev, argc, argv, combinedopt,
3306				 retry_count, timeout);
3307			break;
3308		case CAM_ARG_SCSI_CMD:
3309			error = scsicmd(cam_dev, argc, argv, combinedopt,
3310					retry_count, timeout);
3311			break;
3312		case CAM_ARG_DEBUG:
3313			error = camdebug(argc, argv, combinedopt);
3314			break;
3315		case CAM_ARG_TAG:
3316			error = tagcontrol(cam_dev, argc, argv, combinedopt);
3317			break;
3318		case CAM_ARG_RATE:
3319			error = ratecontrol(cam_dev, retry_count, timeout,
3320					    argc, argv, combinedopt);
3321			break;
3322		case CAM_ARG_FORMAT:
3323			error = scsiformat(cam_dev, argc, argv,
3324					   combinedopt, retry_count, timeout);
3325			break;
3326		case CAM_ARG_USAGE:
3327			usage(1);
3328			break;
3329		default:
3330			usage(0);
3331			error = 1;
3332			break;
3333	}
3334
3335	if (cam_dev != NULL)
3336		cam_close_device(cam_dev);
3337
3338	exit(error);
3339}
3340