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