xref: /freebsd/sbin/camcontrol/camcontrol.c (revision 830940567b49bb0c08dfaed40418999e76616909)
1 /*
2  * Copyright (c) 1997-2007 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 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/ioctl.h>
33 #include <sys/stdint.h>
34 #include <sys/types.h>
35 #include <sys/endian.h>
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <ctype.h>
43 #include <err.h>
44 #include <libutil.h>
45 
46 #include <cam/cam.h>
47 #include <cam/cam_debug.h>
48 #include <cam/cam_ccb.h>
49 #include <cam/scsi/scsi_all.h>
50 #include <cam/scsi/scsi_da.h>
51 #include <cam/scsi/scsi_pass.h>
52 #include <cam/scsi/scsi_message.h>
53 #include <cam/ata/ata_all.h>
54 #include <camlib.h>
55 #include "camcontrol.h"
56 
57 typedef enum {
58 	CAM_CMD_NONE		= 0x00000000,
59 	CAM_CMD_DEVLIST		= 0x00000001,
60 	CAM_CMD_TUR		= 0x00000002,
61 	CAM_CMD_INQUIRY		= 0x00000003,
62 	CAM_CMD_STARTSTOP	= 0x00000004,
63 	CAM_CMD_RESCAN		= 0x00000005,
64 	CAM_CMD_READ_DEFECTS	= 0x00000006,
65 	CAM_CMD_MODE_PAGE	= 0x00000007,
66 	CAM_CMD_SCSI_CMD	= 0x00000008,
67 	CAM_CMD_DEVTREE		= 0x00000009,
68 	CAM_CMD_USAGE		= 0x0000000a,
69 	CAM_CMD_DEBUG		= 0x0000000b,
70 	CAM_CMD_RESET		= 0x0000000c,
71 	CAM_CMD_FORMAT		= 0x0000000d,
72 	CAM_CMD_TAG		= 0x0000000e,
73 	CAM_CMD_RATE		= 0x0000000f,
74 	CAM_CMD_DETACH		= 0x00000010,
75 	CAM_CMD_REPORTLUNS	= 0x00000011,
76 	CAM_CMD_READCAP		= 0x00000012,
77 	CAM_CMD_IDENTIFY	= 0x00000013
78 } cam_cmdmask;
79 
80 typedef enum {
81 	CAM_ARG_NONE		= 0x00000000,
82 	CAM_ARG_VERBOSE		= 0x00000001,
83 	CAM_ARG_DEVICE		= 0x00000002,
84 	CAM_ARG_BUS		= 0x00000004,
85 	CAM_ARG_TARGET		= 0x00000008,
86 	CAM_ARG_LUN		= 0x00000010,
87 	CAM_ARG_EJECT		= 0x00000020,
88 	CAM_ARG_UNIT		= 0x00000040,
89 	CAM_ARG_FORMAT_BLOCK	= 0x00000080,
90 	CAM_ARG_FORMAT_BFI	= 0x00000100,
91 	CAM_ARG_FORMAT_PHYS	= 0x00000200,
92 	CAM_ARG_PLIST		= 0x00000400,
93 	CAM_ARG_GLIST		= 0x00000800,
94 	CAM_ARG_GET_SERIAL	= 0x00001000,
95 	CAM_ARG_GET_STDINQ	= 0x00002000,
96 	CAM_ARG_GET_XFERRATE	= 0x00004000,
97 	CAM_ARG_INQ_MASK	= 0x00007000,
98 	CAM_ARG_MODE_EDIT	= 0x00008000,
99 	CAM_ARG_PAGE_CNTL	= 0x00010000,
100 	CAM_ARG_TIMEOUT		= 0x00020000,
101 	CAM_ARG_CMD_IN		= 0x00040000,
102 	CAM_ARG_CMD_OUT		= 0x00080000,
103 	CAM_ARG_DBD		= 0x00100000,
104 	CAM_ARG_ERR_RECOVER	= 0x00200000,
105 	CAM_ARG_RETRIES		= 0x00400000,
106 	CAM_ARG_START_UNIT	= 0x00800000,
107 	CAM_ARG_DEBUG_INFO	= 0x01000000,
108 	CAM_ARG_DEBUG_TRACE	= 0x02000000,
109 	CAM_ARG_DEBUG_SUBTRACE	= 0x04000000,
110 	CAM_ARG_DEBUG_CDB	= 0x08000000,
111 	CAM_ARG_DEBUG_XPT	= 0x10000000,
112 	CAM_ARG_DEBUG_PERIPH	= 0x20000000,
113 } cam_argmask;
114 
115 struct camcontrol_opts {
116 	const char	*optname;
117 	cam_cmdmask	cmdnum;
118 	cam_argmask	argnum;
119 	const char	*subopt;
120 };
121 
122 #ifndef MINIMALISTIC
123 static const char scsicmd_opts[] = "c:i:o:";
124 static const char readdefect_opts[] = "f:GP";
125 static const char negotiate_opts[] = "acD:O:qR:T:UW:";
126 #endif
127 
128 struct camcontrol_opts option_table[] = {
129 #ifndef MINIMALISTIC
130 	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
131 	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
132 	{"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
133 	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
134 	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
135 	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
136 	{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
137 	{"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
138 	{"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
139 #endif /* MINIMALISTIC */
140 	{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
141 	{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
142 #ifndef MINIMALISTIC
143 	{"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
144 	{"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
145 	{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
146 	{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
147 #endif /* MINIMALISTIC */
148 	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
149 #ifndef MINIMALISTIC
150 	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
151 	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
152 	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
153 	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
154 	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
155 	{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
156 	{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
157 #endif /* MINIMALISTIC */
158 	{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
159 	{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
160 	{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
161 	{NULL, 0, 0, NULL}
162 };
163 
164 typedef enum {
165 	CC_OR_NOT_FOUND,
166 	CC_OR_AMBIGUOUS,
167 	CC_OR_FOUND
168 } camcontrol_optret;
169 
170 cam_cmdmask cmdlist;
171 cam_argmask arglist;
172 
173 
174 camcontrol_optret getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
175 			    const char **subopt);
176 #ifndef MINIMALISTIC
177 static int getdevlist(struct cam_device *device);
178 #endif /* MINIMALISTIC */
179 static int getdevtree(void);
180 #ifndef MINIMALISTIC
181 static int testunitready(struct cam_device *device, int retry_count,
182 			 int timeout, int quiet);
183 static int scsistart(struct cam_device *device, int startstop, int loadeject,
184 		     int retry_count, int timeout);
185 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
186 			 char *combinedopt, int retry_count, int timeout);
187 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
188 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
189 static int scsixferrate(struct cam_device *device);
190 #endif /* MINIMALISTIC */
191 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
192 		     cam_argmask *arglst);
193 static int dorescan_or_reset(int argc, char **argv, int rescan);
194 static int rescan_or_reset_bus(int bus, int rescan);
195 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
196 #ifndef MINIMALISTIC
197 static int readdefects(struct cam_device *device, int argc, char **argv,
198 		       char *combinedopt, int retry_count, int timeout);
199 static void modepage(struct cam_device *device, int argc, char **argv,
200 		     char *combinedopt, int retry_count, int timeout);
201 static int scsicmd(struct cam_device *device, int argc, char **argv,
202 		   char *combinedopt, int retry_count, int timeout);
203 static int tagcontrol(struct cam_device *device, int argc, char **argv,
204 		      char *combinedopt);
205 static void cts_print(struct cam_device *device,
206 		      struct ccb_trans_settings *cts);
207 static void cpi_print(struct ccb_pathinq *cpi);
208 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
209 static int get_print_cts(struct cam_device *device, int user_settings,
210 			 int quiet, struct ccb_trans_settings *cts);
211 static int ratecontrol(struct cam_device *device, int retry_count,
212 		       int timeout, int argc, char **argv, char *combinedopt);
213 static int scsiformat(struct cam_device *device, int argc, char **argv,
214 		      char *combinedopt, int retry_count, int timeout);
215 static int scsireportluns(struct cam_device *device, int argc, char **argv,
216 			  char *combinedopt, int retry_count, int timeout);
217 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
218 			    char *combinedopt, int retry_count, int timeout);
219 #endif /* MINIMALISTIC */
220 
221 camcontrol_optret
222 getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
223 	  const char **subopt)
224 {
225 	struct camcontrol_opts *opts;
226 	int num_matches = 0;
227 
228 	for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
229 	     opts++) {
230 		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
231 			*cmdnum = opts->cmdnum;
232 			*argnum = opts->argnum;
233 			*subopt = opts->subopt;
234 			if (++num_matches > 1)
235 				return(CC_OR_AMBIGUOUS);
236 		}
237 	}
238 
239 	if (num_matches > 0)
240 		return(CC_OR_FOUND);
241 	else
242 		return(CC_OR_NOT_FOUND);
243 }
244 
245 #ifndef MINIMALISTIC
246 static int
247 getdevlist(struct cam_device *device)
248 {
249 	union ccb *ccb;
250 	char status[32];
251 	int error = 0;
252 
253 	ccb = cam_getccb(device);
254 
255 	ccb->ccb_h.func_code = XPT_GDEVLIST;
256 	ccb->ccb_h.flags = CAM_DIR_NONE;
257 	ccb->ccb_h.retry_count = 1;
258 	ccb->cgdl.index = 0;
259 	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
260 	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
261 		if (cam_send_ccb(device, ccb) < 0) {
262 			perror("error getting device list");
263 			cam_freeccb(ccb);
264 			return(1);
265 		}
266 
267 		status[0] = '\0';
268 
269 		switch (ccb->cgdl.status) {
270 			case CAM_GDEVLIST_MORE_DEVS:
271 				strcpy(status, "MORE");
272 				break;
273 			case CAM_GDEVLIST_LAST_DEVICE:
274 				strcpy(status, "LAST");
275 				break;
276 			case CAM_GDEVLIST_LIST_CHANGED:
277 				strcpy(status, "CHANGED");
278 				break;
279 			case CAM_GDEVLIST_ERROR:
280 				strcpy(status, "ERROR");
281 				error = 1;
282 				break;
283 		}
284 
285 		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
286 			ccb->cgdl.periph_name,
287 			ccb->cgdl.unit_number,
288 			ccb->cgdl.generation,
289 			ccb->cgdl.index,
290 			status);
291 
292 		/*
293 		 * If the list has changed, we need to start over from the
294 		 * beginning.
295 		 */
296 		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
297 			ccb->cgdl.index = 0;
298 	}
299 
300 	cam_freeccb(ccb);
301 
302 	return(error);
303 }
304 #endif /* MINIMALISTIC */
305 
306 static int
307 getdevtree(void)
308 {
309 	union ccb ccb;
310 	int bufsize, fd;
311 	unsigned int i;
312 	int need_close = 0;
313 	int error = 0;
314 	int skip_device = 0;
315 
316 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
317 		warn("couldn't open %s", XPT_DEVICE);
318 		return(1);
319 	}
320 
321 	bzero(&ccb, sizeof(union ccb));
322 
323 	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
324 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
325 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
326 
327 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
328 	bufsize = sizeof(struct dev_match_result) * 100;
329 	ccb.cdm.match_buf_len = bufsize;
330 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
331 	if (ccb.cdm.matches == NULL) {
332 		warnx("can't malloc memory for matches");
333 		close(fd);
334 		return(1);
335 	}
336 	ccb.cdm.num_matches = 0;
337 
338 	/*
339 	 * We fetch all nodes, since we display most of them in the default
340 	 * case, and all in the verbose case.
341 	 */
342 	ccb.cdm.num_patterns = 0;
343 	ccb.cdm.pattern_buf_len = 0;
344 
345 	/*
346 	 * We do the ioctl multiple times if necessary, in case there are
347 	 * more than 100 nodes in the EDT.
348 	 */
349 	do {
350 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
351 			warn("error sending CAMIOCOMMAND ioctl");
352 			error = 1;
353 			break;
354 		}
355 
356 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
357 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
358 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
359 			warnx("got CAM error %#x, CDM error %d\n",
360 			      ccb.ccb_h.status, ccb.cdm.status);
361 			error = 1;
362 			break;
363 		}
364 
365 		for (i = 0; i < ccb.cdm.num_matches; i++) {
366 			switch (ccb.cdm.matches[i].type) {
367 			case DEV_MATCH_BUS: {
368 				struct bus_match_result *bus_result;
369 
370 				/*
371 				 * Only print the bus information if the
372 				 * user turns on the verbose flag.
373 				 */
374 				if ((arglist & CAM_ARG_VERBOSE) == 0)
375 					break;
376 
377 				bus_result =
378 					&ccb.cdm.matches[i].result.bus_result;
379 
380 				if (need_close) {
381 					fprintf(stdout, ")\n");
382 					need_close = 0;
383 				}
384 
385 				fprintf(stdout, "scbus%d on %s%d bus %d:\n",
386 					bus_result->path_id,
387 					bus_result->dev_name,
388 					bus_result->unit_number,
389 					bus_result->bus_id);
390 				break;
391 			}
392 			case DEV_MATCH_DEVICE: {
393 				struct device_match_result *dev_result;
394 				char vendor[16], product[48], revision[16];
395 				char tmpstr[256];
396 
397 				dev_result =
398 				     &ccb.cdm.matches[i].result.device_result;
399 
400 				if ((dev_result->flags
401 				     & DEV_RESULT_UNCONFIGURED)
402 				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
403 					skip_device = 1;
404 					break;
405 				} else
406 					skip_device = 0;
407 
408 				if (dev_result->protocol == PROTO_SCSI) {
409 				    cam_strvis(vendor, dev_result->inq_data.vendor,
410 					   sizeof(dev_result->inq_data.vendor),
411 					   sizeof(vendor));
412 				    cam_strvis(product,
413 					   dev_result->inq_data.product,
414 					   sizeof(dev_result->inq_data.product),
415 					   sizeof(product));
416 				    cam_strvis(revision,
417 					   dev_result->inq_data.revision,
418 					  sizeof(dev_result->inq_data.revision),
419 					   sizeof(revision));
420 				    sprintf(tmpstr, "<%s %s %s>", vendor, product,
421 					revision);
422 				} else if (dev_result->protocol == PROTO_ATA ||
423 				    dev_result->protocol == PROTO_SATAPM) {
424 				    cam_strvis(product,
425 					   dev_result->ident_data.model,
426 					   sizeof(dev_result->ident_data.model),
427 					   sizeof(product));
428 				    cam_strvis(revision,
429 					   dev_result->ident_data.revision,
430 					  sizeof(dev_result->ident_data.revision),
431 					   sizeof(revision));
432 				    sprintf(tmpstr, "<%s %s>", product,
433 					revision);
434 				} else {
435 				    sprintf(tmpstr, "<>");
436 				}
437 				if (need_close) {
438 					fprintf(stdout, ")\n");
439 					need_close = 0;
440 				}
441 
442 				fprintf(stdout, "%-33s  at scbus%d "
443 					"target %d lun %d (",
444 					tmpstr,
445 					dev_result->path_id,
446 					dev_result->target_id,
447 					dev_result->target_lun);
448 
449 				need_close = 1;
450 
451 				break;
452 			}
453 			case DEV_MATCH_PERIPH: {
454 				struct periph_match_result *periph_result;
455 
456 				periph_result =
457 				      &ccb.cdm.matches[i].result.periph_result;
458 
459 				if (skip_device != 0)
460 					break;
461 
462 				if (need_close > 1)
463 					fprintf(stdout, ",");
464 
465 				fprintf(stdout, "%s%d",
466 					periph_result->periph_name,
467 					periph_result->unit_number);
468 
469 				need_close++;
470 				break;
471 			}
472 			default:
473 				fprintf(stdout, "unknown match type\n");
474 				break;
475 			}
476 		}
477 
478 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
479 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
480 
481 	if (need_close)
482 		fprintf(stdout, ")\n");
483 
484 	close(fd);
485 
486 	return(error);
487 }
488 
489 #ifndef MINIMALISTIC
490 static int
491 testunitready(struct cam_device *device, int retry_count, int timeout,
492 	      int quiet)
493 {
494 	int error = 0;
495 	union ccb *ccb;
496 
497 	ccb = cam_getccb(device);
498 
499 	scsi_test_unit_ready(&ccb->csio,
500 			     /* retries */ retry_count,
501 			     /* cbfcnp */ NULL,
502 			     /* tag_action */ MSG_SIMPLE_Q_TAG,
503 			     /* sense_len */ SSD_FULL_SIZE,
504 			     /* timeout */ timeout ? timeout : 5000);
505 
506 	/* Disable freezing the device queue */
507 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
508 
509 	if (arglist & CAM_ARG_ERR_RECOVER)
510 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
511 
512 	if (cam_send_ccb(device, ccb) < 0) {
513 		if (quiet == 0)
514 			perror("error sending test unit ready");
515 
516 		if (arglist & CAM_ARG_VERBOSE) {
517 			cam_error_print(device, ccb, CAM_ESF_ALL,
518 					CAM_EPF_ALL, stderr);
519 		}
520 
521 		cam_freeccb(ccb);
522 		return(1);
523 	}
524 
525 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
526 		if (quiet == 0)
527 			fprintf(stdout, "Unit is ready\n");
528 	} else {
529 		if (quiet == 0)
530 			fprintf(stdout, "Unit is not ready\n");
531 		error = 1;
532 
533 		if (arglist & CAM_ARG_VERBOSE) {
534 			cam_error_print(device, ccb, CAM_ESF_ALL,
535 					CAM_EPF_ALL, stderr);
536 		}
537 	}
538 
539 	cam_freeccb(ccb);
540 
541 	return(error);
542 }
543 
544 static int
545 scsistart(struct cam_device *device, int startstop, int loadeject,
546 	  int retry_count, int timeout)
547 {
548 	union ccb *ccb;
549 	int error = 0;
550 
551 	ccb = cam_getccb(device);
552 
553 	/*
554 	 * If we're stopping, send an ordered tag so the drive in question
555 	 * will finish any previously queued writes before stopping.  If
556 	 * the device isn't capable of tagged queueing, or if tagged
557 	 * queueing is turned off, the tag action is a no-op.
558 	 */
559 	scsi_start_stop(&ccb->csio,
560 			/* retries */ retry_count,
561 			/* cbfcnp */ NULL,
562 			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
563 						     MSG_ORDERED_Q_TAG,
564 			/* start/stop */ startstop,
565 			/* load_eject */ loadeject,
566 			/* immediate */ 0,
567 			/* sense_len */ SSD_FULL_SIZE,
568 			/* timeout */ timeout ? timeout : 120000);
569 
570 	/* Disable freezing the device queue */
571 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
572 
573 	if (arglist & CAM_ARG_ERR_RECOVER)
574 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
575 
576 	if (cam_send_ccb(device, ccb) < 0) {
577 		perror("error sending start unit");
578 
579 		if (arglist & CAM_ARG_VERBOSE) {
580 			cam_error_print(device, ccb, CAM_ESF_ALL,
581 					CAM_EPF_ALL, stderr);
582 		}
583 
584 		cam_freeccb(ccb);
585 		return(1);
586 	}
587 
588 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
589 		if (startstop) {
590 			fprintf(stdout, "Unit started successfully");
591 			if (loadeject)
592 				fprintf(stdout,", Media loaded\n");
593 			else
594 				fprintf(stdout,"\n");
595 		} else {
596 			fprintf(stdout, "Unit stopped successfully");
597 			if (loadeject)
598 				fprintf(stdout, ", Media ejected\n");
599 			else
600 				fprintf(stdout, "\n");
601 		}
602 	else {
603 		error = 1;
604 		if (startstop)
605 			fprintf(stdout,
606 				"Error received from start unit command\n");
607 		else
608 			fprintf(stdout,
609 				"Error received from stop unit command\n");
610 
611 		if (arglist & CAM_ARG_VERBOSE) {
612 			cam_error_print(device, ccb, CAM_ESF_ALL,
613 					CAM_EPF_ALL, stderr);
614 		}
615 	}
616 
617 	cam_freeccb(ccb);
618 
619 	return(error);
620 }
621 
622 static int
623 scsidoinquiry(struct cam_device *device, int argc, char **argv,
624 	      char *combinedopt, int retry_count, int timeout)
625 {
626 	int c;
627 	int error = 0;
628 
629 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
630 		switch(c) {
631 		case 'D':
632 			arglist |= CAM_ARG_GET_STDINQ;
633 			break;
634 		case 'R':
635 			arglist |= CAM_ARG_GET_XFERRATE;
636 			break;
637 		case 'S':
638 			arglist |= CAM_ARG_GET_SERIAL;
639 			break;
640 		default:
641 			break;
642 		}
643 	}
644 
645 	/*
646 	 * If the user didn't specify any inquiry options, he wants all of
647 	 * them.
648 	 */
649 	if ((arglist & CAM_ARG_INQ_MASK) == 0)
650 		arglist |= CAM_ARG_INQ_MASK;
651 
652 	if (arglist & CAM_ARG_GET_STDINQ)
653 		error = scsiinquiry(device, retry_count, timeout);
654 
655 	if (error != 0)
656 		return(error);
657 
658 	if (arglist & CAM_ARG_GET_SERIAL)
659 		scsiserial(device, retry_count, timeout);
660 
661 	if (error != 0)
662 		return(error);
663 
664 	if (arglist & CAM_ARG_GET_XFERRATE)
665 		error = scsixferrate(device);
666 
667 	return(error);
668 }
669 
670 static int
671 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
672 {
673 	union ccb *ccb;
674 	struct scsi_inquiry_data *inq_buf;
675 	int error = 0;
676 
677 	ccb = cam_getccb(device);
678 
679 	if (ccb == NULL) {
680 		warnx("couldn't allocate CCB");
681 		return(1);
682 	}
683 
684 	/* cam_getccb cleans up the header, caller has to zero the payload */
685 	bzero(&(&ccb->ccb_h)[1],
686 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
687 
688 	inq_buf = (struct scsi_inquiry_data *)malloc(
689 		sizeof(struct scsi_inquiry_data));
690 
691 	if (inq_buf == NULL) {
692 		cam_freeccb(ccb);
693 		warnx("can't malloc memory for inquiry\n");
694 		return(1);
695 	}
696 	bzero(inq_buf, sizeof(*inq_buf));
697 
698 	/*
699 	 * Note that although the size of the inquiry buffer is the full
700 	 * 256 bytes specified in the SCSI spec, we only tell the device
701 	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
702 	 * two reasons for this:
703 	 *
704 	 *  - The SCSI spec says that when a length field is only 1 byte,
705 	 *    a value of 0 will be interpreted as 256.  Therefore
706 	 *    scsi_inquiry() will convert an inq_len (which is passed in as
707 	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
708 	 *    to 0.  Evidently, very few devices meet the spec in that
709 	 *    regard.  Some devices, like many Seagate disks, take the 0 as
710 	 *    0, and don't return any data.  One Pioneer DVD-R drive
711 	 *    returns more data than the command asked for.
712 	 *
713 	 *    So, since there are numerous devices that just don't work
714 	 *    right with the full inquiry size, we don't send the full size.
715 	 *
716 	 *  - The second reason not to use the full inquiry data length is
717 	 *    that we don't need it here.  The only reason we issue a
718 	 *    standard inquiry is to get the vendor name, device name,
719 	 *    and revision so scsi_print_inquiry() can print them.
720 	 *
721 	 * If, at some point in the future, more inquiry data is needed for
722 	 * some reason, this code should use a procedure similar to the
723 	 * probe code.  i.e., issue a short inquiry, and determine from
724 	 * the additional length passed back from the device how much
725 	 * inquiry data the device supports.  Once the amount the device
726 	 * supports is determined, issue an inquiry for that amount and no
727 	 * more.
728 	 *
729 	 * KDM, 2/18/2000
730 	 */
731 	scsi_inquiry(&ccb->csio,
732 		     /* retries */ retry_count,
733 		     /* cbfcnp */ NULL,
734 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
735 		     /* inq_buf */ (u_int8_t *)inq_buf,
736 		     /* inq_len */ SHORT_INQUIRY_LENGTH,
737 		     /* evpd */ 0,
738 		     /* page_code */ 0,
739 		     /* sense_len */ SSD_FULL_SIZE,
740 		     /* timeout */ timeout ? timeout : 5000);
741 
742 	/* Disable freezing the device queue */
743 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
744 
745 	if (arglist & CAM_ARG_ERR_RECOVER)
746 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
747 
748 	if (cam_send_ccb(device, ccb) < 0) {
749 		perror("error sending SCSI inquiry");
750 
751 		if (arglist & CAM_ARG_VERBOSE) {
752 			cam_error_print(device, ccb, CAM_ESF_ALL,
753 					CAM_EPF_ALL, stderr);
754 		}
755 
756 		cam_freeccb(ccb);
757 		return(1);
758 	}
759 
760 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
761 		error = 1;
762 
763 		if (arglist & CAM_ARG_VERBOSE) {
764 			cam_error_print(device, ccb, CAM_ESF_ALL,
765 					CAM_EPF_ALL, stderr);
766 		}
767 	}
768 
769 	cam_freeccb(ccb);
770 
771 	if (error != 0) {
772 		free(inq_buf);
773 		return(error);
774 	}
775 
776 	fprintf(stdout, "%s%d: ", device->device_name,
777 		device->dev_unit_num);
778 	scsi_print_inquiry(inq_buf);
779 
780 	free(inq_buf);
781 
782 	return(0);
783 }
784 
785 static int
786 scsiserial(struct cam_device *device, int retry_count, int timeout)
787 {
788 	union ccb *ccb;
789 	struct scsi_vpd_unit_serial_number *serial_buf;
790 	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
791 	int error = 0;
792 
793 	ccb = cam_getccb(device);
794 
795 	if (ccb == NULL) {
796 		warnx("couldn't allocate CCB");
797 		return(1);
798 	}
799 
800 	/* cam_getccb cleans up the header, caller has to zero the payload */
801 	bzero(&(&ccb->ccb_h)[1],
802 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
803 
804 	serial_buf = (struct scsi_vpd_unit_serial_number *)
805 		malloc(sizeof(*serial_buf));
806 
807 	if (serial_buf == NULL) {
808 		cam_freeccb(ccb);
809 		warnx("can't malloc memory for serial number");
810 		return(1);
811 	}
812 
813 	scsi_inquiry(&ccb->csio,
814 		     /*retries*/ retry_count,
815 		     /*cbfcnp*/ NULL,
816 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
817 		     /* inq_buf */ (u_int8_t *)serial_buf,
818 		     /* inq_len */ sizeof(*serial_buf),
819 		     /* evpd */ 1,
820 		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
821 		     /* sense_len */ SSD_FULL_SIZE,
822 		     /* timeout */ timeout ? timeout : 5000);
823 
824 	/* Disable freezing the device queue */
825 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
826 
827 	if (arglist & CAM_ARG_ERR_RECOVER)
828 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
829 
830 	if (cam_send_ccb(device, ccb) < 0) {
831 		warn("error getting serial number");
832 
833 		if (arglist & CAM_ARG_VERBOSE) {
834 			cam_error_print(device, ccb, CAM_ESF_ALL,
835 					CAM_EPF_ALL, stderr);
836 		}
837 
838 		cam_freeccb(ccb);
839 		free(serial_buf);
840 		return(1);
841 	}
842 
843 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
844 		error = 1;
845 
846 		if (arglist & CAM_ARG_VERBOSE) {
847 			cam_error_print(device, ccb, CAM_ESF_ALL,
848 					CAM_EPF_ALL, stderr);
849 		}
850 	}
851 
852 	cam_freeccb(ccb);
853 
854 	if (error != 0) {
855 		free(serial_buf);
856 		return(error);
857 	}
858 
859 	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
860 	serial_num[serial_buf->length] = '\0';
861 
862 	if ((arglist & CAM_ARG_GET_STDINQ)
863 	 || (arglist & CAM_ARG_GET_XFERRATE))
864 		fprintf(stdout, "%s%d: Serial Number ",
865 			device->device_name, device->dev_unit_num);
866 
867 	fprintf(stdout, "%.60s\n", serial_num);
868 
869 	free(serial_buf);
870 
871 	return(0);
872 }
873 
874 static int
875 scsixferrate(struct cam_device *device)
876 {
877 	u_int32_t freq = 0;
878 	u_int32_t speed = 0;
879 	union ccb *ccb;
880 	u_int mb;
881 	int retval = 0;
882 
883 	ccb = cam_getccb(device);
884 
885 	if (ccb == NULL) {
886 		warnx("couldn't allocate CCB");
887 		return(1);
888 	}
889 
890 	bzero(&(&ccb->ccb_h)[1],
891 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
892 
893 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
894 	ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
895 
896 	if (((retval = cam_send_ccb(device, ccb)) < 0)
897 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
898 		const char error_string[] = "error getting transfer settings";
899 
900 		if (retval < 0)
901 			warn(error_string);
902 		else
903 			warnx(error_string);
904 
905 		if (arglist & CAM_ARG_VERBOSE)
906 			cam_error_print(device, ccb, CAM_ESF_ALL,
907 					CAM_EPF_ALL, stderr);
908 
909 		retval = 1;
910 
911 		goto xferrate_bailout;
912 
913 	}
914 
915 	if (ccb->cts.transport == XPORT_SPI) {
916 		struct ccb_trans_settings_spi *spi =
917 		    &ccb->cts.xport_specific.spi;
918 
919 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
920 			freq = scsi_calc_syncsrate(spi->sync_period);
921 			speed = freq;
922 		} else {
923 			struct ccb_pathinq cpi;
924 
925 			retval = get_cpi(device, &cpi);
926 			if (retval == 0) {
927 				speed = cpi.base_transfer_speed;
928 				freq = 0;
929 			}
930 		}
931 
932 		fprintf(stdout, "%s%d: ", device->device_name,
933 			device->dev_unit_num);
934 
935 		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
936 			speed *= (0x01 << spi->bus_width);
937 		}
938 
939 		mb = speed / 1000;
940 
941 		if (mb > 0)
942 			fprintf(stdout, "%d.%03dMB/s transfers ",
943 				mb, speed % 1000);
944 		else
945 			fprintf(stdout, "%dKB/s transfers ",
946 				speed);
947 
948 		if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
949 		 && (spi->sync_offset != 0))
950 			fprintf(stdout, "(%d.%03dMHz, offset %d", freq / 1000,
951 				freq % 1000, spi->sync_offset);
952 
953 		if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
954 		 && (spi->bus_width > 0)) {
955 			if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
956 			 && (spi->sync_offset != 0)) {
957 				fprintf(stdout, ", ");
958 			} else {
959 				fprintf(stdout, " (");
960 			}
961 			fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
962 		} else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
963 		 && (spi->sync_offset != 0)) {
964 			fprintf(stdout, ")");
965 		}
966 	} else {
967 		struct ccb_pathinq cpi;
968 
969 		retval = get_cpi(device, &cpi);
970 
971 		if (retval != 0)
972 			goto xferrate_bailout;
973 
974 		speed = cpi.base_transfer_speed;
975 		freq = 0;
976 
977 		mb = speed / 1000;
978 
979 		if (mb > 0)
980 			fprintf(stdout, "%d.%03dMB/s transfers ",
981 				mb, speed % 1000);
982 		else
983 			fprintf(stdout, "%dKB/s transfers ",
984 				speed);
985 	}
986 
987 	if (ccb->cts.protocol == PROTO_SCSI) {
988 		struct ccb_trans_settings_scsi *scsi =
989 		    &ccb->cts.proto_specific.scsi;
990 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
991 			if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
992 				fprintf(stdout, ", Command Queueing Enabled");
993 			}
994 		}
995 	}
996 
997         fprintf(stdout, "\n");
998 
999 xferrate_bailout:
1000 
1001 	cam_freeccb(ccb);
1002 
1003 	return(retval);
1004 }
1005 
1006 static void
1007 atacapprint(struct ata_params *parm)
1008 {
1009 	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1010 				((u_int32_t)parm->lba_size_2 << 16);
1011 
1012 	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1013 				((u_int64_t)parm->lba_size48_2 << 16) |
1014 				((u_int64_t)parm->lba_size48_3 << 32) |
1015 				((u_int64_t)parm->lba_size48_4 << 48);
1016 
1017 	printf("\n");
1018 	printf("Protocol              ");
1019 	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1020 		if (parm->satacapabilities & ATA_SATA_GEN2)
1021 			printf("SATA revision 2.x\n");
1022 		else if (parm->satacapabilities & ATA_SATA_GEN1)
1023 			printf("SATA revision 1.x\n");
1024 		else
1025 			printf("Unknown SATA revision\n");
1026 	}
1027 	else
1028 		printf("ATA/ATAPI revision %d\n", ata_version(parm->version_major));
1029 	printf("device model          %.40s\n", parm->model);
1030 	printf("serial number         %.20s\n", parm->serial);
1031 	printf("firmware revision     %.8s\n", parm->revision);
1032 
1033 	printf("cylinders             %d\n", parm->cylinders);
1034 	printf("heads                 %d\n", parm->heads);
1035 	printf("sectors/track         %d\n", parm->sectors);
1036 
1037 	if (parm->config == ATA_PROTO_CFA ||
1038 	    (parm->support.command2 & ATA_SUPPORT_CFA))
1039 		printf("CFA supported\n");
1040 
1041 	printf("lba%ssupported         ",
1042 		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1043 	if (lbasize)
1044 		printf("%d sectors\n", lbasize);
1045 	else
1046 		printf("\n");
1047 
1048 	printf("lba48%ssupported       ",
1049 		parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1050 	if (lbasize48)
1051 		printf("%ju sectors\n", (uintmax_t)lbasize48);
1052 	else
1053 		printf("\n");
1054 
1055 	printf("dma%ssupported\n",
1056 		parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1057 
1058 	printf("overlap%ssupported\n",
1059 		parm->capabilities1 & ATA_SUPPORT_OVERLAP ? " " : " not ");
1060 
1061 	printf("\nFeature                      "
1062 		"Support  Enable    Value           Vendor\n");
1063 
1064 	printf("write cache                    %s	%s\n",
1065 		parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1066 		parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1067 
1068 	printf("read ahead                     %s	%s\n",
1069 		parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1070 		parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1071 
1072 	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1073 		printf("Native Command Queuing (NCQ)   %s	%s"
1074 			"	%d/0x%02X\n",
1075 			parm->satacapabilities & ATA_SUPPORT_NCQ ?
1076 				"yes" : "no", " -",
1077 			(parm->satacapabilities & ATA_SUPPORT_NCQ) ?
1078 				ATA_QUEUE_LEN(parm->queue) : 0,
1079 			(parm->satacapabilities & ATA_SUPPORT_NCQ) ?
1080 				ATA_QUEUE_LEN(parm->queue) : 0);
1081 	}
1082 	printf("Tagged Command Queuing (TCQ)   %s	%s	%d/0x%02X\n",
1083 		parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1084 		parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1085 		ATA_QUEUE_LEN(parm->queue), ATA_QUEUE_LEN(parm->queue));
1086 
1087 	printf("SMART                          %s	%s\n",
1088 		parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1089 		parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1090 
1091 	printf("microcode download             %s	%s\n",
1092 		parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1093 		parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1094 
1095 	printf("security                       %s	%s\n",
1096 		parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1097 		parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1098 
1099 	printf("power management               %s	%s\n",
1100 		parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1101 		parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1102 
1103 	printf("advanced power management      %s	%s	%d/0x%02X\n",
1104 		parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1105 		parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1106 		parm->apm_value, parm->apm_value);
1107 
1108 	printf("automatic acoustic management  %s	%s	"
1109 		"%d/0x%02X	%d/0x%02X\n",
1110 		parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1111 		parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1112 		ATA_ACOUSTIC_CURRENT(parm->acoustic),
1113 		ATA_ACOUSTIC_CURRENT(parm->acoustic),
1114 		ATA_ACOUSTIC_VENDOR(parm->acoustic),
1115 		ATA_ACOUSTIC_VENDOR(parm->acoustic));
1116 }
1117 
1118 
1119 static int
1120 ataidentify(struct cam_device *device, int retry_count, int timeout)
1121 {
1122 	union ccb *ccb;
1123 	struct ata_params *ident_buf;
1124 	u_int i, error = 0;
1125 	int16_t *ptr;
1126 
1127 	ccb = cam_getccb(device);
1128 
1129 	if (ccb == NULL) {
1130 		warnx("couldn't allocate CCB");
1131 		return(1);
1132 	}
1133 
1134 	/* cam_getccb cleans up the header, caller has to zero the payload */
1135 	bzero(&(&ccb->ccb_h)[1],
1136 	      sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1137 
1138 	ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1139 
1140 	if (ptr == NULL) {
1141 		cam_freeccb(ccb);
1142 		warnx("can't malloc memory for identify\n");
1143 		return(1);
1144 	}
1145 	bzero(ptr, sizeof(struct ata_params));
1146 
1147 	cam_fill_ataio(&ccb->ataio,
1148 		      retry_count,
1149 		      NULL,
1150 		      /*flags*/CAM_DIR_IN,
1151 		      MSG_SIMPLE_Q_TAG,
1152 		      /*data_ptr*/(u_int8_t *)ptr,
1153 		      /*dxfer_len*/sizeof(struct ata_params),
1154 		      timeout ? timeout : 30 * 1000);
1155 //	if (periph->path->device->protocol == PROTO_ATA)
1156 		ata_36bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1157 //	else
1158 //		ata_36bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1159 
1160 	/* Disable freezing the device queue */
1161 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1162 
1163 	if (arglist & CAM_ARG_ERR_RECOVER)
1164 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1165 
1166 	if (cam_send_ccb(device, ccb) < 0) {
1167 		perror("error sending ATA identify");
1168 
1169 		if (arglist & CAM_ARG_VERBOSE) {
1170 			cam_error_print(device, ccb, CAM_ESF_ALL,
1171 					CAM_EPF_ALL, stderr);
1172 		}
1173 
1174 		free(ptr);
1175 		cam_freeccb(ccb);
1176 		return(1);
1177 	}
1178 
1179 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1180 		error = 1;
1181 
1182 		if (arglist & CAM_ARG_VERBOSE) {
1183 			cam_error_print(device, ccb, CAM_ESF_ALL,
1184 					CAM_EPF_ALL, stderr);
1185 		}
1186 	}
1187 
1188 	cam_freeccb(ccb);
1189 
1190 	if (error != 0) {
1191 		free(ptr);
1192 		return(error);
1193 	}
1194 
1195 	for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1196 		ptr[i] = le16toh(ptr[i]);
1197 	ident_buf = (struct ata_params *)ptr;
1198 
1199 	if (strncmp(ident_buf->model, "FX", 2) &&
1200 	    strncmp(ident_buf->model, "NEC", 3) &&
1201 	    strncmp(ident_buf->model, "Pioneer", 7) &&
1202 	    strncmp(ident_buf->model, "SHARP", 5)) {
1203 		ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1204 		ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1205 		ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1206 	}
1207 	ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1208 	ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1209 	ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1210 	ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1211 	ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1212 	ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1213 
1214 	fprintf(stdout, "%s%d: ", device->device_name,
1215 		device->dev_unit_num);
1216 	ata_print_ident(ident_buf);
1217 	atacapprint(ident_buf);
1218 
1219 	free(ident_buf);
1220 
1221 	return(0);
1222 }
1223 #endif /* MINIMALISTIC */
1224 
1225 /*
1226  * Parse out a bus, or a bus, target and lun in the following
1227  * format:
1228  * bus
1229  * bus:target
1230  * bus:target:lun
1231  *
1232  * Returns the number of parsed components, or 0.
1233  */
1234 static int
1235 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1236 {
1237 	char *tmpstr;
1238 	int convs = 0;
1239 
1240 	while (isspace(*tstr) && (*tstr != '\0'))
1241 		tstr++;
1242 
1243 	tmpstr = (char *)strtok(tstr, ":");
1244 	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1245 		*bus = strtol(tmpstr, NULL, 0);
1246 		*arglst |= CAM_ARG_BUS;
1247 		convs++;
1248 		tmpstr = (char *)strtok(NULL, ":");
1249 		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1250 			*target = strtol(tmpstr, NULL, 0);
1251 			*arglst |= CAM_ARG_TARGET;
1252 			convs++;
1253 			tmpstr = (char *)strtok(NULL, ":");
1254 			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1255 				*lun = strtol(tmpstr, NULL, 0);
1256 				*arglst |= CAM_ARG_LUN;
1257 				convs++;
1258 			}
1259 		}
1260 	}
1261 
1262 	return convs;
1263 }
1264 
1265 static int
1266 dorescan_or_reset(int argc, char **argv, int rescan)
1267 {
1268 	static const char must[] =
1269 		"you must specify \"all\", a bus, or a bus:target:lun to %s";
1270 	int rv, error = 0;
1271 	int bus = -1, target = -1, lun = -1;
1272 	char *tstr;
1273 
1274 	if (argc < 3) {
1275 		warnx(must, rescan? "rescan" : "reset");
1276 		return(1);
1277 	}
1278 
1279 	tstr = argv[optind];
1280 	while (isspace(*tstr) && (*tstr != '\0'))
1281 		tstr++;
1282 	if (strncasecmp(tstr, "all", strlen("all")) == 0)
1283 		arglist |= CAM_ARG_BUS;
1284 	else {
1285 		rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1286 		if (rv != 1 && rv != 3) {
1287 			warnx(must, rescan? "rescan" : "reset");
1288 			return(1);
1289 		}
1290 	}
1291 
1292 	if ((arglist & CAM_ARG_BUS)
1293 	    && (arglist & CAM_ARG_TARGET)
1294 	    && (arglist & CAM_ARG_LUN))
1295 		error = scanlun_or_reset_dev(bus, target, lun, rescan);
1296 	else
1297 		error = rescan_or_reset_bus(bus, rescan);
1298 
1299 	return(error);
1300 }
1301 
1302 static int
1303 rescan_or_reset_bus(int bus, int rescan)
1304 {
1305 	union ccb ccb, matchccb;
1306 	int fd, retval;
1307 	int bufsize;
1308 
1309 	retval = 0;
1310 
1311 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1312 		warnx("error opening transport layer device %s", XPT_DEVICE);
1313 		warn("%s", XPT_DEVICE);
1314 		return(1);
1315 	}
1316 
1317 	if (bus != -1) {
1318 		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1319 		ccb.ccb_h.path_id = bus;
1320 		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1321 		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1322 		ccb.crcn.flags = CAM_FLAG_NONE;
1323 
1324 		/* run this at a low priority */
1325 		ccb.ccb_h.pinfo.priority = 5;
1326 
1327 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1328 			warn("CAMIOCOMMAND ioctl failed");
1329 			close(fd);
1330 			return(1);
1331 		}
1332 
1333 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1334 			fprintf(stdout, "%s of bus %d was successful\n",
1335 			    rescan ? "Re-scan" : "Reset", bus);
1336 		} else {
1337 			fprintf(stdout, "%s of bus %d returned error %#x\n",
1338 				rescan ? "Re-scan" : "Reset", bus,
1339 				ccb.ccb_h.status & CAM_STATUS_MASK);
1340 			retval = 1;
1341 		}
1342 
1343 		close(fd);
1344 		return(retval);
1345 
1346 	}
1347 
1348 
1349 	/*
1350 	 * The right way to handle this is to modify the xpt so that it can
1351 	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
1352 	 * that isn't implemented, so instead we enumerate the busses and
1353 	 * send the rescan or reset to those busses in the case where the
1354 	 * given bus is -1 (wildcard).  We don't send a rescan or reset
1355 	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1356 	 * no-op, sending a rescan to the xpt bus would result in a status of
1357 	 * CAM_REQ_INVALID.
1358 	 */
1359 	bzero(&(&matchccb.ccb_h)[1],
1360 	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1361 	matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1362 	bufsize = sizeof(struct dev_match_result) * 20;
1363 	matchccb.cdm.match_buf_len = bufsize;
1364 	matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1365 	if (matchccb.cdm.matches == NULL) {
1366 		warnx("can't malloc memory for matches");
1367 		retval = 1;
1368 		goto bailout;
1369 	}
1370 	matchccb.cdm.num_matches = 0;
1371 
1372 	matchccb.cdm.num_patterns = 1;
1373 	matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1374 
1375 	matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1376 		matchccb.cdm.pattern_buf_len);
1377 	if (matchccb.cdm.patterns == NULL) {
1378 		warnx("can't malloc memory for patterns");
1379 		retval = 1;
1380 		goto bailout;
1381 	}
1382 	matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1383 	matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1384 
1385 	do {
1386 		unsigned int i;
1387 
1388 		if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1389 			warn("CAMIOCOMMAND ioctl failed");
1390 			retval = 1;
1391 			goto bailout;
1392 		}
1393 
1394 		if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1395 		 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1396 		   && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1397 			warnx("got CAM error %#x, CDM error %d\n",
1398 			      matchccb.ccb_h.status, matchccb.cdm.status);
1399 			retval = 1;
1400 			goto bailout;
1401 		}
1402 
1403 		for (i = 0; i < matchccb.cdm.num_matches; i++) {
1404 			struct bus_match_result *bus_result;
1405 
1406 			/* This shouldn't happen. */
1407 			if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1408 				continue;
1409 
1410 			bus_result = &matchccb.cdm.matches[i].result.bus_result;
1411 
1412 			/*
1413 			 * We don't want to rescan or reset the xpt bus.
1414 			 * See above.
1415 			 */
1416 			if ((int)bus_result->path_id == -1)
1417 				continue;
1418 
1419 			ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1420 						       XPT_RESET_BUS;
1421 			ccb.ccb_h.path_id = bus_result->path_id;
1422 			ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1423 			ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1424 			ccb.crcn.flags = CAM_FLAG_NONE;
1425 
1426 			/* run this at a low priority */
1427 			ccb.ccb_h.pinfo.priority = 5;
1428 
1429 			if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1430 				warn("CAMIOCOMMAND ioctl failed");
1431 				retval = 1;
1432 				goto bailout;
1433 			}
1434 
1435 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1436 				fprintf(stdout, "%s of bus %d was successful\n",
1437 					rescan? "Re-scan" : "Reset",
1438 					bus_result->path_id);
1439 			} else {
1440 				/*
1441 				 * Don't bail out just yet, maybe the other
1442 				 * rescan or reset commands will complete
1443 				 * successfully.
1444 				 */
1445 				fprintf(stderr, "%s of bus %d returned error "
1446 					"%#x\n", rescan? "Re-scan" : "Reset",
1447 					bus_result->path_id,
1448 					ccb.ccb_h.status & CAM_STATUS_MASK);
1449 				retval = 1;
1450 			}
1451 		}
1452 	} while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1453 		 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1454 
1455 bailout:
1456 
1457 	if (fd != -1)
1458 		close(fd);
1459 
1460 	if (matchccb.cdm.patterns != NULL)
1461 		free(matchccb.cdm.patterns);
1462 	if (matchccb.cdm.matches != NULL)
1463 		free(matchccb.cdm.matches);
1464 
1465 	return(retval);
1466 }
1467 
1468 static int
1469 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1470 {
1471 	union ccb ccb;
1472 	struct cam_device *device;
1473 	int fd;
1474 
1475 	device = NULL;
1476 
1477 	if (bus < 0) {
1478 		warnx("invalid bus number %d", bus);
1479 		return(1);
1480 	}
1481 
1482 	if (target < 0) {
1483 		warnx("invalid target number %d", target);
1484 		return(1);
1485 	}
1486 
1487 	if (lun < 0) {
1488 		warnx("invalid lun number %d", lun);
1489 		return(1);
1490 	}
1491 
1492 	fd = -1;
1493 
1494 	bzero(&ccb, sizeof(union ccb));
1495 
1496 	if (scan) {
1497 		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1498 			warnx("error opening transport layer device %s\n",
1499 			    XPT_DEVICE);
1500 			warn("%s", XPT_DEVICE);
1501 			return(1);
1502 		}
1503 	} else {
1504 		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1505 		if (device == NULL) {
1506 			warnx("%s", cam_errbuf);
1507 			return(1);
1508 		}
1509 	}
1510 
1511 	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1512 	ccb.ccb_h.path_id = bus;
1513 	ccb.ccb_h.target_id = target;
1514 	ccb.ccb_h.target_lun = lun;
1515 	ccb.ccb_h.timeout = 5000;
1516 	ccb.crcn.flags = CAM_FLAG_NONE;
1517 
1518 	/* run this at a low priority */
1519 	ccb.ccb_h.pinfo.priority = 5;
1520 
1521 	if (scan) {
1522 		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1523 			warn("CAMIOCOMMAND ioctl failed");
1524 			close(fd);
1525 			return(1);
1526 		}
1527 	} else {
1528 		if (cam_send_ccb(device, &ccb) < 0) {
1529 			warn("error sending XPT_RESET_DEV CCB");
1530 			cam_close_device(device);
1531 			return(1);
1532 		}
1533 	}
1534 
1535 	if (scan)
1536 		close(fd);
1537 	else
1538 		cam_close_device(device);
1539 
1540 	/*
1541 	 * An error code of CAM_BDR_SENT is normal for a BDR request.
1542 	 */
1543 	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1544 	 || ((!scan)
1545 	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1546 		fprintf(stdout, "%s of %d:%d:%d was successful\n",
1547 		    scan? "Re-scan" : "Reset", bus, target, lun);
1548 		return(0);
1549 	} else {
1550 		fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1551 		    scan? "Re-scan" : "Reset", bus, target, lun,
1552 		    ccb.ccb_h.status & CAM_STATUS_MASK);
1553 		return(1);
1554 	}
1555 }
1556 
1557 #ifndef MINIMALISTIC
1558 static int
1559 readdefects(struct cam_device *device, int argc, char **argv,
1560 	    char *combinedopt, int retry_count, int timeout)
1561 {
1562 	union ccb *ccb = NULL;
1563 	struct scsi_read_defect_data_10 *rdd_cdb;
1564 	u_int8_t *defect_list = NULL;
1565 	u_int32_t dlist_length = 65000;
1566 	u_int32_t returned_length = 0;
1567 	u_int32_t num_returned = 0;
1568 	u_int8_t returned_format;
1569 	unsigned int i;
1570 	int c, error = 0;
1571 	int lists_specified = 0;
1572 
1573 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1574 		switch(c){
1575 		case 'f':
1576 		{
1577 			char *tstr;
1578 			tstr = optarg;
1579 			while (isspace(*tstr) && (*tstr != '\0'))
1580 				tstr++;
1581 			if (strcmp(tstr, "block") == 0)
1582 				arglist |= CAM_ARG_FORMAT_BLOCK;
1583 			else if (strcmp(tstr, "bfi") == 0)
1584 				arglist |= CAM_ARG_FORMAT_BFI;
1585 			else if (strcmp(tstr, "phys") == 0)
1586 				arglist |= CAM_ARG_FORMAT_PHYS;
1587 			else {
1588 				error = 1;
1589 				warnx("invalid defect format %s", tstr);
1590 				goto defect_bailout;
1591 			}
1592 			break;
1593 		}
1594 		case 'G':
1595 			arglist |= CAM_ARG_GLIST;
1596 			break;
1597 		case 'P':
1598 			arglist |= CAM_ARG_PLIST;
1599 			break;
1600 		default:
1601 			break;
1602 		}
1603 	}
1604 
1605 	ccb = cam_getccb(device);
1606 
1607 	/*
1608 	 * Hopefully 65000 bytes is enough to hold the defect list.  If it
1609 	 * isn't, the disk is probably dead already.  We'd have to go with
1610 	 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1611 	 * to hold them all.
1612 	 */
1613 	defect_list = malloc(dlist_length);
1614 	if (defect_list == NULL) {
1615 		warnx("can't malloc memory for defect list");
1616 		error = 1;
1617 		goto defect_bailout;
1618 	}
1619 
1620 	rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1621 
1622 	/*
1623 	 * cam_getccb() zeros the CCB header only.  So we need to zero the
1624 	 * payload portion of the ccb.
1625 	 */
1626 	bzero(&(&ccb->ccb_h)[1],
1627 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1628 
1629 	cam_fill_csio(&ccb->csio,
1630 		      /*retries*/ retry_count,
1631 		      /*cbfcnp*/ NULL,
1632 		      /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1633 					      CAM_PASS_ERR_RECOVER : 0),
1634 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
1635 		      /*data_ptr*/ defect_list,
1636 		      /*dxfer_len*/ dlist_length,
1637 		      /*sense_len*/ SSD_FULL_SIZE,
1638 		      /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1639 		      /*timeout*/ timeout ? timeout : 5000);
1640 
1641 	rdd_cdb->opcode = READ_DEFECT_DATA_10;
1642 	if (arglist & CAM_ARG_FORMAT_BLOCK)
1643 		rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1644 	else if (arglist & CAM_ARG_FORMAT_BFI)
1645 		rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1646 	else if (arglist & CAM_ARG_FORMAT_PHYS)
1647 		rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1648 	else {
1649 		error = 1;
1650 		warnx("no defect list format specified");
1651 		goto defect_bailout;
1652 	}
1653 	if (arglist & CAM_ARG_PLIST) {
1654 		rdd_cdb->format |= SRDD10_PLIST;
1655 		lists_specified++;
1656 	}
1657 
1658 	if (arglist & CAM_ARG_GLIST) {
1659 		rdd_cdb->format |= SRDD10_GLIST;
1660 		lists_specified++;
1661 	}
1662 
1663 	scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1664 
1665 	/* Disable freezing the device queue */
1666 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1667 
1668 	if (cam_send_ccb(device, ccb) < 0) {
1669 		perror("error reading defect list");
1670 
1671 		if (arglist & CAM_ARG_VERBOSE) {
1672 			cam_error_print(device, ccb, CAM_ESF_ALL,
1673 					CAM_EPF_ALL, stderr);
1674 		}
1675 
1676 		error = 1;
1677 		goto defect_bailout;
1678 	}
1679 
1680 	returned_length = scsi_2btoul(((struct
1681 		scsi_read_defect_data_hdr_10 *)defect_list)->length);
1682 
1683 	returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1684 			defect_list)->format;
1685 
1686 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1687 	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1688 	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1689 		struct scsi_sense_data *sense;
1690 		int error_code, sense_key, asc, ascq;
1691 
1692 		sense = &ccb->csio.sense_data;
1693 		scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1694 
1695 		/*
1696 		 * According to the SCSI spec, if the disk doesn't support
1697 		 * the requested format, it will generally return a sense
1698 		 * key of RECOVERED ERROR, and an additional sense code
1699 		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1700 		 * also check to make sure that the returned length is
1701 		 * greater than 0, and then print out whatever format the
1702 		 * disk gave us.
1703 		 */
1704 		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1705 		 && (asc == 0x1c) && (ascq == 0x00)
1706 		 && (returned_length > 0)) {
1707 			warnx("requested defect format not available");
1708 			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1709 			case SRDD10_BLOCK_FORMAT:
1710 				warnx("Device returned block format");
1711 				break;
1712 			case SRDD10_BYTES_FROM_INDEX_FORMAT:
1713 				warnx("Device returned bytes from index"
1714 				      " format");
1715 				break;
1716 			case SRDD10_PHYSICAL_SECTOR_FORMAT:
1717 				warnx("Device returned physical sector format");
1718 				break;
1719 			default:
1720 				error = 1;
1721 				warnx("Device returned unknown defect"
1722 				     " data format %#x", returned_format);
1723 				goto defect_bailout;
1724 				break; /* NOTREACHED */
1725 			}
1726 		} else {
1727 			error = 1;
1728 			warnx("Error returned from read defect data command");
1729 			if (arglist & CAM_ARG_VERBOSE)
1730 				cam_error_print(device, ccb, CAM_ESF_ALL,
1731 						CAM_EPF_ALL, stderr);
1732 			goto defect_bailout;
1733 		}
1734 	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1735 		error = 1;
1736 		warnx("Error returned from read defect data command");
1737 		if (arglist & CAM_ARG_VERBOSE)
1738 			cam_error_print(device, ccb, CAM_ESF_ALL,
1739 					CAM_EPF_ALL, stderr);
1740 		goto defect_bailout;
1741 	}
1742 
1743 	/*
1744 	 * XXX KDM  I should probably clean up the printout format for the
1745 	 * disk defects.
1746 	 */
1747 	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1748 		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1749 		{
1750 			struct scsi_defect_desc_phys_sector *dlist;
1751 
1752 			dlist = (struct scsi_defect_desc_phys_sector *)
1753 				(defect_list +
1754 				sizeof(struct scsi_read_defect_data_hdr_10));
1755 
1756 			num_returned = returned_length /
1757 				sizeof(struct scsi_defect_desc_phys_sector);
1758 
1759 			fprintf(stderr, "Got %d defect", num_returned);
1760 
1761 			if ((lists_specified == 0) || (num_returned == 0)) {
1762 				fprintf(stderr, "s.\n");
1763 				break;
1764 			} else if (num_returned == 1)
1765 				fprintf(stderr, ":\n");
1766 			else
1767 				fprintf(stderr, "s:\n");
1768 
1769 			for (i = 0; i < num_returned; i++) {
1770 				fprintf(stdout, "%d:%d:%d\n",
1771 					scsi_3btoul(dlist[i].cylinder),
1772 					dlist[i].head,
1773 					scsi_4btoul(dlist[i].sector));
1774 			}
1775 			break;
1776 		}
1777 		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1778 		{
1779 			struct scsi_defect_desc_bytes_from_index *dlist;
1780 
1781 			dlist = (struct scsi_defect_desc_bytes_from_index *)
1782 				(defect_list +
1783 				sizeof(struct scsi_read_defect_data_hdr_10));
1784 
1785 			num_returned = returned_length /
1786 			      sizeof(struct scsi_defect_desc_bytes_from_index);
1787 
1788 			fprintf(stderr, "Got %d defect", num_returned);
1789 
1790 			if ((lists_specified == 0) || (num_returned == 0)) {
1791 				fprintf(stderr, "s.\n");
1792 				break;
1793 			} else if (num_returned == 1)
1794 				fprintf(stderr, ":\n");
1795 			else
1796 				fprintf(stderr, "s:\n");
1797 
1798 			for (i = 0; i < num_returned; i++) {
1799 				fprintf(stdout, "%d:%d:%d\n",
1800 					scsi_3btoul(dlist[i].cylinder),
1801 					dlist[i].head,
1802 					scsi_4btoul(dlist[i].bytes_from_index));
1803 			}
1804 			break;
1805 		}
1806 		case SRDDH10_BLOCK_FORMAT:
1807 		{
1808 			struct scsi_defect_desc_block *dlist;
1809 
1810 			dlist = (struct scsi_defect_desc_block *)(defect_list +
1811 				sizeof(struct scsi_read_defect_data_hdr_10));
1812 
1813 			num_returned = returned_length /
1814 			      sizeof(struct scsi_defect_desc_block);
1815 
1816 			fprintf(stderr, "Got %d defect", num_returned);
1817 
1818 			if ((lists_specified == 0) || (num_returned == 0)) {
1819 				fprintf(stderr, "s.\n");
1820 				break;
1821 			} else if (num_returned == 1)
1822 				fprintf(stderr, ":\n");
1823 			else
1824 				fprintf(stderr, "s:\n");
1825 
1826 			for (i = 0; i < num_returned; i++)
1827 				fprintf(stdout, "%u\n",
1828 					scsi_4btoul(dlist[i].address));
1829 			break;
1830 		}
1831 		default:
1832 			fprintf(stderr, "Unknown defect format %d\n",
1833 				returned_format & SRDDH10_DLIST_FORMAT_MASK);
1834 			error = 1;
1835 			break;
1836 	}
1837 defect_bailout:
1838 
1839 	if (defect_list != NULL)
1840 		free(defect_list);
1841 
1842 	if (ccb != NULL)
1843 		cam_freeccb(ccb);
1844 
1845 	return(error);
1846 }
1847 #endif /* MINIMALISTIC */
1848 
1849 #if 0
1850 void
1851 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
1852 {
1853 	union ccb *ccb;
1854 
1855 	ccb = cam_getccb(device);
1856 
1857 	cam_freeccb(ccb);
1858 }
1859 #endif
1860 
1861 #ifndef MINIMALISTIC
1862 void
1863 mode_sense(struct cam_device *device, int mode_page, int page_control,
1864 	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
1865 {
1866 	union ccb *ccb;
1867 	int retval;
1868 
1869 	ccb = cam_getccb(device);
1870 
1871 	if (ccb == NULL)
1872 		errx(1, "mode_sense: couldn't allocate CCB");
1873 
1874 	bzero(&(&ccb->ccb_h)[1],
1875 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1876 
1877 	scsi_mode_sense(&ccb->csio,
1878 			/* retries */ retry_count,
1879 			/* cbfcnp */ NULL,
1880 			/* tag_action */ MSG_SIMPLE_Q_TAG,
1881 			/* dbd */ dbd,
1882 			/* page_code */ page_control << 6,
1883 			/* page */ mode_page,
1884 			/* param_buf */ data,
1885 			/* param_len */ datalen,
1886 			/* sense_len */ SSD_FULL_SIZE,
1887 			/* timeout */ timeout ? timeout : 5000);
1888 
1889 	if (arglist & CAM_ARG_ERR_RECOVER)
1890 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1891 
1892 	/* Disable freezing the device queue */
1893 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1894 
1895 	if (((retval = cam_send_ccb(device, ccb)) < 0)
1896 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1897 		if (arglist & CAM_ARG_VERBOSE) {
1898 			cam_error_print(device, ccb, CAM_ESF_ALL,
1899 					CAM_EPF_ALL, stderr);
1900 		}
1901 		cam_freeccb(ccb);
1902 		cam_close_device(device);
1903 		if (retval < 0)
1904 			err(1, "error sending mode sense command");
1905 		else
1906 			errx(1, "error sending mode sense command");
1907 	}
1908 
1909 	cam_freeccb(ccb);
1910 }
1911 
1912 void
1913 mode_select(struct cam_device *device, int save_pages, int retry_count,
1914 	   int timeout, u_int8_t *data, int datalen)
1915 {
1916 	union ccb *ccb;
1917 	int retval;
1918 
1919 	ccb = cam_getccb(device);
1920 
1921 	if (ccb == NULL)
1922 		errx(1, "mode_select: couldn't allocate CCB");
1923 
1924 	bzero(&(&ccb->ccb_h)[1],
1925 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1926 
1927 	scsi_mode_select(&ccb->csio,
1928 			 /* retries */ retry_count,
1929 			 /* cbfcnp */ NULL,
1930 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
1931 			 /* scsi_page_fmt */ 1,
1932 			 /* save_pages */ save_pages,
1933 			 /* param_buf */ data,
1934 			 /* param_len */ datalen,
1935 			 /* sense_len */ SSD_FULL_SIZE,
1936 			 /* timeout */ timeout ? timeout : 5000);
1937 
1938 	if (arglist & CAM_ARG_ERR_RECOVER)
1939 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1940 
1941 	/* Disable freezing the device queue */
1942 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1943 
1944 	if (((retval = cam_send_ccb(device, ccb)) < 0)
1945 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1946 		if (arglist & CAM_ARG_VERBOSE) {
1947 			cam_error_print(device, ccb, CAM_ESF_ALL,
1948 					CAM_EPF_ALL, stderr);
1949 		}
1950 		cam_freeccb(ccb);
1951 		cam_close_device(device);
1952 
1953 		if (retval < 0)
1954 			err(1, "error sending mode select command");
1955 		else
1956 			errx(1, "error sending mode select command");
1957 
1958 	}
1959 
1960 	cam_freeccb(ccb);
1961 }
1962 
1963 void
1964 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
1965 	 int retry_count, int timeout)
1966 {
1967 	int c, mode_page = -1, page_control = 0;
1968 	int binary = 0, list = 0;
1969 
1970 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1971 		switch(c) {
1972 		case 'b':
1973 			binary = 1;
1974 			break;
1975 		case 'd':
1976 			arglist |= CAM_ARG_DBD;
1977 			break;
1978 		case 'e':
1979 			arglist |= CAM_ARG_MODE_EDIT;
1980 			break;
1981 		case 'l':
1982 			list = 1;
1983 			break;
1984 		case 'm':
1985 			mode_page = strtol(optarg, NULL, 0);
1986 			if (mode_page < 0)
1987 				errx(1, "invalid mode page %d", mode_page);
1988 			break;
1989 		case 'P':
1990 			page_control = strtol(optarg, NULL, 0);
1991 			if ((page_control < 0) || (page_control > 3))
1992 				errx(1, "invalid page control field %d",
1993 				     page_control);
1994 			arglist |= CAM_ARG_PAGE_CNTL;
1995 			break;
1996 		default:
1997 			break;
1998 		}
1999 	}
2000 
2001 	if (mode_page == -1 && list == 0)
2002 		errx(1, "you must specify a mode page!");
2003 
2004 	if (list) {
2005 		mode_list(device, page_control, arglist & CAM_ARG_DBD,
2006 		    retry_count, timeout);
2007 	} else {
2008 		mode_edit(device, mode_page, page_control,
2009 		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2010 		    retry_count, timeout);
2011 	}
2012 }
2013 
2014 static int
2015 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2016 	int retry_count, int timeout)
2017 {
2018 	union ccb *ccb;
2019 	u_int32_t flags = CAM_DIR_NONE;
2020 	u_int8_t *data_ptr = NULL;
2021 	u_int8_t cdb[20];
2022 	struct get_hook hook;
2023 	int c, data_bytes = 0;
2024 	int cdb_len = 0;
2025 	char *datastr = NULL, *tstr;
2026 	int error = 0;
2027 	int fd_data = 0;
2028 	int retval;
2029 
2030 	ccb = cam_getccb(device);
2031 
2032 	if (ccb == NULL) {
2033 		warnx("scsicmd: error allocating ccb");
2034 		return(1);
2035 	}
2036 
2037 	bzero(&(&ccb->ccb_h)[1],
2038 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2039 
2040 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2041 		switch(c) {
2042 		case 'c':
2043 			tstr = optarg;
2044 			while (isspace(*tstr) && (*tstr != '\0'))
2045 				tstr++;
2046 			hook.argc = argc - optind;
2047 			hook.argv = argv + optind;
2048 			hook.got = 0;
2049 			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2050 						    iget, &hook);
2051 			/*
2052 			 * Increment optind by the number of arguments the
2053 			 * encoding routine processed.  After each call to
2054 			 * getopt(3), optind points to the argument that
2055 			 * getopt should process _next_.  In this case,
2056 			 * that means it points to the first command string
2057 			 * argument, if there is one.  Once we increment
2058 			 * this, it should point to either the next command
2059 			 * line argument, or it should be past the end of
2060 			 * the list.
2061 			 */
2062 			optind += hook.got;
2063 			break;
2064 		case 'i':
2065 			if (arglist & CAM_ARG_CMD_OUT) {
2066 				warnx("command must either be "
2067 				      "read or write, not both");
2068 				error = 1;
2069 				goto scsicmd_bailout;
2070 			}
2071 			arglist |= CAM_ARG_CMD_IN;
2072 			flags = CAM_DIR_IN;
2073 			data_bytes = strtol(optarg, NULL, 0);
2074 			if (data_bytes <= 0) {
2075 				warnx("invalid number of input bytes %d",
2076 				      data_bytes);
2077 				error = 1;
2078 				goto scsicmd_bailout;
2079 			}
2080 			hook.argc = argc - optind;
2081 			hook.argv = argv + optind;
2082 			hook.got = 0;
2083 			optind++;
2084 			datastr = cget(&hook, NULL);
2085 			/*
2086 			 * If the user supplied "-" instead of a format, he
2087 			 * wants the data to be written to stdout.
2088 			 */
2089 			if ((datastr != NULL)
2090 			 && (datastr[0] == '-'))
2091 				fd_data = 1;
2092 
2093 			data_ptr = (u_int8_t *)malloc(data_bytes);
2094 			if (data_ptr == NULL) {
2095 				warnx("can't malloc memory for data_ptr");
2096 				error = 1;
2097 				goto scsicmd_bailout;
2098 			}
2099 			break;
2100 		case 'o':
2101 			if (arglist & CAM_ARG_CMD_IN) {
2102 				warnx("command must either be "
2103 				      "read or write, not both");
2104 				error = 1;
2105 				goto scsicmd_bailout;
2106 			}
2107 			arglist |= CAM_ARG_CMD_OUT;
2108 			flags = CAM_DIR_OUT;
2109 			data_bytes = strtol(optarg, NULL, 0);
2110 			if (data_bytes <= 0) {
2111 				warnx("invalid number of output bytes %d",
2112 				      data_bytes);
2113 				error = 1;
2114 				goto scsicmd_bailout;
2115 			}
2116 			hook.argc = argc - optind;
2117 			hook.argv = argv + optind;
2118 			hook.got = 0;
2119 			datastr = cget(&hook, NULL);
2120 			data_ptr = (u_int8_t *)malloc(data_bytes);
2121 			if (data_ptr == NULL) {
2122 				warnx("can't malloc memory for data_ptr");
2123 				error = 1;
2124 				goto scsicmd_bailout;
2125 			}
2126 			/*
2127 			 * If the user supplied "-" instead of a format, he
2128 			 * wants the data to be read from stdin.
2129 			 */
2130 			if ((datastr != NULL)
2131 			 && (datastr[0] == '-'))
2132 				fd_data = 1;
2133 			else
2134 				buff_encode_visit(data_ptr, data_bytes, datastr,
2135 						  iget, &hook);
2136 			optind += hook.got;
2137 			break;
2138 		default:
2139 			break;
2140 		}
2141 	}
2142 
2143 	/*
2144 	 * If fd_data is set, and we're writing to the device, we need to
2145 	 * read the data the user wants written from stdin.
2146 	 */
2147 	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2148 		ssize_t amt_read;
2149 		int amt_to_read = data_bytes;
2150 		u_int8_t *buf_ptr = data_ptr;
2151 
2152 		for (amt_read = 0; amt_to_read > 0;
2153 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2154 			if (amt_read == -1) {
2155 				warn("error reading data from stdin");
2156 				error = 1;
2157 				goto scsicmd_bailout;
2158 			}
2159 			amt_to_read -= amt_read;
2160 			buf_ptr += amt_read;
2161 		}
2162 	}
2163 
2164 	if (arglist & CAM_ARG_ERR_RECOVER)
2165 		flags |= CAM_PASS_ERR_RECOVER;
2166 
2167 	/* Disable freezing the device queue */
2168 	flags |= CAM_DEV_QFRZDIS;
2169 
2170 	/*
2171 	 * This is taken from the SCSI-3 draft spec.
2172 	 * (T10/1157D revision 0.3)
2173 	 * The top 3 bits of an opcode are the group code.  The next 5 bits
2174 	 * are the command code.
2175 	 * Group 0:  six byte commands
2176 	 * Group 1:  ten byte commands
2177 	 * Group 2:  ten byte commands
2178 	 * Group 3:  reserved
2179 	 * Group 4:  sixteen byte commands
2180 	 * Group 5:  twelve byte commands
2181 	 * Group 6:  vendor specific
2182 	 * Group 7:  vendor specific
2183 	 */
2184 	switch((cdb[0] >> 5) & 0x7) {
2185 		case 0:
2186 			cdb_len = 6;
2187 			break;
2188 		case 1:
2189 		case 2:
2190 			cdb_len = 10;
2191 			break;
2192 		case 3:
2193 		case 6:
2194 		case 7:
2195 		        /* computed by buff_encode_visit */
2196 			break;
2197 		case 4:
2198 			cdb_len = 16;
2199 			break;
2200 		case 5:
2201 			cdb_len = 12;
2202 			break;
2203 	}
2204 
2205 	/*
2206 	 * We should probably use csio_build_visit or something like that
2207 	 * here, but it's easier to encode arguments as you go.  The
2208 	 * alternative would be skipping the CDB argument and then encoding
2209 	 * it here, since we've got the data buffer argument by now.
2210 	 */
2211 	bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2212 
2213 	cam_fill_csio(&ccb->csio,
2214 		      /*retries*/ retry_count,
2215 		      /*cbfcnp*/ NULL,
2216 		      /*flags*/ flags,
2217 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
2218 		      /*data_ptr*/ data_ptr,
2219 		      /*dxfer_len*/ data_bytes,
2220 		      /*sense_len*/ SSD_FULL_SIZE,
2221 		      /*cdb_len*/ cdb_len,
2222 		      /*timeout*/ timeout ? timeout : 5000);
2223 
2224 	if (((retval = cam_send_ccb(device, ccb)) < 0)
2225 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2226 		if (retval < 0)
2227 			warn("error sending command");
2228 		else
2229 			warnx("error sending command");
2230 
2231 		if (arglist & CAM_ARG_VERBOSE) {
2232 			cam_error_print(device, ccb, CAM_ESF_ALL,
2233 					CAM_EPF_ALL, stderr);
2234 		}
2235 
2236 		error = 1;
2237 		goto scsicmd_bailout;
2238 	}
2239 
2240 
2241 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2242 	 && (arglist & CAM_ARG_CMD_IN)
2243 	 && (data_bytes > 0)) {
2244 		if (fd_data == 0) {
2245 			buff_decode_visit(data_ptr, data_bytes, datastr,
2246 					  arg_put, NULL);
2247 			fprintf(stdout, "\n");
2248 		} else {
2249 			ssize_t amt_written;
2250 			int amt_to_write = data_bytes;
2251 			u_int8_t *buf_ptr = data_ptr;
2252 
2253 			for (amt_written = 0; (amt_to_write > 0) &&
2254 			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2255 				amt_to_write -= amt_written;
2256 				buf_ptr += amt_written;
2257 			}
2258 			if (amt_written == -1) {
2259 				warn("error writing data to stdout");
2260 				error = 1;
2261 				goto scsicmd_bailout;
2262 			} else if ((amt_written == 0)
2263 				&& (amt_to_write > 0)) {
2264 				warnx("only wrote %u bytes out of %u",
2265 				      data_bytes - amt_to_write, data_bytes);
2266 			}
2267 		}
2268 	}
2269 
2270 scsicmd_bailout:
2271 
2272 	if ((data_bytes > 0) && (data_ptr != NULL))
2273 		free(data_ptr);
2274 
2275 	cam_freeccb(ccb);
2276 
2277 	return(error);
2278 }
2279 
2280 static int
2281 camdebug(int argc, char **argv, char *combinedopt)
2282 {
2283 	int c, fd;
2284 	int bus = -1, target = -1, lun = -1;
2285 	char *tstr, *tmpstr = NULL;
2286 	union ccb ccb;
2287 	int error = 0;
2288 
2289 	bzero(&ccb, sizeof(union ccb));
2290 
2291 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2292 		switch(c) {
2293 		case 'I':
2294 			arglist |= CAM_ARG_DEBUG_INFO;
2295 			ccb.cdbg.flags |= CAM_DEBUG_INFO;
2296 			break;
2297 		case 'P':
2298 			arglist |= CAM_ARG_DEBUG_PERIPH;
2299 			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2300 			break;
2301 		case 'S':
2302 			arglist |= CAM_ARG_DEBUG_SUBTRACE;
2303 			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2304 			break;
2305 		case 'T':
2306 			arglist |= CAM_ARG_DEBUG_TRACE;
2307 			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2308 			break;
2309 		case 'X':
2310 			arglist |= CAM_ARG_DEBUG_XPT;
2311 			ccb.cdbg.flags |= CAM_DEBUG_XPT;
2312 			break;
2313 		case 'c':
2314 			arglist |= CAM_ARG_DEBUG_CDB;
2315 			ccb.cdbg.flags |= CAM_DEBUG_CDB;
2316 			break;
2317 		default:
2318 			break;
2319 		}
2320 	}
2321 
2322 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2323 		warnx("error opening transport layer device %s", XPT_DEVICE);
2324 		warn("%s", XPT_DEVICE);
2325 		return(1);
2326 	}
2327 	argc -= optind;
2328 	argv += optind;
2329 
2330 	if (argc <= 0) {
2331 		warnx("you must specify \"off\", \"all\" or a bus,");
2332 		warnx("bus:target, or bus:target:lun");
2333 		close(fd);
2334 		return(1);
2335 	}
2336 
2337 	tstr = *argv;
2338 
2339 	while (isspace(*tstr) && (*tstr != '\0'))
2340 		tstr++;
2341 
2342 	if (strncmp(tstr, "off", 3) == 0) {
2343 		ccb.cdbg.flags = CAM_DEBUG_NONE;
2344 		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2345 			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2346 			     CAM_ARG_DEBUG_XPT);
2347 	} else if (strncmp(tstr, "all", 3) != 0) {
2348 		tmpstr = (char *)strtok(tstr, ":");
2349 		if ((tmpstr != NULL) && (*tmpstr != '\0')){
2350 			bus = strtol(tmpstr, NULL, 0);
2351 			arglist |= CAM_ARG_BUS;
2352 			tmpstr = (char *)strtok(NULL, ":");
2353 			if ((tmpstr != NULL) && (*tmpstr != '\0')){
2354 				target = strtol(tmpstr, NULL, 0);
2355 				arglist |= CAM_ARG_TARGET;
2356 				tmpstr = (char *)strtok(NULL, ":");
2357 				if ((tmpstr != NULL) && (*tmpstr != '\0')){
2358 					lun = strtol(tmpstr, NULL, 0);
2359 					arglist |= CAM_ARG_LUN;
2360 				}
2361 			}
2362 		} else {
2363 			error = 1;
2364 			warnx("you must specify \"all\", \"off\", or a bus,");
2365 			warnx("bus:target, or bus:target:lun to debug");
2366 		}
2367 	}
2368 
2369 	if (error == 0) {
2370 
2371 		ccb.ccb_h.func_code = XPT_DEBUG;
2372 		ccb.ccb_h.path_id = bus;
2373 		ccb.ccb_h.target_id = target;
2374 		ccb.ccb_h.target_lun = lun;
2375 
2376 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2377 			warn("CAMIOCOMMAND ioctl failed");
2378 			error = 1;
2379 		}
2380 
2381 		if (error == 0) {
2382 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2383 			     CAM_FUNC_NOTAVAIL) {
2384 				warnx("CAM debugging not available");
2385 				warnx("you need to put options CAMDEBUG in"
2386 				      " your kernel config file!");
2387 				error = 1;
2388 			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2389 				    CAM_REQ_CMP) {
2390 				warnx("XPT_DEBUG CCB failed with status %#x",
2391 				      ccb.ccb_h.status);
2392 				error = 1;
2393 			} else {
2394 				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2395 					fprintf(stderr,
2396 						"Debugging turned off\n");
2397 				} else {
2398 					fprintf(stderr,
2399 						"Debugging enabled for "
2400 						"%d:%d:%d\n",
2401 						bus, target, lun);
2402 				}
2403 			}
2404 		}
2405 		close(fd);
2406 	}
2407 
2408 	return(error);
2409 }
2410 
2411 static int
2412 tagcontrol(struct cam_device *device, int argc, char **argv,
2413 	   char *combinedopt)
2414 {
2415 	int c;
2416 	union ccb *ccb;
2417 	int numtags = -1;
2418 	int retval = 0;
2419 	int quiet = 0;
2420 	char pathstr[1024];
2421 
2422 	ccb = cam_getccb(device);
2423 
2424 	if (ccb == NULL) {
2425 		warnx("tagcontrol: error allocating ccb");
2426 		return(1);
2427 	}
2428 
2429 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2430 		switch(c) {
2431 		case 'N':
2432 			numtags = strtol(optarg, NULL, 0);
2433 			if (numtags < 0) {
2434 				warnx("tag count %d is < 0", numtags);
2435 				retval = 1;
2436 				goto tagcontrol_bailout;
2437 			}
2438 			break;
2439 		case 'q':
2440 			quiet++;
2441 			break;
2442 		default:
2443 			break;
2444 		}
2445 	}
2446 
2447 	cam_path_string(device, pathstr, sizeof(pathstr));
2448 
2449 	if (numtags >= 0) {
2450 		bzero(&(&ccb->ccb_h)[1],
2451 		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2452 		ccb->ccb_h.func_code = XPT_REL_SIMQ;
2453 		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2454 		ccb->crs.openings = numtags;
2455 
2456 
2457 		if (cam_send_ccb(device, ccb) < 0) {
2458 			perror("error sending XPT_REL_SIMQ CCB");
2459 			retval = 1;
2460 			goto tagcontrol_bailout;
2461 		}
2462 
2463 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2464 			warnx("XPT_REL_SIMQ CCB failed");
2465 			cam_error_print(device, ccb, CAM_ESF_ALL,
2466 					CAM_EPF_ALL, stderr);
2467 			retval = 1;
2468 			goto tagcontrol_bailout;
2469 		}
2470 
2471 
2472 		if (quiet == 0)
2473 			fprintf(stdout, "%stagged openings now %d\n",
2474 				pathstr, ccb->crs.openings);
2475 	}
2476 
2477 	bzero(&(&ccb->ccb_h)[1],
2478 	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2479 
2480 	ccb->ccb_h.func_code = XPT_GDEV_STATS;
2481 
2482 	if (cam_send_ccb(device, ccb) < 0) {
2483 		perror("error sending XPT_GDEV_STATS CCB");
2484 		retval = 1;
2485 		goto tagcontrol_bailout;
2486 	}
2487 
2488 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2489 		warnx("XPT_GDEV_STATS CCB failed");
2490 		cam_error_print(device, ccb, CAM_ESF_ALL,
2491 				CAM_EPF_ALL, stderr);
2492 		retval = 1;
2493 		goto tagcontrol_bailout;
2494 	}
2495 
2496 	if (arglist & CAM_ARG_VERBOSE) {
2497 		fprintf(stdout, "%s", pathstr);
2498 		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2499 		fprintf(stdout, "%s", pathstr);
2500 		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2501 		fprintf(stdout, "%s", pathstr);
2502 		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2503 		fprintf(stdout, "%s", pathstr);
2504 		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2505 		fprintf(stdout, "%s", pathstr);
2506 		fprintf(stdout, "held          %d\n", ccb->cgds.held);
2507 		fprintf(stdout, "%s", pathstr);
2508 		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2509 		fprintf(stdout, "%s", pathstr);
2510 		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2511 	} else {
2512 		if (quiet == 0) {
2513 			fprintf(stdout, "%s", pathstr);
2514 			fprintf(stdout, "device openings: ");
2515 		}
2516 		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2517 			ccb->cgds.dev_active);
2518 	}
2519 
2520 tagcontrol_bailout:
2521 
2522 	cam_freeccb(ccb);
2523 	return(retval);
2524 }
2525 
2526 static void
2527 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2528 {
2529 	char pathstr[1024];
2530 
2531 	cam_path_string(device, pathstr, sizeof(pathstr));
2532 
2533 	if (cts->transport == XPORT_SPI) {
2534 		struct ccb_trans_settings_spi *spi =
2535 		    &cts->xport_specific.spi;
2536 
2537 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2538 
2539 			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2540 				spi->sync_period);
2541 
2542 			if (spi->sync_offset != 0) {
2543 				u_int freq;
2544 
2545 				freq = scsi_calc_syncsrate(spi->sync_period);
2546 				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2547 					pathstr, freq / 1000, freq % 1000);
2548 			}
2549 		}
2550 
2551 		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2552 			fprintf(stdout, "%soffset: %d\n", pathstr,
2553 			    spi->sync_offset);
2554 		}
2555 
2556 		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2557 			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2558 				(0x01 << spi->bus_width) * 8);
2559 		}
2560 
2561 		if (spi->valid & CTS_SPI_VALID_DISC) {
2562 			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2563 				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2564 				"enabled" : "disabled");
2565 		}
2566 	}
2567 
2568 	if (cts->protocol == PROTO_SCSI) {
2569 		struct ccb_trans_settings_scsi *scsi=
2570 		    &cts->proto_specific.scsi;
2571 
2572 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
2573 			fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2574 				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2575 				"enabled" : "disabled");
2576 		}
2577 	}
2578 
2579 }
2580 
2581 /*
2582  * Get a path inquiry CCB for the specified device.
2583  */
2584 static int
2585 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2586 {
2587 	union ccb *ccb;
2588 	int retval = 0;
2589 
2590 	ccb = cam_getccb(device);
2591 
2592 	if (ccb == NULL) {
2593 		warnx("get_cpi: couldn't allocate CCB");
2594 		return(1);
2595 	}
2596 
2597 	bzero(&(&ccb->ccb_h)[1],
2598 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2599 
2600 	ccb->ccb_h.func_code = XPT_PATH_INQ;
2601 
2602 	if (cam_send_ccb(device, ccb) < 0) {
2603 		warn("get_cpi: error sending Path Inquiry CCB");
2604 
2605 		if (arglist & CAM_ARG_VERBOSE)
2606 			cam_error_print(device, ccb, CAM_ESF_ALL,
2607 					CAM_EPF_ALL, stderr);
2608 
2609 		retval = 1;
2610 
2611 		goto get_cpi_bailout;
2612 	}
2613 
2614 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2615 
2616 		if (arglist & CAM_ARG_VERBOSE)
2617 			cam_error_print(device, ccb, CAM_ESF_ALL,
2618 					CAM_EPF_ALL, stderr);
2619 
2620 		retval = 1;
2621 
2622 		goto get_cpi_bailout;
2623 	}
2624 
2625 	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2626 
2627 get_cpi_bailout:
2628 
2629 	cam_freeccb(ccb);
2630 
2631 	return(retval);
2632 }
2633 
2634 static void
2635 cpi_print(struct ccb_pathinq *cpi)
2636 {
2637 	char adapter_str[1024];
2638 	int i;
2639 
2640 	snprintf(adapter_str, sizeof(adapter_str),
2641 		 "%s%d:", cpi->dev_name, cpi->unit_number);
2642 
2643 	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2644 		cpi->version_num);
2645 
2646 	for (i = 1; i < 0xff; i = i << 1) {
2647 		const char *str;
2648 
2649 		if ((i & cpi->hba_inquiry) == 0)
2650 			continue;
2651 
2652 		fprintf(stdout, "%s supports ", adapter_str);
2653 
2654 		switch(i) {
2655 		case PI_MDP_ABLE:
2656 			str = "MDP message";
2657 			break;
2658 		case PI_WIDE_32:
2659 			str = "32 bit wide SCSI";
2660 			break;
2661 		case PI_WIDE_16:
2662 			str = "16 bit wide SCSI";
2663 			break;
2664 		case PI_SDTR_ABLE:
2665 			str = "SDTR message";
2666 			break;
2667 		case PI_LINKED_CDB:
2668 			str = "linked CDBs";
2669 			break;
2670 		case PI_TAG_ABLE:
2671 			str = "tag queue messages";
2672 			break;
2673 		case PI_SOFT_RST:
2674 			str = "soft reset alternative";
2675 			break;
2676 		default:
2677 			str = "unknown PI bit set";
2678 			break;
2679 		}
2680 		fprintf(stdout, "%s\n", str);
2681 	}
2682 
2683 	for (i = 1; i < 0xff; i = i << 1) {
2684 		const char *str;
2685 
2686 		if ((i & cpi->hba_misc) == 0)
2687 			continue;
2688 
2689 		fprintf(stdout, "%s ", adapter_str);
2690 
2691 		switch(i) {
2692 		case PIM_SCANHILO:
2693 			str = "bus scans from high ID to low ID";
2694 			break;
2695 		case PIM_NOREMOVE:
2696 			str = "removable devices not included in scan";
2697 			break;
2698 		case PIM_NOINITIATOR:
2699 			str = "initiator role not supported";
2700 			break;
2701 		case PIM_NOBUSRESET:
2702 			str = "user has disabled initial BUS RESET or"
2703 			      " controller is in target/mixed mode";
2704 			break;
2705 		default:
2706 			str = "unknown PIM bit set";
2707 			break;
2708 		}
2709 		fprintf(stdout, "%s\n", str);
2710 	}
2711 
2712 	for (i = 1; i < 0xff; i = i << 1) {
2713 		const char *str;
2714 
2715 		if ((i & cpi->target_sprt) == 0)
2716 			continue;
2717 
2718 		fprintf(stdout, "%s supports ", adapter_str);
2719 		switch(i) {
2720 		case PIT_PROCESSOR:
2721 			str = "target mode processor mode";
2722 			break;
2723 		case PIT_PHASE:
2724 			str = "target mode phase cog. mode";
2725 			break;
2726 		case PIT_DISCONNECT:
2727 			str = "disconnects in target mode";
2728 			break;
2729 		case PIT_TERM_IO:
2730 			str = "terminate I/O message in target mode";
2731 			break;
2732 		case PIT_GRP_6:
2733 			str = "group 6 commands in target mode";
2734 			break;
2735 		case PIT_GRP_7:
2736 			str = "group 7 commands in target mode";
2737 			break;
2738 		default:
2739 			str = "unknown PIT bit set";
2740 			break;
2741 		}
2742 
2743 		fprintf(stdout, "%s\n", str);
2744 	}
2745 	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
2746 		cpi->hba_eng_cnt);
2747 	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
2748 		cpi->max_target);
2749 	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
2750 		cpi->max_lun);
2751 	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
2752 		adapter_str, cpi->hpath_id);
2753 	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
2754 		cpi->initiator_id);
2755 	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
2756 	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
2757 	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
2758 	fprintf(stdout, "%s base transfer speed: ", adapter_str);
2759 	if (cpi->base_transfer_speed > 1000)
2760 		fprintf(stdout, "%d.%03dMB/sec\n",
2761 			cpi->base_transfer_speed / 1000,
2762 			cpi->base_transfer_speed % 1000);
2763 	else
2764 		fprintf(stdout, "%dKB/sec\n",
2765 			(cpi->base_transfer_speed % 1000) * 1000);
2766 }
2767 
2768 static int
2769 get_print_cts(struct cam_device *device, int user_settings, int quiet,
2770 	      struct ccb_trans_settings *cts)
2771 {
2772 	int retval;
2773 	union ccb *ccb;
2774 
2775 	retval = 0;
2776 	ccb = cam_getccb(device);
2777 
2778 	if (ccb == NULL) {
2779 		warnx("get_print_cts: error allocating ccb");
2780 		return(1);
2781 	}
2782 
2783 	bzero(&(&ccb->ccb_h)[1],
2784 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2785 
2786 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
2787 
2788 	if (user_settings == 0)
2789 		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
2790 	else
2791 		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
2792 
2793 	if (cam_send_ccb(device, ccb) < 0) {
2794 		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
2795 		if (arglist & CAM_ARG_VERBOSE)
2796 			cam_error_print(device, ccb, CAM_ESF_ALL,
2797 					CAM_EPF_ALL, stderr);
2798 		retval = 1;
2799 		goto get_print_cts_bailout;
2800 	}
2801 
2802 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2803 		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
2804 		if (arglist & CAM_ARG_VERBOSE)
2805 			cam_error_print(device, ccb, CAM_ESF_ALL,
2806 					CAM_EPF_ALL, stderr);
2807 		retval = 1;
2808 		goto get_print_cts_bailout;
2809 	}
2810 
2811 	if (quiet == 0)
2812 		cts_print(device, &ccb->cts);
2813 
2814 	if (cts != NULL)
2815 		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
2816 
2817 get_print_cts_bailout:
2818 
2819 	cam_freeccb(ccb);
2820 
2821 	return(retval);
2822 }
2823 
2824 static int
2825 ratecontrol(struct cam_device *device, int retry_count, int timeout,
2826 	    int argc, char **argv, char *combinedopt)
2827 {
2828 	int c;
2829 	union ccb *ccb;
2830 	int user_settings = 0;
2831 	int retval = 0;
2832 	int disc_enable = -1, tag_enable = -1;
2833 	int offset = -1;
2834 	double syncrate = -1;
2835 	int bus_width = -1;
2836 	int quiet = 0;
2837 	int change_settings = 0, send_tur = 0;
2838 	struct ccb_pathinq cpi;
2839 
2840 	ccb = cam_getccb(device);
2841 
2842 	if (ccb == NULL) {
2843 		warnx("ratecontrol: error allocating ccb");
2844 		return(1);
2845 	}
2846 
2847 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2848 		switch(c){
2849 		case 'a':
2850 			send_tur = 1;
2851 			break;
2852 		case 'c':
2853 			user_settings = 0;
2854 			break;
2855 		case 'D':
2856 			if (strncasecmp(optarg, "enable", 6) == 0)
2857 				disc_enable = 1;
2858 			else if (strncasecmp(optarg, "disable", 7) == 0)
2859 				disc_enable = 0;
2860 			else {
2861 				warnx("-D argument \"%s\" is unknown", optarg);
2862 				retval = 1;
2863 				goto ratecontrol_bailout;
2864 			}
2865 			change_settings = 1;
2866 			break;
2867 		case 'O':
2868 			offset = strtol(optarg, NULL, 0);
2869 			if (offset < 0) {
2870 				warnx("offset value %d is < 0", offset);
2871 				retval = 1;
2872 				goto ratecontrol_bailout;
2873 			}
2874 			change_settings = 1;
2875 			break;
2876 		case 'q':
2877 			quiet++;
2878 			break;
2879 		case 'R':
2880 			syncrate = atof(optarg);
2881 
2882 			if (syncrate < 0) {
2883 				warnx("sync rate %f is < 0", syncrate);
2884 				retval = 1;
2885 				goto ratecontrol_bailout;
2886 			}
2887 			change_settings = 1;
2888 			break;
2889 		case 'T':
2890 			if (strncasecmp(optarg, "enable", 6) == 0)
2891 				tag_enable = 1;
2892 			else if (strncasecmp(optarg, "disable", 7) == 0)
2893 				tag_enable = 0;
2894 			else {
2895 				warnx("-T argument \"%s\" is unknown", optarg);
2896 				retval = 1;
2897 				goto ratecontrol_bailout;
2898 			}
2899 			change_settings = 1;
2900 			break;
2901 		case 'U':
2902 			user_settings = 1;
2903 			break;
2904 		case 'W':
2905 			bus_width = strtol(optarg, NULL, 0);
2906 			if (bus_width < 0) {
2907 				warnx("bus width %d is < 0", bus_width);
2908 				retval = 1;
2909 				goto ratecontrol_bailout;
2910 			}
2911 			change_settings = 1;
2912 			break;
2913 		default:
2914 			break;
2915 		}
2916 	}
2917 
2918 	bzero(&(&ccb->ccb_h)[1],
2919 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2920 
2921 	/*
2922 	 * Grab path inquiry information, so we can determine whether
2923 	 * or not the initiator is capable of the things that the user
2924 	 * requests.
2925 	 */
2926 	ccb->ccb_h.func_code = XPT_PATH_INQ;
2927 
2928 	if (cam_send_ccb(device, ccb) < 0) {
2929 		perror("error sending XPT_PATH_INQ CCB");
2930 		if (arglist & CAM_ARG_VERBOSE) {
2931 			cam_error_print(device, ccb, CAM_ESF_ALL,
2932 					CAM_EPF_ALL, stderr);
2933 		}
2934 		retval = 1;
2935 		goto ratecontrol_bailout;
2936 	}
2937 
2938 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2939 		warnx("XPT_PATH_INQ CCB failed");
2940 		if (arglist & CAM_ARG_VERBOSE) {
2941 			cam_error_print(device, ccb, CAM_ESF_ALL,
2942 					CAM_EPF_ALL, stderr);
2943 		}
2944 		retval = 1;
2945 		goto ratecontrol_bailout;
2946 	}
2947 
2948 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
2949 
2950 	bzero(&(&ccb->ccb_h)[1],
2951 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2952 
2953 	if (quiet == 0)
2954 		fprintf(stdout, "Current Parameters:\n");
2955 
2956 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
2957 
2958 	if (retval != 0)
2959 		goto ratecontrol_bailout;
2960 
2961 	if (arglist & CAM_ARG_VERBOSE)
2962 		cpi_print(&cpi);
2963 
2964 	if (change_settings) {
2965 		int didsettings = 0;
2966 		struct ccb_trans_settings_spi *spi = NULL;
2967 		struct ccb_trans_settings_scsi *scsi = NULL;
2968 
2969 		if (ccb->cts.transport == XPORT_SPI) {
2970 			spi = &ccb->cts.xport_specific.spi;
2971 			spi->valid = 0;
2972 		}
2973 		if (ccb->cts.protocol == PROTO_SCSI) {
2974 			scsi = &ccb->cts.proto_specific.scsi;
2975 			scsi->valid = 0;
2976 		}
2977 		if (spi && disc_enable != -1) {
2978 			spi->valid |= CTS_SPI_VALID_DISC;
2979 			if (disc_enable == 0)
2980 				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
2981 			else
2982 				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
2983 		}
2984 
2985 		if (scsi && tag_enable != -1) {
2986 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
2987 				warnx("HBA does not support tagged queueing, "
2988 				      "so you cannot modify tag settings");
2989 				retval = 1;
2990 				goto ratecontrol_bailout;
2991 			}
2992 
2993 			scsi->valid |= CTS_SCSI_VALID_TQ;
2994 
2995 			if (tag_enable == 0)
2996 				scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
2997 			else
2998 				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
2999 			didsettings++;
3000 		}
3001 
3002 		if (spi && offset != -1) {
3003 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3004 				warnx("HBA at %s%d is not cable of changing "
3005 				      "offset", cpi.dev_name,
3006 				      cpi.unit_number);
3007 				retval = 1;
3008 				goto ratecontrol_bailout;
3009 			}
3010 			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3011 			spi->sync_offset = offset;
3012 			didsettings++;
3013 		}
3014 
3015 		if (spi && syncrate != -1) {
3016 			int prelim_sync_period;
3017 			u_int freq;
3018 
3019 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3020 				warnx("HBA at %s%d is not cable of changing "
3021 				      "transfer rates", cpi.dev_name,
3022 				      cpi.unit_number);
3023 				retval = 1;
3024 				goto ratecontrol_bailout;
3025 			}
3026 
3027 			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3028 
3029 			/*
3030 			 * The sync rate the user gives us is in MHz.
3031 			 * We need to translate it into KHz for this
3032 			 * calculation.
3033 			 */
3034 			syncrate *= 1000;
3035 
3036 			/*
3037 			 * Next, we calculate a "preliminary" sync period
3038 			 * in tenths of a nanosecond.
3039 			 */
3040 			if (syncrate == 0)
3041 				prelim_sync_period = 0;
3042 			else
3043 				prelim_sync_period = 10000000 / syncrate;
3044 
3045 			spi->sync_period =
3046 				scsi_calc_syncparam(prelim_sync_period);
3047 
3048 			freq = scsi_calc_syncsrate(spi->sync_period);
3049 			didsettings++;
3050 		}
3051 
3052 		/*
3053 		 * The bus_width argument goes like this:
3054 		 * 0 == 8 bit
3055 		 * 1 == 16 bit
3056 		 * 2 == 32 bit
3057 		 * Therefore, if you shift the number of bits given on the
3058 		 * command line right by 4, you should get the correct
3059 		 * number.
3060 		 */
3061 		if (spi && bus_width != -1) {
3062 
3063 			/*
3064 			 * We might as well validate things here with a
3065 			 * decipherable error message, rather than what
3066 			 * will probably be an indecipherable error message
3067 			 * by the time it gets back to us.
3068 			 */
3069 			if ((bus_width == 16)
3070 			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3071 				warnx("HBA does not support 16 bit bus width");
3072 				retval = 1;
3073 				goto ratecontrol_bailout;
3074 			} else if ((bus_width == 32)
3075 				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3076 				warnx("HBA does not support 32 bit bus width");
3077 				retval = 1;
3078 				goto ratecontrol_bailout;
3079 			} else if ((bus_width != 8)
3080 				&& (bus_width != 16)
3081 				&& (bus_width != 32)) {
3082 				warnx("Invalid bus width %d", bus_width);
3083 				retval = 1;
3084 				goto ratecontrol_bailout;
3085 			}
3086 
3087 			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3088 			spi->bus_width = bus_width >> 4;
3089 			didsettings++;
3090 		}
3091 
3092 		if  (didsettings == 0) {
3093 			goto ratecontrol_bailout;
3094 		}
3095 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3096 
3097 		if (cam_send_ccb(device, ccb) < 0) {
3098 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3099 			if (arglist & CAM_ARG_VERBOSE) {
3100 				cam_error_print(device, ccb, CAM_ESF_ALL,
3101 						CAM_EPF_ALL, stderr);
3102 			}
3103 			retval = 1;
3104 			goto ratecontrol_bailout;
3105 		}
3106 
3107 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3108 			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3109 			if (arglist & CAM_ARG_VERBOSE) {
3110 				cam_error_print(device, ccb, CAM_ESF_ALL,
3111 						CAM_EPF_ALL, stderr);
3112 			}
3113 			retval = 1;
3114 			goto ratecontrol_bailout;
3115 		}
3116 	}
3117 
3118 	if (send_tur) {
3119 		retval = testunitready(device, retry_count, timeout,
3120 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3121 
3122 		/*
3123 		 * If the TUR didn't succeed, just bail.
3124 		 */
3125 		if (retval != 0) {
3126 			if (quiet == 0)
3127 				fprintf(stderr, "Test Unit Ready failed\n");
3128 			goto ratecontrol_bailout;
3129 		}
3130 
3131 		/*
3132 		 * If the user wants things quiet, there's no sense in
3133 		 * getting the transfer settings, if we're not going
3134 		 * to print them.
3135 		 */
3136 		if (quiet != 0)
3137 			goto ratecontrol_bailout;
3138 
3139 		fprintf(stdout, "New Parameters:\n");
3140 		retval = get_print_cts(device, user_settings, 0, NULL);
3141 	}
3142 
3143 ratecontrol_bailout:
3144 
3145 	cam_freeccb(ccb);
3146 	return(retval);
3147 }
3148 
3149 static int
3150 scsiformat(struct cam_device *device, int argc, char **argv,
3151 	   char *combinedopt, int retry_count, int timeout)
3152 {
3153 	union ccb *ccb;
3154 	int c;
3155 	int ycount = 0, quiet = 0;
3156 	int error = 0, response = 0, retval = 0;
3157 	int use_timeout = 10800 * 1000;
3158 	int immediate = 1;
3159 	struct format_defect_list_header fh;
3160 	u_int8_t *data_ptr = NULL;
3161 	u_int32_t dxfer_len = 0;
3162 	u_int8_t byte2 = 0;
3163 	int num_warnings = 0;
3164 	int reportonly = 0;
3165 
3166 	ccb = cam_getccb(device);
3167 
3168 	if (ccb == NULL) {
3169 		warnx("scsiformat: error allocating ccb");
3170 		return(1);
3171 	}
3172 
3173 	bzero(&(&ccb->ccb_h)[1],
3174 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3175 
3176 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3177 		switch(c) {
3178 		case 'q':
3179 			quiet++;
3180 			break;
3181 		case 'r':
3182 			reportonly = 1;
3183 			break;
3184 		case 'w':
3185 			immediate = 0;
3186 			break;
3187 		case 'y':
3188 			ycount++;
3189 			break;
3190 		}
3191 	}
3192 
3193 	if (reportonly)
3194 		goto doreport;
3195 
3196 	if (quiet == 0) {
3197 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3198 			"following device:\n");
3199 
3200 		error = scsidoinquiry(device, argc, argv, combinedopt,
3201 				      retry_count, timeout);
3202 
3203 		if (error != 0) {
3204 			warnx("scsiformat: error sending inquiry");
3205 			goto scsiformat_bailout;
3206 		}
3207 	}
3208 
3209 	if (ycount == 0) {
3210 
3211 		do {
3212 			char str[1024];
3213 
3214 			fprintf(stdout, "Are you SURE you want to do "
3215 				"this? (yes/no) ");
3216 
3217 			if (fgets(str, sizeof(str), stdin) != NULL) {
3218 
3219 				if (strncasecmp(str, "yes", 3) == 0)
3220 					response = 1;
3221 				else if (strncasecmp(str, "no", 2) == 0)
3222 					response = -1;
3223 				else {
3224 					fprintf(stdout, "Please answer"
3225 						" \"yes\" or \"no\"\n");
3226 				}
3227 			}
3228 		} while (response == 0);
3229 
3230 		if (response == -1) {
3231 			error = 1;
3232 			goto scsiformat_bailout;
3233 		}
3234 	}
3235 
3236 	if (timeout != 0)
3237 		use_timeout = timeout;
3238 
3239 	if (quiet == 0) {
3240 		fprintf(stdout, "Current format timeout is %d seconds\n",
3241 			use_timeout / 1000);
3242 	}
3243 
3244 	/*
3245 	 * If the user hasn't disabled questions and didn't specify a
3246 	 * timeout on the command line, ask them if they want the current
3247 	 * timeout.
3248 	 */
3249 	if ((ycount == 0)
3250 	 && (timeout == 0)) {
3251 		char str[1024];
3252 		int new_timeout = 0;
3253 
3254 		fprintf(stdout, "Enter new timeout in seconds or press\n"
3255 			"return to keep the current timeout [%d] ",
3256 			use_timeout / 1000);
3257 
3258 		if (fgets(str, sizeof(str), stdin) != NULL) {
3259 			if (str[0] != '\0')
3260 				new_timeout = atoi(str);
3261 		}
3262 
3263 		if (new_timeout != 0) {
3264 			use_timeout = new_timeout * 1000;
3265 			fprintf(stdout, "Using new timeout value %d\n",
3266 				use_timeout / 1000);
3267 		}
3268 	}
3269 
3270 	/*
3271 	 * Keep this outside the if block below to silence any unused
3272 	 * variable warnings.
3273 	 */
3274 	bzero(&fh, sizeof(fh));
3275 
3276 	/*
3277 	 * If we're in immediate mode, we've got to include the format
3278 	 * header
3279 	 */
3280 	if (immediate != 0) {
3281 		fh.byte2 = FU_DLH_IMMED;
3282 		data_ptr = (u_int8_t *)&fh;
3283 		dxfer_len = sizeof(fh);
3284 		byte2 = FU_FMT_DATA;
3285 	} else if (quiet == 0) {
3286 		fprintf(stdout, "Formatting...");
3287 		fflush(stdout);
3288 	}
3289 
3290 	scsi_format_unit(&ccb->csio,
3291 			 /* retries */ retry_count,
3292 			 /* cbfcnp */ NULL,
3293 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
3294 			 /* byte2 */ byte2,
3295 			 /* ileave */ 0,
3296 			 /* data_ptr */ data_ptr,
3297 			 /* dxfer_len */ dxfer_len,
3298 			 /* sense_len */ SSD_FULL_SIZE,
3299 			 /* timeout */ use_timeout);
3300 
3301 	/* Disable freezing the device queue */
3302 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3303 
3304 	if (arglist & CAM_ARG_ERR_RECOVER)
3305 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3306 
3307 	if (((retval = cam_send_ccb(device, ccb)) < 0)
3308 	 || ((immediate == 0)
3309 	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3310 		const char errstr[] = "error sending format command";
3311 
3312 		if (retval < 0)
3313 			warn(errstr);
3314 		else
3315 			warnx(errstr);
3316 
3317 		if (arglist & CAM_ARG_VERBOSE) {
3318 			cam_error_print(device, ccb, CAM_ESF_ALL,
3319 					CAM_EPF_ALL, stderr);
3320 		}
3321 		error = 1;
3322 		goto scsiformat_bailout;
3323 	}
3324 
3325 	/*
3326 	 * If we ran in non-immediate mode, we already checked for errors
3327 	 * above and printed out any necessary information.  If we're in
3328 	 * immediate mode, we need to loop through and get status
3329 	 * information periodically.
3330 	 */
3331 	if (immediate == 0) {
3332 		if (quiet == 0) {
3333 			fprintf(stdout, "Format Complete\n");
3334 		}
3335 		goto scsiformat_bailout;
3336 	}
3337 
3338 doreport:
3339 	do {
3340 		cam_status status;
3341 
3342 		bzero(&(&ccb->ccb_h)[1],
3343 		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3344 
3345 		/*
3346 		 * There's really no need to do error recovery or
3347 		 * retries here, since we're just going to sit in a
3348 		 * loop and wait for the device to finish formatting.
3349 		 */
3350 		scsi_test_unit_ready(&ccb->csio,
3351 				     /* retries */ 0,
3352 				     /* cbfcnp */ NULL,
3353 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
3354 				     /* sense_len */ SSD_FULL_SIZE,
3355 				     /* timeout */ 5000);
3356 
3357 		/* Disable freezing the device queue */
3358 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3359 
3360 		retval = cam_send_ccb(device, ccb);
3361 
3362 		/*
3363 		 * If we get an error from the ioctl, bail out.  SCSI
3364 		 * errors are expected.
3365 		 */
3366 		if (retval < 0) {
3367 			warn("error sending CAMIOCOMMAND ioctl");
3368 			if (arglist & CAM_ARG_VERBOSE) {
3369 				cam_error_print(device, ccb, CAM_ESF_ALL,
3370 						CAM_EPF_ALL, stderr);
3371 			}
3372 			error = 1;
3373 			goto scsiformat_bailout;
3374 		}
3375 
3376 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
3377 
3378 		if ((status != CAM_REQ_CMP)
3379 		 && (status == CAM_SCSI_STATUS_ERROR)
3380 		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3381 			struct scsi_sense_data *sense;
3382 			int error_code, sense_key, asc, ascq;
3383 
3384 			sense = &ccb->csio.sense_data;
3385 			scsi_extract_sense(sense, &error_code, &sense_key,
3386 					   &asc, &ascq);
3387 
3388 			/*
3389 			 * According to the SCSI-2 and SCSI-3 specs, a
3390 			 * drive that is in the middle of a format should
3391 			 * return NOT READY with an ASC of "logical unit
3392 			 * not ready, format in progress".  The sense key
3393 			 * specific bytes will then be a progress indicator.
3394 			 */
3395 			if ((sense_key == SSD_KEY_NOT_READY)
3396 			 && (asc == 0x04) && (ascq == 0x04)) {
3397 				if ((sense->extra_len >= 10)
3398 				 && ((sense->sense_key_spec[0] &
3399 				      SSD_SCS_VALID) != 0)
3400 				 && (quiet == 0)) {
3401 					int val;
3402 					u_int64_t percentage;
3403 
3404 					val = scsi_2btoul(
3405 						&sense->sense_key_spec[1]);
3406 					percentage = 10000 * val;
3407 
3408 					fprintf(stdout,
3409 						"\rFormatting:  %ju.%02u %% "
3410 						"(%d/%d) done",
3411 						(uintmax_t)(percentage /
3412 						(0x10000 * 100)),
3413 						(unsigned)((percentage /
3414 						0x10000) % 100),
3415 						val, 0x10000);
3416 					fflush(stdout);
3417 				} else if ((quiet == 0)
3418 					&& (++num_warnings <= 1)) {
3419 					warnx("Unexpected SCSI Sense Key "
3420 					      "Specific value returned "
3421 					      "during format:");
3422 					scsi_sense_print(device, &ccb->csio,
3423 							 stderr);
3424 					warnx("Unable to print status "
3425 					      "information, but format will "
3426 					      "proceed.");
3427 					warnx("will exit when format is "
3428 					      "complete");
3429 				}
3430 				sleep(1);
3431 			} else {
3432 				warnx("Unexpected SCSI error during format");
3433 				cam_error_print(device, ccb, CAM_ESF_ALL,
3434 						CAM_EPF_ALL, stderr);
3435 				error = 1;
3436 				goto scsiformat_bailout;
3437 			}
3438 
3439 		} else if (status != CAM_REQ_CMP) {
3440 			warnx("Unexpected CAM status %#x", status);
3441 			if (arglist & CAM_ARG_VERBOSE)
3442 				cam_error_print(device, ccb, CAM_ESF_ALL,
3443 						CAM_EPF_ALL, stderr);
3444 			error = 1;
3445 			goto scsiformat_bailout;
3446 		}
3447 
3448 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3449 
3450 	if (quiet == 0)
3451 		fprintf(stdout, "\nFormat Complete\n");
3452 
3453 scsiformat_bailout:
3454 
3455 	cam_freeccb(ccb);
3456 
3457 	return(error);
3458 }
3459 
3460 static int
3461 scsireportluns(struct cam_device *device, int argc, char **argv,
3462 	       char *combinedopt, int retry_count, int timeout)
3463 {
3464 	union ccb *ccb;
3465 	int c, countonly, lunsonly;
3466 	struct scsi_report_luns_data *lundata;
3467 	int alloc_len;
3468 	uint8_t report_type;
3469 	uint32_t list_len, i, j;
3470 	int retval;
3471 
3472 	retval = 0;
3473 	lundata = NULL;
3474 	report_type = RPL_REPORT_DEFAULT;
3475 	ccb = cam_getccb(device);
3476 
3477 	if (ccb == NULL) {
3478 		warnx("%s: error allocating ccb", __func__);
3479 		return (1);
3480 	}
3481 
3482 	bzero(&(&ccb->ccb_h)[1],
3483 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3484 
3485 	countonly = 0;
3486 	lunsonly = 0;
3487 
3488 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3489 		switch (c) {
3490 		case 'c':
3491 			countonly++;
3492 			break;
3493 		case 'l':
3494 			lunsonly++;
3495 			break;
3496 		case 'r':
3497 			if (strcasecmp(optarg, "default") == 0)
3498 				report_type = RPL_REPORT_DEFAULT;
3499 			else if (strcasecmp(optarg, "wellknown") == 0)
3500 				report_type = RPL_REPORT_WELLKNOWN;
3501 			else if (strcasecmp(optarg, "all") == 0)
3502 				report_type = RPL_REPORT_ALL;
3503 			else {
3504 				warnx("%s: invalid report type \"%s\"",
3505 				      __func__, optarg);
3506 				retval = 1;
3507 				goto bailout;
3508 			}
3509 			break;
3510 		default:
3511 			break;
3512 		}
3513 	}
3514 
3515 	if ((countonly != 0)
3516 	 && (lunsonly != 0)) {
3517 		warnx("%s: you can only specify one of -c or -l", __func__);
3518 		retval = 1;
3519 		goto bailout;
3520 	}
3521 	/*
3522 	 * According to SPC-4, the allocation length must be at least 16
3523 	 * bytes -- enough for the header and one LUN.
3524 	 */
3525 	alloc_len = sizeof(*lundata) + 8;
3526 
3527 retry:
3528 
3529 	lundata = malloc(alloc_len);
3530 
3531 	if (lundata == NULL) {
3532 		warn("%s: error mallocing %d bytes", __func__, alloc_len);
3533 		retval = 1;
3534 		goto bailout;
3535 	}
3536 
3537 	scsi_report_luns(&ccb->csio,
3538 			 /*retries*/ retry_count,
3539 			 /*cbfcnp*/ NULL,
3540 			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3541 			 /*select_report*/ report_type,
3542 			 /*rpl_buf*/ lundata,
3543 			 /*alloc_len*/ alloc_len,
3544 			 /*sense_len*/ SSD_FULL_SIZE,
3545 			 /*timeout*/ timeout ? timeout : 5000);
3546 
3547 	/* Disable freezing the device queue */
3548 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3549 
3550 	if (arglist & CAM_ARG_ERR_RECOVER)
3551 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3552 
3553 	if (cam_send_ccb(device, ccb) < 0) {
3554 		warn("error sending REPORT LUNS command");
3555 
3556 		if (arglist & CAM_ARG_VERBOSE)
3557 			cam_error_print(device, ccb, CAM_ESF_ALL,
3558 					CAM_EPF_ALL, stderr);
3559 
3560 		retval = 1;
3561 		goto bailout;
3562 	}
3563 
3564 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3565 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3566 		retval = 1;
3567 		goto bailout;
3568 	}
3569 
3570 
3571 	list_len = scsi_4btoul(lundata->length);
3572 
3573 	/*
3574 	 * If we need to list the LUNs, and our allocation
3575 	 * length was too short, reallocate and retry.
3576 	 */
3577 	if ((countonly == 0)
3578 	 && (list_len > (alloc_len - sizeof(*lundata)))) {
3579 		alloc_len = list_len + sizeof(*lundata);
3580 		free(lundata);
3581 		goto retry;
3582 	}
3583 
3584 	if (lunsonly == 0)
3585 		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
3586 			((list_len / 8) > 1) ? "s" : "");
3587 
3588 	if (countonly != 0)
3589 		goto bailout;
3590 
3591 	for (i = 0; i < (list_len / 8); i++) {
3592 		int no_more;
3593 
3594 		no_more = 0;
3595 		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
3596 			if (j != 0)
3597 				fprintf(stdout, ",");
3598 			switch (lundata->luns[i].lundata[j] &
3599 				RPL_LUNDATA_ATYP_MASK) {
3600 			case RPL_LUNDATA_ATYP_PERIPH:
3601 				if ((lundata->luns[i].lundata[j] &
3602 				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
3603 					fprintf(stdout, "%d:",
3604 						lundata->luns[i].lundata[j] &
3605 						RPL_LUNDATA_PERIPH_BUS_MASK);
3606 				else if ((j == 0)
3607 				      && ((lundata->luns[i].lundata[j+2] &
3608 					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
3609 					no_more = 1;
3610 
3611 				fprintf(stdout, "%d",
3612 					lundata->luns[i].lundata[j+1]);
3613 				break;
3614 			case RPL_LUNDATA_ATYP_FLAT: {
3615 				uint8_t tmplun[2];
3616 				tmplun[0] = lundata->luns[i].lundata[j] &
3617 					RPL_LUNDATA_FLAT_LUN_MASK;
3618 				tmplun[1] = lundata->luns[i].lundata[j+1];
3619 
3620 				fprintf(stdout, "%d", scsi_2btoul(tmplun));
3621 				no_more = 1;
3622 				break;
3623 			}
3624 			case RPL_LUNDATA_ATYP_LUN:
3625 				fprintf(stdout, "%d:%d:%d",
3626 					(lundata->luns[i].lundata[j+1] &
3627 					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
3628 					lundata->luns[i].lundata[j] &
3629 					RPL_LUNDATA_LUN_TARG_MASK,
3630 					lundata->luns[i].lundata[j+1] &
3631 					RPL_LUNDATA_LUN_LUN_MASK);
3632 				break;
3633 			case RPL_LUNDATA_ATYP_EXTLUN: {
3634 				int field_len, field_len_code, eam_code;
3635 
3636 				eam_code = lundata->luns[i].lundata[j] &
3637 					RPL_LUNDATA_EXT_EAM_MASK;
3638 				field_len_code = (lundata->luns[i].lundata[j] &
3639 					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
3640 				field_len = field_len_code * 2;
3641 
3642 				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
3643 				 && (field_len_code == 0x00)) {
3644 					fprintf(stdout, "%d",
3645 						lundata->luns[i].lundata[j+1]);
3646 				} else if ((eam_code ==
3647 					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
3648 					&& (field_len_code == 0x03)) {
3649 					uint8_t tmp_lun[8];
3650 
3651 					/*
3652 					 * This format takes up all 8 bytes.
3653 					 * If we aren't starting at offset 0,
3654 					 * that's a bug.
3655 					 */
3656 					if (j != 0) {
3657 						fprintf(stdout, "Invalid "
3658 							"offset %d for "
3659 							"Extended LUN not "
3660 							"specified format", j);
3661 						no_more = 1;
3662 						break;
3663 					}
3664 					bzero(tmp_lun, sizeof(tmp_lun));
3665 					bcopy(&lundata->luns[i].lundata[j+1],
3666 					      &tmp_lun[1], sizeof(tmp_lun) - 1);
3667 					fprintf(stdout, "%#jx",
3668 					       (intmax_t)scsi_8btou64(tmp_lun));
3669 					no_more = 1;
3670 				} else {
3671 					fprintf(stderr, "Unknown Extended LUN"
3672 						"Address method %#x, length "
3673 						"code %#x", eam_code,
3674 						field_len_code);
3675 					no_more = 1;
3676 				}
3677 				break;
3678 			}
3679 			default:
3680 				fprintf(stderr, "Unknown LUN address method "
3681 					"%#x\n", lundata->luns[i].lundata[0] &
3682 					RPL_LUNDATA_ATYP_MASK);
3683 				break;
3684 			}
3685 			/*
3686 			 * For the flat addressing method, there are no
3687 			 * other levels after it.
3688 			 */
3689 			if (no_more != 0)
3690 				break;
3691 		}
3692 		fprintf(stdout, "\n");
3693 	}
3694 
3695 bailout:
3696 
3697 	cam_freeccb(ccb);
3698 
3699 	free(lundata);
3700 
3701 	return (retval);
3702 }
3703 
3704 static int
3705 scsireadcapacity(struct cam_device *device, int argc, char **argv,
3706 		 char *combinedopt, int retry_count, int timeout)
3707 {
3708 	union ccb *ccb;
3709 	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
3710 	struct scsi_read_capacity_data rcap;
3711 	struct scsi_read_capacity_data_long rcaplong;
3712 	uint64_t maxsector;
3713 	uint32_t block_len;
3714 	int retval;
3715 	int c;
3716 
3717 	blocksizeonly = 0;
3718 	humanize = 0;
3719 	numblocks = 0;
3720 	quiet = 0;
3721 	sizeonly = 0;
3722 	baseten = 0;
3723 	retval = 0;
3724 
3725 	ccb = cam_getccb(device);
3726 
3727 	if (ccb == NULL) {
3728 		warnx("%s: error allocating ccb", __func__);
3729 		return (1);
3730 	}
3731 
3732 	bzero(&(&ccb->ccb_h)[1],
3733 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3734 
3735 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3736 		switch (c) {
3737 		case 'b':
3738 			blocksizeonly++;
3739 			break;
3740 		case 'h':
3741 			humanize++;
3742 			baseten = 0;
3743 			break;
3744 		case 'H':
3745 			humanize++;
3746 			baseten++;
3747 			break;
3748 		case 'N':
3749 			numblocks++;
3750 			break;
3751 		case 'q':
3752 			quiet++;
3753 			break;
3754 		case 's':
3755 			sizeonly++;
3756 			break;
3757 		default:
3758 			break;
3759 		}
3760 	}
3761 
3762 	if ((blocksizeonly != 0)
3763 	 && (numblocks != 0)) {
3764 		warnx("%s: you can only specify one of -b or -N", __func__);
3765 		retval = 1;
3766 		goto bailout;
3767 	}
3768 
3769 	if ((blocksizeonly != 0)
3770 	 && (sizeonly != 0)) {
3771 		warnx("%s: you can only specify one of -b or -s", __func__);
3772 		retval = 1;
3773 		goto bailout;
3774 	}
3775 
3776 	if ((humanize != 0)
3777 	 && (quiet != 0)) {
3778 		warnx("%s: you can only specify one of -h/-H or -q", __func__);
3779 		retval = 1;
3780 		goto bailout;
3781 	}
3782 
3783 	if ((humanize != 0)
3784 	 && (blocksizeonly != 0)) {
3785 		warnx("%s: you can only specify one of -h/-H or -b", __func__);
3786 		retval = 1;
3787 		goto bailout;
3788 	}
3789 
3790 	scsi_read_capacity(&ccb->csio,
3791 			   /*retries*/ retry_count,
3792 			   /*cbfcnp*/ NULL,
3793 			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
3794 			   &rcap,
3795 			   SSD_FULL_SIZE,
3796 			   /*timeout*/ timeout ? timeout : 5000);
3797 
3798 	/* Disable freezing the device queue */
3799 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3800 
3801 	if (arglist & CAM_ARG_ERR_RECOVER)
3802 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3803 
3804 	if (cam_send_ccb(device, ccb) < 0) {
3805 		warn("error sending READ CAPACITY command");
3806 
3807 		if (arglist & CAM_ARG_VERBOSE)
3808 			cam_error_print(device, ccb, CAM_ESF_ALL,
3809 					CAM_EPF_ALL, stderr);
3810 
3811 		retval = 1;
3812 		goto bailout;
3813 	}
3814 
3815 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3816 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3817 		retval = 1;
3818 		goto bailout;
3819 	}
3820 
3821 	maxsector = scsi_4btoul(rcap.addr);
3822 	block_len = scsi_4btoul(rcap.length);
3823 
3824 	/*
3825 	 * A last block of 2^32-1 means that the true capacity is over 2TB,
3826 	 * and we need to issue the long READ CAPACITY to get the real
3827 	 * capacity.  Otherwise, we're all set.
3828 	 */
3829 	if (maxsector != 0xffffffff)
3830 		goto do_print;
3831 
3832 	scsi_read_capacity_16(&ccb->csio,
3833 			      /*retries*/ retry_count,
3834 			      /*cbfcnp*/ NULL,
3835 			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
3836 			      /*lba*/ 0,
3837 			      /*reladdr*/ 0,
3838 			      /*pmi*/ 0,
3839 			      &rcaplong,
3840 			      /*sense_len*/ SSD_FULL_SIZE,
3841 			      /*timeout*/ timeout ? timeout : 5000);
3842 
3843 	/* Disable freezing the device queue */
3844 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3845 
3846 	if (arglist & CAM_ARG_ERR_RECOVER)
3847 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3848 
3849 	if (cam_send_ccb(device, ccb) < 0) {
3850 		warn("error sending READ CAPACITY (16) command");
3851 
3852 		if (arglist & CAM_ARG_VERBOSE)
3853 			cam_error_print(device, ccb, CAM_ESF_ALL,
3854 					CAM_EPF_ALL, stderr);
3855 
3856 		retval = 1;
3857 		goto bailout;
3858 	}
3859 
3860 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3861 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3862 		retval = 1;
3863 		goto bailout;
3864 	}
3865 
3866 	maxsector = scsi_8btou64(rcaplong.addr);
3867 	block_len = scsi_4btoul(rcaplong.length);
3868 
3869 do_print:
3870 	if (blocksizeonly == 0) {
3871 		/*
3872 		 * Humanize implies !quiet, and also implies numblocks.
3873 		 */
3874 		if (humanize != 0) {
3875 			char tmpstr[6];
3876 			int64_t tmpbytes;
3877 			int ret;
3878 
3879 			tmpbytes = (maxsector + 1) * block_len;
3880 			ret = humanize_number(tmpstr, sizeof(tmpstr),
3881 					      tmpbytes, "", HN_AUTOSCALE,
3882 					      HN_B | HN_DECIMAL |
3883 					      ((baseten != 0) ?
3884 					      HN_DIVISOR_1000 : 0));
3885 			if (ret == -1) {
3886 				warnx("%s: humanize_number failed!", __func__);
3887 				retval = 1;
3888 				goto bailout;
3889 			}
3890 			fprintf(stdout, "Device Size: %s%s", tmpstr,
3891 				(sizeonly == 0) ?  ", " : "\n");
3892 		} else if (numblocks != 0) {
3893 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
3894 				"Blocks: " : "", (uintmax_t)maxsector + 1,
3895 				(sizeonly == 0) ? ", " : "\n");
3896 		} else {
3897 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
3898 				"Last Block: " : "", (uintmax_t)maxsector,
3899 				(sizeonly == 0) ? ", " : "\n");
3900 		}
3901 	}
3902 	if (sizeonly == 0)
3903 		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
3904 			"Block Length: " : "", block_len, (quiet == 0) ?
3905 			" bytes" : "");
3906 bailout:
3907 	cam_freeccb(ccb);
3908 
3909 	return (retval);
3910 }
3911 
3912 #endif /* MINIMALISTIC */
3913 
3914 void
3915 usage(int verbose)
3916 {
3917 	fprintf(verbose ? stdout : stderr,
3918 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
3919 "        camcontrol devlist    [-v]\n"
3920 #ifndef MINIMALISTIC
3921 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
3922 "        camcontrol tur        [dev_id][generic args]\n"
3923 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
3924 "        camcontrol identify   [dev_id][generic args]\n"
3925 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
3926 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
3927 "                              [-q] [-s]\n"
3928 "        camcontrol start      [dev_id][generic args]\n"
3929 "        camcontrol stop       [dev_id][generic args]\n"
3930 "        camcontrol load       [dev_id][generic args]\n"
3931 "        camcontrol eject      [dev_id][generic args]\n"
3932 #endif /* MINIMALISTIC */
3933 "        camcontrol rescan     <all | bus[:target:lun]>\n"
3934 "        camcontrol reset      <all | bus[:target:lun]>\n"
3935 #ifndef MINIMALISTIC
3936 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
3937 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
3938 "                              [-P pagectl][-e | -b][-d]\n"
3939 "        camcontrol cmd        [dev_id][generic args] <-c cmd [args]>\n"
3940 "                              [-i len fmt|-o len fmt [args]]\n"
3941 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
3942 "                              <all|bus[:target[:lun]]|off>\n"
3943 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
3944 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
3945 "                              [-D <enable|disable>][-O offset][-q]\n"
3946 "                              [-R syncrate][-v][-T <enable|disable>]\n"
3947 "                              [-U][-W bus_width]\n"
3948 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
3949 #endif /* MINIMALISTIC */
3950 "        camcontrol help\n");
3951 	if (!verbose)
3952 		return;
3953 #ifndef MINIMALISTIC
3954 	fprintf(stdout,
3955 "Specify one of the following options:\n"
3956 "devlist     list all CAM devices\n"
3957 "periphlist  list all CAM peripheral drivers attached to a device\n"
3958 "tur         send a test unit ready to the named device\n"
3959 "inquiry     send a SCSI inquiry command to the named device\n"
3960 "identify    send a ATA identify command to the named device\n"
3961 "reportluns  send a SCSI report luns command to the device\n"
3962 "readcap     send a SCSI read capacity command to the device\n"
3963 "start       send a Start Unit command to the device\n"
3964 "stop        send a Stop Unit command to the device\n"
3965 "load        send a Start Unit command to the device with the load bit set\n"
3966 "eject       send a Stop Unit command to the device with the eject bit set\n"
3967 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
3968 "reset       reset all busses, the given bus, or bus:target:lun\n"
3969 "defects     read the defect list of the specified device\n"
3970 "modepage    display or edit (-e) the given mode page\n"
3971 "cmd         send the given scsi command, may need -i or -o as well\n"
3972 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
3973 "tags        report or set the number of transaction slots for a device\n"
3974 "negotiate   report or set device negotiation parameters\n"
3975 "format      send the SCSI FORMAT UNIT command to the named device\n"
3976 "help        this message\n"
3977 "Device Identifiers:\n"
3978 "bus:target        specify the bus and target, lun defaults to 0\n"
3979 "bus:target:lun    specify the bus, target and lun\n"
3980 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
3981 "Generic arguments:\n"
3982 "-v                be verbose, print out sense information\n"
3983 "-t timeout        command timeout in seconds, overrides default timeout\n"
3984 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
3985 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
3986 "-E                have the kernel attempt to perform SCSI error recovery\n"
3987 "-C count          specify the SCSI command retry count (needs -E to work)\n"
3988 "modepage arguments:\n"
3989 "-l                list all available mode pages\n"
3990 "-m page           specify the mode page to view or edit\n"
3991 "-e                edit the specified mode page\n"
3992 "-b                force view to binary mode\n"
3993 "-d                disable block descriptors for mode sense\n"
3994 "-P pgctl          page control field 0-3\n"
3995 "defects arguments:\n"
3996 "-f format         specify defect list format (block, bfi or phys)\n"
3997 "-G                get the grown defect list\n"
3998 "-P                get the permanant defect list\n"
3999 "inquiry arguments:\n"
4000 "-D                get the standard inquiry data\n"
4001 "-S                get the serial number\n"
4002 "-R                get the transfer rate, etc.\n"
4003 "reportluns arguments:\n"
4004 "-c                only report a count of available LUNs\n"
4005 "-l                only print out luns, and not a count\n"
4006 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
4007 "readcap arguments\n"
4008 "-b                only report the blocksize\n"
4009 "-h                human readable device size, base 2\n"
4010 "-H                human readable device size, base 10\n"
4011 "-N                print the number of blocks instead of last block\n"
4012 "-q                quiet, print numbers only\n"
4013 "-s                only report the last block/device size\n"
4014 "cmd arguments:\n"
4015 "-c cdb [args]     specify the SCSI CDB\n"
4016 "-i len fmt        specify input data and input data format\n"
4017 "-o len fmt [args] specify output data and output data fmt\n"
4018 "debug arguments:\n"
4019 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
4020 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
4021 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
4022 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
4023 "tags arguments:\n"
4024 "-N tags           specify the number of tags to use for this device\n"
4025 "-q                be quiet, don't report the number of tags\n"
4026 "-v                report a number of tag-related parameters\n"
4027 "negotiate arguments:\n"
4028 "-a                send a test unit ready after negotiation\n"
4029 "-c                report/set current negotiation settings\n"
4030 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
4031 "-O offset         set command delay offset\n"
4032 "-q                be quiet, don't report anything\n"
4033 "-R syncrate       synchronization rate in MHz\n"
4034 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
4035 "-U                report/set user negotiation settings\n"
4036 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
4037 "-v                also print a Path Inquiry CCB for the controller\n"
4038 "format arguments:\n"
4039 "-q                be quiet, don't print status messages\n"
4040 "-r                run in report only mode\n"
4041 "-w                don't send immediate format command\n"
4042 "-y                don't ask any questions\n");
4043 #endif /* MINIMALISTIC */
4044 }
4045 
4046 int
4047 main(int argc, char **argv)
4048 {
4049 	int c;
4050 	char *device = NULL;
4051 	int unit = 0;
4052 	struct cam_device *cam_dev = NULL;
4053 	int timeout = 0, retry_count = 1;
4054 	camcontrol_optret optreturn;
4055 	char *tstr;
4056 	const char *mainopt = "C:En:t:u:v";
4057 	const char *subopt = NULL;
4058 	char combinedopt[256];
4059 	int error = 0, optstart = 2;
4060 	int devopen = 1;
4061 #ifndef MINIMALISTIC
4062 	int bus, target, lun;
4063 #endif /* MINIMALISTIC */
4064 
4065 	cmdlist = CAM_CMD_NONE;
4066 	arglist = CAM_ARG_NONE;
4067 
4068 	if (argc < 2) {
4069 		usage(0);
4070 		exit(1);
4071 	}
4072 
4073 	/*
4074 	 * Get the base option.
4075 	 */
4076 	optreturn = getoption(argv[1], &cmdlist, &arglist, &subopt);
4077 
4078 	if (optreturn == CC_OR_AMBIGUOUS) {
4079 		warnx("ambiguous option %s", argv[1]);
4080 		usage(0);
4081 		exit(1);
4082 	} else if (optreturn == CC_OR_NOT_FOUND) {
4083 		warnx("option %s not found", argv[1]);
4084 		usage(0);
4085 		exit(1);
4086 	}
4087 
4088 	/*
4089 	 * Ahh, getopt(3) is a pain.
4090 	 *
4091 	 * This is a gross hack.  There really aren't many other good
4092 	 * options (excuse the pun) for parsing options in a situation like
4093 	 * this.  getopt is kinda braindead, so you end up having to run
4094 	 * through the options twice, and give each invocation of getopt
4095 	 * the option string for the other invocation.
4096 	 *
4097 	 * You would think that you could just have two groups of options.
4098 	 * The first group would get parsed by the first invocation of
4099 	 * getopt, and the second group would get parsed by the second
4100 	 * invocation of getopt.  It doesn't quite work out that way.  When
4101 	 * the first invocation of getopt finishes, it leaves optind pointing
4102 	 * to the argument _after_ the first argument in the second group.
4103 	 * So when the second invocation of getopt comes around, it doesn't
4104 	 * recognize the first argument it gets and then bails out.
4105 	 *
4106 	 * A nice alternative would be to have a flag for getopt that says
4107 	 * "just keep parsing arguments even when you encounter an unknown
4108 	 * argument", but there isn't one.  So there's no real clean way to
4109 	 * easily parse two sets of arguments without having one invocation
4110 	 * of getopt know about the other.
4111 	 *
4112 	 * Without this hack, the first invocation of getopt would work as
4113 	 * long as the generic arguments are first, but the second invocation
4114 	 * (in the subfunction) would fail in one of two ways.  In the case
4115 	 * where you don't set optreset, it would fail because optind may be
4116 	 * pointing to the argument after the one it should be pointing at.
4117 	 * In the case where you do set optreset, and reset optind, it would
4118 	 * fail because getopt would run into the first set of options, which
4119 	 * it doesn't understand.
4120 	 *
4121 	 * All of this would "sort of" work if you could somehow figure out
4122 	 * whether optind had been incremented one option too far.  The
4123 	 * mechanics of that, however, are more daunting than just giving
4124 	 * both invocations all of the expect options for either invocation.
4125 	 *
4126 	 * Needless to say, I wouldn't mind if someone invented a better
4127 	 * (non-GPL!) command line parsing interface than getopt.  I
4128 	 * wouldn't mind if someone added more knobs to getopt to make it
4129 	 * work better.  Who knows, I may talk myself into doing it someday,
4130 	 * if the standards weenies let me.  As it is, it just leads to
4131 	 * hackery like this and causes people to avoid it in some cases.
4132 	 *
4133 	 * KDM, September 8th, 1998
4134 	 */
4135 	if (subopt != NULL)
4136 		sprintf(combinedopt, "%s%s", mainopt, subopt);
4137 	else
4138 		sprintf(combinedopt, "%s", mainopt);
4139 
4140 	/*
4141 	 * For these options we do not parse optional device arguments and
4142 	 * we do not open a passthrough device.
4143 	 */
4144 	if ((cmdlist == CAM_CMD_RESCAN)
4145 	 || (cmdlist == CAM_CMD_RESET)
4146 	 || (cmdlist == CAM_CMD_DEVTREE)
4147 	 || (cmdlist == CAM_CMD_USAGE)
4148 	 || (cmdlist == CAM_CMD_DEBUG))
4149 		devopen = 0;
4150 
4151 #ifndef MINIMALISTIC
4152 	if ((devopen == 1)
4153 	 && (argc > 2 && argv[2][0] != '-')) {
4154 		char name[30];
4155 		int rv;
4156 
4157 		/*
4158 		 * First catch people who try to do things like:
4159 		 * camcontrol tur /dev/da0
4160 		 * camcontrol doesn't take device nodes as arguments.
4161 		 */
4162 		if (argv[2][0] == '/') {
4163 			warnx("%s is not a valid device identifier", argv[2]);
4164 			errx(1, "please read the camcontrol(8) man page");
4165 		} else if (isdigit(argv[2][0])) {
4166 			/* device specified as bus:target[:lun] */
4167 			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
4168 			if (rv < 2)
4169 				errx(1, "numeric device specification must "
4170 				     "be either bus:target, or "
4171 				     "bus:target:lun");
4172 			/* default to 0 if lun was not specified */
4173 			if ((arglist & CAM_ARG_LUN) == 0) {
4174 				lun = 0;
4175 				arglist |= CAM_ARG_LUN;
4176 			}
4177 			optstart++;
4178 		} else {
4179 			if (cam_get_device(argv[2], name, sizeof name, &unit)
4180 			    == -1)
4181 				errx(1, "%s", cam_errbuf);
4182 			device = strdup(name);
4183 			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
4184 			optstart++;
4185 		}
4186 	}
4187 #endif /* MINIMALISTIC */
4188 	/*
4189 	 * Start getopt processing at argv[2/3], since we've already
4190 	 * accepted argv[1..2] as the command name, and as a possible
4191 	 * device name.
4192 	 */
4193 	optind = optstart;
4194 
4195 	/*
4196 	 * Now we run through the argument list looking for generic
4197 	 * options, and ignoring options that possibly belong to
4198 	 * subfunctions.
4199 	 */
4200 	while ((c = getopt(argc, argv, combinedopt))!= -1){
4201 		switch(c) {
4202 			case 'C':
4203 				retry_count = strtol(optarg, NULL, 0);
4204 				if (retry_count < 0)
4205 					errx(1, "retry count %d is < 0",
4206 					     retry_count);
4207 				arglist |= CAM_ARG_RETRIES;
4208 				break;
4209 			case 'E':
4210 				arglist |= CAM_ARG_ERR_RECOVER;
4211 				break;
4212 			case 'n':
4213 				arglist |= CAM_ARG_DEVICE;
4214 				tstr = optarg;
4215 				while (isspace(*tstr) && (*tstr != '\0'))
4216 					tstr++;
4217 				device = (char *)strdup(tstr);
4218 				break;
4219 			case 't':
4220 				timeout = strtol(optarg, NULL, 0);
4221 				if (timeout < 0)
4222 					errx(1, "invalid timeout %d", timeout);
4223 				/* Convert the timeout from seconds to ms */
4224 				timeout *= 1000;
4225 				arglist |= CAM_ARG_TIMEOUT;
4226 				break;
4227 			case 'u':
4228 				arglist |= CAM_ARG_UNIT;
4229 				unit = strtol(optarg, NULL, 0);
4230 				break;
4231 			case 'v':
4232 				arglist |= CAM_ARG_VERBOSE;
4233 				break;
4234 			default:
4235 				break;
4236 		}
4237 	}
4238 
4239 #ifndef MINIMALISTIC
4240 	/*
4241 	 * For most commands we'll want to open the passthrough device
4242 	 * associated with the specified device.  In the case of the rescan
4243 	 * commands, we don't use a passthrough device at all, just the
4244 	 * transport layer device.
4245 	 */
4246 	if (devopen == 1) {
4247 		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
4248 		 && (((arglist & CAM_ARG_DEVICE) == 0)
4249 		  || ((arglist & CAM_ARG_UNIT) == 0))) {
4250 			errx(1, "subcommand \"%s\" requires a valid device "
4251 			     "identifier", argv[1]);
4252 		}
4253 
4254 		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
4255 				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
4256 				cam_open_spec_device(device,unit,O_RDWR,NULL)))
4257 		     == NULL)
4258 			errx(1,"%s", cam_errbuf);
4259 	}
4260 #endif /* MINIMALISTIC */
4261 
4262 	/*
4263 	 * Reset optind to 2, and reset getopt, so these routines can parse
4264 	 * the arguments again.
4265 	 */
4266 	optind = optstart;
4267 	optreset = 1;
4268 
4269 	switch(cmdlist) {
4270 #ifndef MINIMALISTIC
4271 		case CAM_CMD_DEVLIST:
4272 			error = getdevlist(cam_dev);
4273 			break;
4274 #endif /* MINIMALISTIC */
4275 		case CAM_CMD_DEVTREE:
4276 			error = getdevtree();
4277 			break;
4278 #ifndef MINIMALISTIC
4279 		case CAM_CMD_TUR:
4280 			error = testunitready(cam_dev, retry_count, timeout, 0);
4281 			break;
4282 		case CAM_CMD_INQUIRY:
4283 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
4284 					      retry_count, timeout);
4285 			break;
4286 		case CAM_CMD_IDENTIFY:
4287 			error = ataidentify(cam_dev, retry_count, timeout);
4288 			break;
4289 		case CAM_CMD_STARTSTOP:
4290 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
4291 					  arglist & CAM_ARG_EJECT, retry_count,
4292 					  timeout);
4293 			break;
4294 #endif /* MINIMALISTIC */
4295 		case CAM_CMD_RESCAN:
4296 			error = dorescan_or_reset(argc, argv, 1);
4297 			break;
4298 		case CAM_CMD_RESET:
4299 			error = dorescan_or_reset(argc, argv, 0);
4300 			break;
4301 #ifndef MINIMALISTIC
4302 		case CAM_CMD_READ_DEFECTS:
4303 			error = readdefects(cam_dev, argc, argv, combinedopt,
4304 					    retry_count, timeout);
4305 			break;
4306 		case CAM_CMD_MODE_PAGE:
4307 			modepage(cam_dev, argc, argv, combinedopt,
4308 				 retry_count, timeout);
4309 			break;
4310 		case CAM_CMD_SCSI_CMD:
4311 			error = scsicmd(cam_dev, argc, argv, combinedopt,
4312 					retry_count, timeout);
4313 			break;
4314 		case CAM_CMD_DEBUG:
4315 			error = camdebug(argc, argv, combinedopt);
4316 			break;
4317 		case CAM_CMD_TAG:
4318 			error = tagcontrol(cam_dev, argc, argv, combinedopt);
4319 			break;
4320 		case CAM_CMD_RATE:
4321 			error = ratecontrol(cam_dev, retry_count, timeout,
4322 					    argc, argv, combinedopt);
4323 			break;
4324 		case CAM_CMD_FORMAT:
4325 			error = scsiformat(cam_dev, argc, argv,
4326 					   combinedopt, retry_count, timeout);
4327 			break;
4328 		case CAM_CMD_REPORTLUNS:
4329 			error = scsireportluns(cam_dev, argc, argv,
4330 					       combinedopt, retry_count,
4331 					       timeout);
4332 			break;
4333 		case CAM_CMD_READCAP:
4334 			error = scsireadcapacity(cam_dev, argc, argv,
4335 						 combinedopt, retry_count,
4336 						 timeout);
4337 			break;
4338 #endif /* MINIMALISTIC */
4339 		case CAM_CMD_USAGE:
4340 			usage(1);
4341 			break;
4342 		default:
4343 			usage(0);
4344 			error = 1;
4345 			break;
4346 	}
4347 
4348 	if (cam_dev != NULL)
4349 		cam_close_device(cam_dev);
4350 
4351 	exit(error);
4352 }
4353