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