xref: /freebsd/sbin/camcontrol/camcontrol.c (revision 724b4bfdf1306e4f2c451b6d146fe0fe0353b2c8)
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 #include <sys/sbuf.h>
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <inttypes.h>
43 #include <limits.h>
44 #include <fcntl.h>
45 #include <ctype.h>
46 #include <err.h>
47 #include <libutil.h>
48 
49 #include <cam/cam.h>
50 #include <cam/cam_debug.h>
51 #include <cam/cam_ccb.h>
52 #include <cam/scsi/scsi_all.h>
53 #include <cam/scsi/scsi_da.h>
54 #include <cam/scsi/scsi_pass.h>
55 #include <cam/scsi/scsi_message.h>
56 #include <cam/scsi/smp_all.h>
57 #include <cam/ata/ata_all.h>
58 #include <camlib.h>
59 #include "camcontrol.h"
60 
61 typedef enum {
62 	CAM_CMD_NONE		= 0x00000000,
63 	CAM_CMD_DEVLIST		= 0x00000001,
64 	CAM_CMD_TUR		= 0x00000002,
65 	CAM_CMD_INQUIRY		= 0x00000003,
66 	CAM_CMD_STARTSTOP	= 0x00000004,
67 	CAM_CMD_RESCAN		= 0x00000005,
68 	CAM_CMD_READ_DEFECTS	= 0x00000006,
69 	CAM_CMD_MODE_PAGE	= 0x00000007,
70 	CAM_CMD_SCSI_CMD	= 0x00000008,
71 	CAM_CMD_DEVTREE		= 0x00000009,
72 	CAM_CMD_USAGE		= 0x0000000a,
73 	CAM_CMD_DEBUG		= 0x0000000b,
74 	CAM_CMD_RESET		= 0x0000000c,
75 	CAM_CMD_FORMAT		= 0x0000000d,
76 	CAM_CMD_TAG		= 0x0000000e,
77 	CAM_CMD_RATE		= 0x0000000f,
78 	CAM_CMD_DETACH		= 0x00000010,
79 	CAM_CMD_REPORTLUNS	= 0x00000011,
80 	CAM_CMD_READCAP		= 0x00000012,
81 	CAM_CMD_IDENTIFY	= 0x00000013,
82 	CAM_CMD_IDLE		= 0x00000014,
83 	CAM_CMD_STANDBY		= 0x00000015,
84 	CAM_CMD_SLEEP		= 0x00000016,
85 	CAM_CMD_SMP_CMD		= 0x00000017,
86 	CAM_CMD_SMP_RG		= 0x00000018,
87 	CAM_CMD_SMP_PC		= 0x00000019,
88 	CAM_CMD_SMP_PHYLIST	= 0x0000001a,
89 	CAM_CMD_SMP_MANINFO	= 0x0000001b,
90 	CAM_CMD_DOWNLOAD_FW	= 0x0000001c
91 } cam_cmdmask;
92 
93 typedef enum {
94 	CAM_ARG_NONE		= 0x00000000,
95 	CAM_ARG_VERBOSE		= 0x00000001,
96 	CAM_ARG_DEVICE		= 0x00000002,
97 	CAM_ARG_BUS		= 0x00000004,
98 	CAM_ARG_TARGET		= 0x00000008,
99 	CAM_ARG_LUN		= 0x00000010,
100 	CAM_ARG_EJECT		= 0x00000020,
101 	CAM_ARG_UNIT		= 0x00000040,
102 	CAM_ARG_FORMAT_BLOCK	= 0x00000080,
103 	CAM_ARG_FORMAT_BFI	= 0x00000100,
104 	CAM_ARG_FORMAT_PHYS	= 0x00000200,
105 	CAM_ARG_PLIST		= 0x00000400,
106 	CAM_ARG_GLIST		= 0x00000800,
107 	CAM_ARG_GET_SERIAL	= 0x00001000,
108 	CAM_ARG_GET_STDINQ	= 0x00002000,
109 	CAM_ARG_GET_XFERRATE	= 0x00004000,
110 	CAM_ARG_INQ_MASK	= 0x00007000,
111 	CAM_ARG_MODE_EDIT	= 0x00008000,
112 	CAM_ARG_PAGE_CNTL	= 0x00010000,
113 	CAM_ARG_TIMEOUT		= 0x00020000,
114 	CAM_ARG_CMD_IN		= 0x00040000,
115 	CAM_ARG_CMD_OUT		= 0x00080000,
116 	CAM_ARG_DBD		= 0x00100000,
117 	CAM_ARG_ERR_RECOVER	= 0x00200000,
118 	CAM_ARG_RETRIES		= 0x00400000,
119 	CAM_ARG_START_UNIT	= 0x00800000,
120 	CAM_ARG_DEBUG_INFO	= 0x01000000,
121 	CAM_ARG_DEBUG_TRACE	= 0x02000000,
122 	CAM_ARG_DEBUG_SUBTRACE	= 0x04000000,
123 	CAM_ARG_DEBUG_CDB	= 0x08000000,
124 	CAM_ARG_DEBUG_XPT	= 0x10000000,
125 	CAM_ARG_DEBUG_PERIPH	= 0x20000000,
126 	CAM_ARG_DEBUG_PROBE	= 0x40000000,
127 } cam_argmask;
128 
129 struct camcontrol_opts {
130 	const char	*optname;
131 	uint32_t	cmdnum;
132 	cam_argmask	argnum;
133 	const char	*subopt;
134 };
135 
136 #ifndef MINIMALISTIC
137 static const char scsicmd_opts[] = "a:c:dfi:o:r";
138 static const char readdefect_opts[] = "f:GP";
139 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
140 static const char smprg_opts[] = "l";
141 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
142 static const char smpphylist_opts[] = "lq";
143 #endif
144 
145 static struct camcontrol_opts option_table[] = {
146 #ifndef MINIMALISTIC
147 	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
148 	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
149 	{"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
150 	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
151 	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
152 	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
153 	{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
154 	{"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
155 	{"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
156 #endif /* MINIMALISTIC */
157 	{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
158 	{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
159 #ifndef MINIMALISTIC
160 	{"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
161 	{"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
162 	{"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
163 	{"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
164 	{"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
165 	{"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
166 	{"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
167 	{"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
168 	{"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
169 	{"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
170 	{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
171 	{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
172 #endif /* MINIMALISTIC */
173 	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
174 #ifndef MINIMALISTIC
175 	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
176 	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
177 	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
178 	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
179 	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
180 	{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
181 	{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
182 	{"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
183 	{"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
184 	{"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
185 	{"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:ys"},
186 #endif /* MINIMALISTIC */
187 	{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
188 	{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
189 	{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
190 	{NULL, 0, 0, NULL}
191 };
192 
193 typedef enum {
194 	CC_OR_NOT_FOUND,
195 	CC_OR_AMBIGUOUS,
196 	CC_OR_FOUND
197 } camcontrol_optret;
198 
199 struct cam_devitem {
200 	struct device_match_result dev_match;
201 	int num_periphs;
202 	struct periph_match_result *periph_matches;
203 	struct scsi_vpd_device_id *device_id;
204 	int device_id_len;
205 	STAILQ_ENTRY(cam_devitem) links;
206 };
207 
208 struct cam_devlist {
209 	STAILQ_HEAD(, cam_devitem) dev_queue;
210 	path_id_t path_id;
211 };
212 
213 static cam_cmdmask cmdlist;
214 static cam_argmask arglist;
215 
216 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
217 			    uint32_t *cmdnum, cam_argmask *argnum,
218 			    const char **subopt);
219 #ifndef MINIMALISTIC
220 static int getdevlist(struct cam_device *device);
221 #endif /* MINIMALISTIC */
222 static int getdevtree(void);
223 #ifndef MINIMALISTIC
224 static int testunitready(struct cam_device *device, int retry_count,
225 			 int timeout, int quiet);
226 static int scsistart(struct cam_device *device, int startstop, int loadeject,
227 		     int retry_count, int timeout);
228 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
229 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
230 static int camxferrate(struct cam_device *device);
231 #endif /* MINIMALISTIC */
232 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
233 		     cam_argmask *arglst);
234 static int dorescan_or_reset(int argc, char **argv, int rescan);
235 static int rescan_or_reset_bus(int bus, int rescan);
236 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
237 #ifndef MINIMALISTIC
238 static int readdefects(struct cam_device *device, int argc, char **argv,
239 		       char *combinedopt, int retry_count, int timeout);
240 static void modepage(struct cam_device *device, int argc, char **argv,
241 		     char *combinedopt, int retry_count, int timeout);
242 static int scsicmd(struct cam_device *device, int argc, char **argv,
243 		   char *combinedopt, int retry_count, int timeout);
244 static int smpcmd(struct cam_device *device, int argc, char **argv,
245 		  char *combinedopt, int retry_count, int timeout);
246 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
247 			    char *combinedopt, int retry_count, int timeout);
248 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
249 			 char *combinedopt, int retry_count, int timeout);
250 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
251 		      char *combinedopt, int retry_count, int timeout);
252 static int getdevid(struct cam_devitem *item);
253 static int buildbusdevlist(struct cam_devlist *devlist);
254 static void freebusdevlist(struct cam_devlist *devlist);
255 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
256 					 uint64_t sasaddr);
257 static int smpphylist(struct cam_device *device, int argc, char **argv,
258 		      char *combinedopt, int retry_count, int timeout);
259 static int tagcontrol(struct cam_device *device, int argc, char **argv,
260 		      char *combinedopt);
261 static void cts_print(struct cam_device *device,
262 		      struct ccb_trans_settings *cts);
263 static void cpi_print(struct ccb_pathinq *cpi);
264 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
265 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
266 static int get_print_cts(struct cam_device *device, int user_settings,
267 			 int quiet, struct ccb_trans_settings *cts);
268 static int ratecontrol(struct cam_device *device, int retry_count,
269 		       int timeout, int argc, char **argv, char *combinedopt);
270 static int scsiformat(struct cam_device *device, int argc, char **argv,
271 		      char *combinedopt, int retry_count, int timeout);
272 static int scsireportluns(struct cam_device *device, int argc, char **argv,
273 			  char *combinedopt, int retry_count, int timeout);
274 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
275 			    char *combinedopt, int retry_count, int timeout);
276 static int atapm(struct cam_device *device, int argc, char **argv,
277 			    char *combinedopt, int retry_count, int timeout);
278 #endif /* MINIMALISTIC */
279 #ifndef min
280 #define min(a,b) (((a)<(b))?(a):(b))
281 #endif
282 #ifndef max
283 #define max(a,b) (((a)>(b))?(a):(b))
284 #endif
285 
286 camcontrol_optret
287 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
288 	  cam_argmask *argnum, const char **subopt)
289 {
290 	struct camcontrol_opts *opts;
291 	int num_matches = 0;
292 
293 	for (opts = table; (opts != NULL) && (opts->optname != NULL);
294 	     opts++) {
295 		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
296 			*cmdnum = opts->cmdnum;
297 			*argnum = opts->argnum;
298 			*subopt = opts->subopt;
299 			if (++num_matches > 1)
300 				return(CC_OR_AMBIGUOUS);
301 		}
302 	}
303 
304 	if (num_matches > 0)
305 		return(CC_OR_FOUND);
306 	else
307 		return(CC_OR_NOT_FOUND);
308 }
309 
310 #ifndef MINIMALISTIC
311 static int
312 getdevlist(struct cam_device *device)
313 {
314 	union ccb *ccb;
315 	char status[32];
316 	int error = 0;
317 
318 	ccb = cam_getccb(device);
319 
320 	ccb->ccb_h.func_code = XPT_GDEVLIST;
321 	ccb->ccb_h.flags = CAM_DIR_NONE;
322 	ccb->ccb_h.retry_count = 1;
323 	ccb->cgdl.index = 0;
324 	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
325 	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
326 		if (cam_send_ccb(device, ccb) < 0) {
327 			perror("error getting device list");
328 			cam_freeccb(ccb);
329 			return(1);
330 		}
331 
332 		status[0] = '\0';
333 
334 		switch (ccb->cgdl.status) {
335 			case CAM_GDEVLIST_MORE_DEVS:
336 				strcpy(status, "MORE");
337 				break;
338 			case CAM_GDEVLIST_LAST_DEVICE:
339 				strcpy(status, "LAST");
340 				break;
341 			case CAM_GDEVLIST_LIST_CHANGED:
342 				strcpy(status, "CHANGED");
343 				break;
344 			case CAM_GDEVLIST_ERROR:
345 				strcpy(status, "ERROR");
346 				error = 1;
347 				break;
348 		}
349 
350 		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
351 			ccb->cgdl.periph_name,
352 			ccb->cgdl.unit_number,
353 			ccb->cgdl.generation,
354 			ccb->cgdl.index,
355 			status);
356 
357 		/*
358 		 * If the list has changed, we need to start over from the
359 		 * beginning.
360 		 */
361 		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
362 			ccb->cgdl.index = 0;
363 	}
364 
365 	cam_freeccb(ccb);
366 
367 	return(error);
368 }
369 #endif /* MINIMALISTIC */
370 
371 static int
372 getdevtree(void)
373 {
374 	union ccb ccb;
375 	int bufsize, fd;
376 	unsigned int i;
377 	int need_close = 0;
378 	int error = 0;
379 	int skip_device = 0;
380 
381 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
382 		warn("couldn't open %s", XPT_DEVICE);
383 		return(1);
384 	}
385 
386 	bzero(&ccb, sizeof(union ccb));
387 
388 	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
389 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
390 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
391 
392 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
393 	bufsize = sizeof(struct dev_match_result) * 100;
394 	ccb.cdm.match_buf_len = bufsize;
395 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
396 	if (ccb.cdm.matches == NULL) {
397 		warnx("can't malloc memory for matches");
398 		close(fd);
399 		return(1);
400 	}
401 	ccb.cdm.num_matches = 0;
402 
403 	/*
404 	 * We fetch all nodes, since we display most of them in the default
405 	 * case, and all in the verbose case.
406 	 */
407 	ccb.cdm.num_patterns = 0;
408 	ccb.cdm.pattern_buf_len = 0;
409 
410 	/*
411 	 * We do the ioctl multiple times if necessary, in case there are
412 	 * more than 100 nodes in the EDT.
413 	 */
414 	do {
415 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
416 			warn("error sending CAMIOCOMMAND ioctl");
417 			error = 1;
418 			break;
419 		}
420 
421 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
422 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
423 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
424 			warnx("got CAM error %#x, CDM error %d\n",
425 			      ccb.ccb_h.status, ccb.cdm.status);
426 			error = 1;
427 			break;
428 		}
429 
430 		for (i = 0; i < ccb.cdm.num_matches; i++) {
431 			switch (ccb.cdm.matches[i].type) {
432 			case DEV_MATCH_BUS: {
433 				struct bus_match_result *bus_result;
434 
435 				/*
436 				 * Only print the bus information if the
437 				 * user turns on the verbose flag.
438 				 */
439 				if ((arglist & CAM_ARG_VERBOSE) == 0)
440 					break;
441 
442 				bus_result =
443 					&ccb.cdm.matches[i].result.bus_result;
444 
445 				if (need_close) {
446 					fprintf(stdout, ")\n");
447 					need_close = 0;
448 				}
449 
450 				fprintf(stdout, "scbus%d on %s%d bus %d:\n",
451 					bus_result->path_id,
452 					bus_result->dev_name,
453 					bus_result->unit_number,
454 					bus_result->bus_id);
455 				break;
456 			}
457 			case DEV_MATCH_DEVICE: {
458 				struct device_match_result *dev_result;
459 				char vendor[16], product[48], revision[16];
460 				char fw[5], tmpstr[256];
461 
462 				dev_result =
463 				     &ccb.cdm.matches[i].result.device_result;
464 
465 				if ((dev_result->flags
466 				     & DEV_RESULT_UNCONFIGURED)
467 				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
468 					skip_device = 1;
469 					break;
470 				} else
471 					skip_device = 0;
472 
473 				if (dev_result->protocol == PROTO_SCSI) {
474 				    cam_strvis(vendor, dev_result->inq_data.vendor,
475 					   sizeof(dev_result->inq_data.vendor),
476 					   sizeof(vendor));
477 				    cam_strvis(product,
478 					   dev_result->inq_data.product,
479 					   sizeof(dev_result->inq_data.product),
480 					   sizeof(product));
481 				    cam_strvis(revision,
482 					   dev_result->inq_data.revision,
483 					  sizeof(dev_result->inq_data.revision),
484 					   sizeof(revision));
485 				    sprintf(tmpstr, "<%s %s %s>", vendor, product,
486 					revision);
487 				} else if (dev_result->protocol == PROTO_ATA ||
488 				    dev_result->protocol == PROTO_SATAPM) {
489 				    cam_strvis(product,
490 					   dev_result->ident_data.model,
491 					   sizeof(dev_result->ident_data.model),
492 					   sizeof(product));
493 				    cam_strvis(revision,
494 					   dev_result->ident_data.revision,
495 					  sizeof(dev_result->ident_data.revision),
496 					   sizeof(revision));
497 				    sprintf(tmpstr, "<%s %s>", product,
498 					revision);
499 				} else if (dev_result->protocol == PROTO_SEMB) {
500 					struct sep_identify_data *sid;
501 
502 					sid = (struct sep_identify_data *)
503 					    &dev_result->ident_data;
504 					cam_strvis(vendor, sid->vendor_id,
505 					    sizeof(sid->vendor_id),
506 					    sizeof(vendor));
507 					cam_strvis(product, sid->product_id,
508 					    sizeof(sid->product_id),
509 					    sizeof(product));
510 					cam_strvis(revision, sid->product_rev,
511 					    sizeof(sid->product_rev),
512 					    sizeof(revision));
513 					cam_strvis(fw, sid->firmware_rev,
514 					    sizeof(sid->firmware_rev),
515 					    sizeof(fw));
516 					sprintf(tmpstr, "<%s %s %s %s>",
517 					    vendor, product, revision, fw);
518 				} else {
519 				    sprintf(tmpstr, "<>");
520 				}
521 				if (need_close) {
522 					fprintf(stdout, ")\n");
523 					need_close = 0;
524 				}
525 
526 				fprintf(stdout, "%-33s  at scbus%d "
527 					"target %d lun %d (",
528 					tmpstr,
529 					dev_result->path_id,
530 					dev_result->target_id,
531 					dev_result->target_lun);
532 
533 				need_close = 1;
534 
535 				break;
536 			}
537 			case DEV_MATCH_PERIPH: {
538 				struct periph_match_result *periph_result;
539 
540 				periph_result =
541 				      &ccb.cdm.matches[i].result.periph_result;
542 
543 				if (skip_device != 0)
544 					break;
545 
546 				if (need_close > 1)
547 					fprintf(stdout, ",");
548 
549 				fprintf(stdout, "%s%d",
550 					periph_result->periph_name,
551 					periph_result->unit_number);
552 
553 				need_close++;
554 				break;
555 			}
556 			default:
557 				fprintf(stdout, "unknown match type\n");
558 				break;
559 			}
560 		}
561 
562 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
563 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
564 
565 	if (need_close)
566 		fprintf(stdout, ")\n");
567 
568 	close(fd);
569 
570 	return(error);
571 }
572 
573 #ifndef MINIMALISTIC
574 static int
575 testunitready(struct cam_device *device, int retry_count, int timeout,
576 	      int quiet)
577 {
578 	int error = 0;
579 	union ccb *ccb;
580 
581 	ccb = cam_getccb(device);
582 
583 	scsi_test_unit_ready(&ccb->csio,
584 			     /* retries */ retry_count,
585 			     /* cbfcnp */ NULL,
586 			     /* tag_action */ MSG_SIMPLE_Q_TAG,
587 			     /* sense_len */ SSD_FULL_SIZE,
588 			     /* timeout */ timeout ? timeout : 5000);
589 
590 	/* Disable freezing the device queue */
591 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
592 
593 	if (arglist & CAM_ARG_ERR_RECOVER)
594 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
595 
596 	if (cam_send_ccb(device, ccb) < 0) {
597 		if (quiet == 0)
598 			perror("error sending test unit ready");
599 
600 		if (arglist & CAM_ARG_VERBOSE) {
601 			cam_error_print(device, ccb, CAM_ESF_ALL,
602 					CAM_EPF_ALL, stderr);
603 		}
604 
605 		cam_freeccb(ccb);
606 		return(1);
607 	}
608 
609 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
610 		if (quiet == 0)
611 			fprintf(stdout, "Unit is ready\n");
612 	} else {
613 		if (quiet == 0)
614 			fprintf(stdout, "Unit is not ready\n");
615 		error = 1;
616 
617 		if (arglist & CAM_ARG_VERBOSE) {
618 			cam_error_print(device, ccb, CAM_ESF_ALL,
619 					CAM_EPF_ALL, stderr);
620 		}
621 	}
622 
623 	cam_freeccb(ccb);
624 
625 	return(error);
626 }
627 
628 static int
629 scsistart(struct cam_device *device, int startstop, int loadeject,
630 	  int retry_count, int timeout)
631 {
632 	union ccb *ccb;
633 	int error = 0;
634 
635 	ccb = cam_getccb(device);
636 
637 	/*
638 	 * If we're stopping, send an ordered tag so the drive in question
639 	 * will finish any previously queued writes before stopping.  If
640 	 * the device isn't capable of tagged queueing, or if tagged
641 	 * queueing is turned off, the tag action is a no-op.
642 	 */
643 	scsi_start_stop(&ccb->csio,
644 			/* retries */ retry_count,
645 			/* cbfcnp */ NULL,
646 			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
647 						     MSG_ORDERED_Q_TAG,
648 			/* start/stop */ startstop,
649 			/* load_eject */ loadeject,
650 			/* immediate */ 0,
651 			/* sense_len */ SSD_FULL_SIZE,
652 			/* timeout */ timeout ? timeout : 120000);
653 
654 	/* Disable freezing the device queue */
655 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
656 
657 	if (arglist & CAM_ARG_ERR_RECOVER)
658 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
659 
660 	if (cam_send_ccb(device, ccb) < 0) {
661 		perror("error sending start unit");
662 
663 		if (arglist & CAM_ARG_VERBOSE) {
664 			cam_error_print(device, ccb, CAM_ESF_ALL,
665 					CAM_EPF_ALL, stderr);
666 		}
667 
668 		cam_freeccb(ccb);
669 		return(1);
670 	}
671 
672 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
673 		if (startstop) {
674 			fprintf(stdout, "Unit started successfully");
675 			if (loadeject)
676 				fprintf(stdout,", Media loaded\n");
677 			else
678 				fprintf(stdout,"\n");
679 		} else {
680 			fprintf(stdout, "Unit stopped successfully");
681 			if (loadeject)
682 				fprintf(stdout, ", Media ejected\n");
683 			else
684 				fprintf(stdout, "\n");
685 		}
686 	else {
687 		error = 1;
688 		if (startstop)
689 			fprintf(stdout,
690 				"Error received from start unit command\n");
691 		else
692 			fprintf(stdout,
693 				"Error received from stop unit command\n");
694 
695 		if (arglist & CAM_ARG_VERBOSE) {
696 			cam_error_print(device, ccb, CAM_ESF_ALL,
697 					CAM_EPF_ALL, stderr);
698 		}
699 	}
700 
701 	cam_freeccb(ccb);
702 
703 	return(error);
704 }
705 
706 int
707 scsidoinquiry(struct cam_device *device, int argc, char **argv,
708 	      char *combinedopt, int retry_count, int timeout)
709 {
710 	int c;
711 	int error = 0;
712 
713 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
714 		switch(c) {
715 		case 'D':
716 			arglist |= CAM_ARG_GET_STDINQ;
717 			break;
718 		case 'R':
719 			arglist |= CAM_ARG_GET_XFERRATE;
720 			break;
721 		case 'S':
722 			arglist |= CAM_ARG_GET_SERIAL;
723 			break;
724 		default:
725 			break;
726 		}
727 	}
728 
729 	/*
730 	 * If the user didn't specify any inquiry options, he wants all of
731 	 * them.
732 	 */
733 	if ((arglist & CAM_ARG_INQ_MASK) == 0)
734 		arglist |= CAM_ARG_INQ_MASK;
735 
736 	if (arglist & CAM_ARG_GET_STDINQ)
737 		error = scsiinquiry(device, retry_count, timeout);
738 
739 	if (error != 0)
740 		return(error);
741 
742 	if (arglist & CAM_ARG_GET_SERIAL)
743 		scsiserial(device, retry_count, timeout);
744 
745 	if (error != 0)
746 		return(error);
747 
748 	if (arglist & CAM_ARG_GET_XFERRATE)
749 		error = camxferrate(device);
750 
751 	return(error);
752 }
753 
754 static int
755 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
756 {
757 	union ccb *ccb;
758 	struct scsi_inquiry_data *inq_buf;
759 	int error = 0;
760 
761 	ccb = cam_getccb(device);
762 
763 	if (ccb == NULL) {
764 		warnx("couldn't allocate CCB");
765 		return(1);
766 	}
767 
768 	/* cam_getccb cleans up the header, caller has to zero the payload */
769 	bzero(&(&ccb->ccb_h)[1],
770 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
771 
772 	inq_buf = (struct scsi_inquiry_data *)malloc(
773 		sizeof(struct scsi_inquiry_data));
774 
775 	if (inq_buf == NULL) {
776 		cam_freeccb(ccb);
777 		warnx("can't malloc memory for inquiry\n");
778 		return(1);
779 	}
780 	bzero(inq_buf, sizeof(*inq_buf));
781 
782 	/*
783 	 * Note that although the size of the inquiry buffer is the full
784 	 * 256 bytes specified in the SCSI spec, we only tell the device
785 	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
786 	 * two reasons for this:
787 	 *
788 	 *  - The SCSI spec says that when a length field is only 1 byte,
789 	 *    a value of 0 will be interpreted as 256.  Therefore
790 	 *    scsi_inquiry() will convert an inq_len (which is passed in as
791 	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
792 	 *    to 0.  Evidently, very few devices meet the spec in that
793 	 *    regard.  Some devices, like many Seagate disks, take the 0 as
794 	 *    0, and don't return any data.  One Pioneer DVD-R drive
795 	 *    returns more data than the command asked for.
796 	 *
797 	 *    So, since there are numerous devices that just don't work
798 	 *    right with the full inquiry size, we don't send the full size.
799 	 *
800 	 *  - The second reason not to use the full inquiry data length is
801 	 *    that we don't need it here.  The only reason we issue a
802 	 *    standard inquiry is to get the vendor name, device name,
803 	 *    and revision so scsi_print_inquiry() can print them.
804 	 *
805 	 * If, at some point in the future, more inquiry data is needed for
806 	 * some reason, this code should use a procedure similar to the
807 	 * probe code.  i.e., issue a short inquiry, and determine from
808 	 * the additional length passed back from the device how much
809 	 * inquiry data the device supports.  Once the amount the device
810 	 * supports is determined, issue an inquiry for that amount and no
811 	 * more.
812 	 *
813 	 * KDM, 2/18/2000
814 	 */
815 	scsi_inquiry(&ccb->csio,
816 		     /* retries */ retry_count,
817 		     /* cbfcnp */ NULL,
818 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
819 		     /* inq_buf */ (u_int8_t *)inq_buf,
820 		     /* inq_len */ SHORT_INQUIRY_LENGTH,
821 		     /* evpd */ 0,
822 		     /* page_code */ 0,
823 		     /* sense_len */ SSD_FULL_SIZE,
824 		     /* timeout */ timeout ? timeout : 5000);
825 
826 	/* Disable freezing the device queue */
827 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
828 
829 	if (arglist & CAM_ARG_ERR_RECOVER)
830 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
831 
832 	if (cam_send_ccb(device, ccb) < 0) {
833 		perror("error sending SCSI inquiry");
834 
835 		if (arglist & CAM_ARG_VERBOSE) {
836 			cam_error_print(device, ccb, CAM_ESF_ALL,
837 					CAM_EPF_ALL, stderr);
838 		}
839 
840 		cam_freeccb(ccb);
841 		return(1);
842 	}
843 
844 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
845 		error = 1;
846 
847 		if (arglist & CAM_ARG_VERBOSE) {
848 			cam_error_print(device, ccb, CAM_ESF_ALL,
849 					CAM_EPF_ALL, stderr);
850 		}
851 	}
852 
853 	cam_freeccb(ccb);
854 
855 	if (error != 0) {
856 		free(inq_buf);
857 		return(error);
858 	}
859 
860 	fprintf(stdout, "%s%d: ", device->device_name,
861 		device->dev_unit_num);
862 	scsi_print_inquiry(inq_buf);
863 
864 	free(inq_buf);
865 
866 	return(0);
867 }
868 
869 static int
870 scsiserial(struct cam_device *device, int retry_count, int timeout)
871 {
872 	union ccb *ccb;
873 	struct scsi_vpd_unit_serial_number *serial_buf;
874 	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
875 	int error = 0;
876 
877 	ccb = cam_getccb(device);
878 
879 	if (ccb == NULL) {
880 		warnx("couldn't allocate CCB");
881 		return(1);
882 	}
883 
884 	/* cam_getccb cleans up the header, caller has to zero the payload */
885 	bzero(&(&ccb->ccb_h)[1],
886 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
887 
888 	serial_buf = (struct scsi_vpd_unit_serial_number *)
889 		malloc(sizeof(*serial_buf));
890 
891 	if (serial_buf == NULL) {
892 		cam_freeccb(ccb);
893 		warnx("can't malloc memory for serial number");
894 		return(1);
895 	}
896 
897 	scsi_inquiry(&ccb->csio,
898 		     /*retries*/ retry_count,
899 		     /*cbfcnp*/ NULL,
900 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
901 		     /* inq_buf */ (u_int8_t *)serial_buf,
902 		     /* inq_len */ sizeof(*serial_buf),
903 		     /* evpd */ 1,
904 		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
905 		     /* sense_len */ SSD_FULL_SIZE,
906 		     /* timeout */ timeout ? timeout : 5000);
907 
908 	/* Disable freezing the device queue */
909 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
910 
911 	if (arglist & CAM_ARG_ERR_RECOVER)
912 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
913 
914 	if (cam_send_ccb(device, ccb) < 0) {
915 		warn("error getting serial number");
916 
917 		if (arglist & CAM_ARG_VERBOSE) {
918 			cam_error_print(device, ccb, CAM_ESF_ALL,
919 					CAM_EPF_ALL, stderr);
920 		}
921 
922 		cam_freeccb(ccb);
923 		free(serial_buf);
924 		return(1);
925 	}
926 
927 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
928 		error = 1;
929 
930 		if (arglist & CAM_ARG_VERBOSE) {
931 			cam_error_print(device, ccb, CAM_ESF_ALL,
932 					CAM_EPF_ALL, stderr);
933 		}
934 	}
935 
936 	cam_freeccb(ccb);
937 
938 	if (error != 0) {
939 		free(serial_buf);
940 		return(error);
941 	}
942 
943 	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
944 	serial_num[serial_buf->length] = '\0';
945 
946 	if ((arglist & CAM_ARG_GET_STDINQ)
947 	 || (arglist & CAM_ARG_GET_XFERRATE))
948 		fprintf(stdout, "%s%d: Serial Number ",
949 			device->device_name, device->dev_unit_num);
950 
951 	fprintf(stdout, "%.60s\n", serial_num);
952 
953 	free(serial_buf);
954 
955 	return(0);
956 }
957 
958 static int
959 camxferrate(struct cam_device *device)
960 {
961 	struct ccb_pathinq cpi;
962 	u_int32_t freq = 0;
963 	u_int32_t speed = 0;
964 	union ccb *ccb;
965 	u_int mb;
966 	int retval = 0;
967 
968 	if ((retval = get_cpi(device, &cpi)) != 0)
969 		return (1);
970 
971 	ccb = cam_getccb(device);
972 
973 	if (ccb == NULL) {
974 		warnx("couldn't allocate CCB");
975 		return(1);
976 	}
977 
978 	bzero(&(&ccb->ccb_h)[1],
979 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
980 
981 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
982 	ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
983 
984 	if (((retval = cam_send_ccb(device, ccb)) < 0)
985 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
986 		const char error_string[] = "error getting transfer settings";
987 
988 		if (retval < 0)
989 			warn(error_string);
990 		else
991 			warnx(error_string);
992 
993 		if (arglist & CAM_ARG_VERBOSE)
994 			cam_error_print(device, ccb, CAM_ESF_ALL,
995 					CAM_EPF_ALL, stderr);
996 
997 		retval = 1;
998 
999 		goto xferrate_bailout;
1000 
1001 	}
1002 
1003 	speed = cpi.base_transfer_speed;
1004 	freq = 0;
1005 	if (ccb->cts.transport == XPORT_SPI) {
1006 		struct ccb_trans_settings_spi *spi =
1007 		    &ccb->cts.xport_specific.spi;
1008 
1009 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1010 			freq = scsi_calc_syncsrate(spi->sync_period);
1011 			speed = freq;
1012 		}
1013 		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1014 			speed *= (0x01 << spi->bus_width);
1015 		}
1016 	} else if (ccb->cts.transport == XPORT_FC) {
1017 		struct ccb_trans_settings_fc *fc =
1018 		    &ccb->cts.xport_specific.fc;
1019 
1020 		if (fc->valid & CTS_FC_VALID_SPEED)
1021 			speed = fc->bitrate;
1022 	} else if (ccb->cts.transport == XPORT_SAS) {
1023 		struct ccb_trans_settings_sas *sas =
1024 		    &ccb->cts.xport_specific.sas;
1025 
1026 		if (sas->valid & CTS_SAS_VALID_SPEED)
1027 			speed = sas->bitrate;
1028 	} else if (ccb->cts.transport == XPORT_ATA) {
1029 		struct ccb_trans_settings_pata *pata =
1030 		    &ccb->cts.xport_specific.ata;
1031 
1032 		if (pata->valid & CTS_ATA_VALID_MODE)
1033 			speed = ata_mode2speed(pata->mode);
1034 	} else if (ccb->cts.transport == XPORT_SATA) {
1035 		struct	ccb_trans_settings_sata *sata =
1036 		    &ccb->cts.xport_specific.sata;
1037 
1038 		if (sata->valid & CTS_SATA_VALID_REVISION)
1039 			speed = ata_revision2speed(sata->revision);
1040 	}
1041 
1042 	mb = speed / 1000;
1043 	if (mb > 0) {
1044 		fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1045 			device->device_name, device->dev_unit_num,
1046 			mb, speed % 1000);
1047 	} else {
1048 		fprintf(stdout, "%s%d: %dKB/s transfers",
1049 			device->device_name, device->dev_unit_num,
1050 			speed);
1051 	}
1052 
1053 	if (ccb->cts.transport == XPORT_SPI) {
1054 		struct ccb_trans_settings_spi *spi =
1055 		    &ccb->cts.xport_specific.spi;
1056 
1057 		if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1058 		 && (spi->sync_offset != 0))
1059 			fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1060 				freq % 1000, spi->sync_offset);
1061 
1062 		if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1063 		 && (spi->bus_width > 0)) {
1064 			if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1065 			 && (spi->sync_offset != 0)) {
1066 				fprintf(stdout, ", ");
1067 			} else {
1068 				fprintf(stdout, " (");
1069 			}
1070 			fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1071 		} else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1072 		 && (spi->sync_offset != 0)) {
1073 			fprintf(stdout, ")");
1074 		}
1075 	} else if (ccb->cts.transport == XPORT_ATA) {
1076 		struct ccb_trans_settings_pata *pata =
1077 		    &ccb->cts.xport_specific.ata;
1078 
1079 		printf(" (");
1080 		if (pata->valid & CTS_ATA_VALID_MODE)
1081 			printf("%s, ", ata_mode2string(pata->mode));
1082 		if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1083 			printf("ATAPI %dbytes, ", pata->atapi);
1084 		if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1085 			printf("PIO %dbytes", pata->bytecount);
1086 		printf(")");
1087 	} else if (ccb->cts.transport == XPORT_SATA) {
1088 		struct ccb_trans_settings_sata *sata =
1089 		    &ccb->cts.xport_specific.sata;
1090 
1091 		printf(" (");
1092 		if (sata->valid & CTS_SATA_VALID_REVISION)
1093 			printf("SATA %d.x, ", sata->revision);
1094 		else
1095 			printf("SATA, ");
1096 		if (sata->valid & CTS_SATA_VALID_MODE)
1097 			printf("%s, ", ata_mode2string(sata->mode));
1098 		if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1099 			printf("ATAPI %dbytes, ", sata->atapi);
1100 		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1101 			printf("PIO %dbytes", sata->bytecount);
1102 		printf(")");
1103 	}
1104 
1105 	if (ccb->cts.protocol == PROTO_SCSI) {
1106 		struct ccb_trans_settings_scsi *scsi =
1107 		    &ccb->cts.proto_specific.scsi;
1108 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
1109 			if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1110 				fprintf(stdout, ", Command Queueing Enabled");
1111 			}
1112 		}
1113 	}
1114 
1115         fprintf(stdout, "\n");
1116 
1117 xferrate_bailout:
1118 
1119 	cam_freeccb(ccb);
1120 
1121 	return(retval);
1122 }
1123 
1124 static void
1125 atacapprint(struct ata_params *parm)
1126 {
1127 	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1128 				((u_int32_t)parm->lba_size_2 << 16);
1129 
1130 	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1131 				((u_int64_t)parm->lba_size48_2 << 16) |
1132 				((u_int64_t)parm->lba_size48_3 << 32) |
1133 				((u_int64_t)parm->lba_size48_4 << 48);
1134 
1135 	printf("\n");
1136 	printf("protocol              ");
1137 	printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1138 	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1139 		if (parm->satacapabilities & ATA_SATA_GEN3)
1140 			printf(" SATA 3.x\n");
1141 		else if (parm->satacapabilities & ATA_SATA_GEN2)
1142 			printf(" SATA 2.x\n");
1143 		else if (parm->satacapabilities & ATA_SATA_GEN1)
1144 			printf(" SATA 1.x\n");
1145 		else
1146 			printf(" SATA\n");
1147 	}
1148 	else
1149 		printf("\n");
1150 	printf("device model          %.40s\n", parm->model);
1151 	printf("firmware revision     %.8s\n", parm->revision);
1152 	printf("serial number         %.20s\n", parm->serial);
1153 	if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1154 		printf("WWN                   %04x%04x%04x%04x\n",
1155 		    parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1156 	}
1157 	if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1158 		printf("media serial number   %.30s\n",
1159 		    parm->media_serial);
1160 	}
1161 
1162 	printf("cylinders             %d\n", parm->cylinders);
1163 	printf("heads                 %d\n", parm->heads);
1164 	printf("sectors/track         %d\n", parm->sectors);
1165 	printf("sector size           logical %u, physical %lu, offset %lu\n",
1166 	    ata_logical_sector_size(parm),
1167 	    (unsigned long)ata_physical_sector_size(parm),
1168 	    (unsigned long)ata_logical_sector_offset(parm));
1169 
1170 	if (parm->config == ATA_PROTO_CFA ||
1171 	    (parm->support.command2 & ATA_SUPPORT_CFA))
1172 		printf("CFA supported\n");
1173 
1174 	printf("LBA%ssupported         ",
1175 		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1176 	if (lbasize)
1177 		printf("%d sectors\n", lbasize);
1178 	else
1179 		printf("\n");
1180 
1181 	printf("LBA48%ssupported       ",
1182 		parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1183 	if (lbasize48)
1184 		printf("%ju sectors\n", (uintmax_t)lbasize48);
1185 	else
1186 		printf("\n");
1187 
1188 	printf("PIO supported         PIO");
1189 	switch (ata_max_pmode(parm)) {
1190 	case ATA_PIO4:
1191 		printf("4");
1192 		break;
1193 	case ATA_PIO3:
1194 		printf("3");
1195 		break;
1196 	case ATA_PIO2:
1197 		printf("2");
1198 		break;
1199 	case ATA_PIO1:
1200 		printf("1");
1201 		break;
1202 	default:
1203 		printf("0");
1204 	}
1205 	if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1206 		printf(" w/o IORDY");
1207 	printf("\n");
1208 
1209 	printf("DMA%ssupported         ",
1210 		parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1211 	if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1212 		if (parm->mwdmamodes & 0xff) {
1213 			printf("WDMA");
1214 			if (parm->mwdmamodes & 0x04)
1215 				printf("2");
1216 			else if (parm->mwdmamodes & 0x02)
1217 				printf("1");
1218 			else if (parm->mwdmamodes & 0x01)
1219 				printf("0");
1220 			printf(" ");
1221 		}
1222 		if ((parm->atavalid & ATA_FLAG_88) &&
1223 		    (parm->udmamodes & 0xff)) {
1224 			printf("UDMA");
1225 			if (parm->udmamodes & 0x40)
1226 				printf("6");
1227 			else if (parm->udmamodes & 0x20)
1228 				printf("5");
1229 			else if (parm->udmamodes & 0x10)
1230 				printf("4");
1231 			else if (parm->udmamodes & 0x08)
1232 				printf("3");
1233 			else if (parm->udmamodes & 0x04)
1234 				printf("2");
1235 			else if (parm->udmamodes & 0x02)
1236 				printf("1");
1237 			else if (parm->udmamodes & 0x01)
1238 				printf("0");
1239 			printf(" ");
1240 		}
1241 	}
1242 	printf("\n");
1243 
1244 	if (parm->media_rotation_rate == 1) {
1245 		printf("media RPM             non-rotating\n");
1246 	} else if (parm->media_rotation_rate >= 0x0401 &&
1247 	    parm->media_rotation_rate <= 0xFFFE) {
1248 		printf("media RPM             %d\n",
1249 			parm->media_rotation_rate);
1250 	}
1251 
1252 	printf("\nFeature                      "
1253 		"Support  Enabled   Value           Vendor\n");
1254 	printf("read ahead                     %s	%s\n",
1255 		parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1256 		parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1257 	printf("write cache                    %s	%s\n",
1258 		parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1259 		parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1260 	printf("flush cache                    %s	%s\n",
1261 		parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1262 		parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1263 	printf("overlap                        %s\n",
1264 		parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1265 	printf("Tagged Command Queuing (TCQ)   %s	%s",
1266 		parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1267 		parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1268 		if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1269 			printf("	%d tags\n",
1270 			    ATA_QUEUE_LEN(parm->queue) + 1);
1271 		} else
1272 			printf("\n");
1273 	printf("Native Command Queuing (NCQ)   ");
1274 	if (parm->satacapabilities != 0xffff &&
1275 	    (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1276 		printf("yes		%d tags\n",
1277 		    ATA_QUEUE_LEN(parm->queue) + 1);
1278 	} else
1279 		printf("no\n");
1280 	printf("SMART                          %s	%s\n",
1281 		parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1282 		parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1283 	printf("microcode download             %s	%s\n",
1284 		parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1285 		parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1286 	printf("security                       %s	%s\n",
1287 		parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1288 		parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1289 	printf("power management               %s	%s\n",
1290 		parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1291 		parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1292 	printf("advanced power management      %s	%s",
1293 		parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1294 		parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1295 		if (parm->support.command2 & ATA_SUPPORT_APM) {
1296 			printf("	%d/0x%02X\n",
1297 			    parm->apm_value, parm->apm_value);
1298 		} else
1299 			printf("\n");
1300 	printf("automatic acoustic management  %s	%s",
1301 		parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1302 		parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1303 		if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1304 			printf("	%d/0x%02X	%d/0x%02X\n",
1305 			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1306 			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1307 			    ATA_ACOUSTIC_VENDOR(parm->acoustic),
1308 			    ATA_ACOUSTIC_VENDOR(parm->acoustic));
1309 		} else
1310 			printf("\n");
1311 	printf("media status notification      %s	%s\n",
1312 		parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1313 		parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1314 	printf("power-up in Standby            %s	%s\n",
1315 		parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1316 		parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1317 	printf("write-read-verify              %s	%s",
1318 		parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1319 		parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1320 		if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1321 			printf("	%d/0x%x\n",
1322 			    parm->wrv_mode, parm->wrv_mode);
1323 		} else
1324 			printf("\n");
1325 	printf("unload                         %s	%s\n",
1326 		parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1327 		parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1328 	printf("free-fall                      %s	%s\n",
1329 		parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1330 		parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1331 	printf("data set management (TRIM)     %s\n",
1332 		parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1333 }
1334 
1335 static int
1336 ataidentify(struct cam_device *device, int retry_count, int timeout)
1337 {
1338 	union ccb *ccb;
1339 	struct ata_params *ident_buf;
1340 	struct ccb_getdev cgd;
1341 	u_int i, error = 0;
1342 	int16_t *ptr;
1343 
1344 	if (get_cgd(device, &cgd) != 0) {
1345 		warnx("couldn't get CGD");
1346 		return(1);
1347 	}
1348 	ccb = cam_getccb(device);
1349 
1350 	if (ccb == NULL) {
1351 		warnx("couldn't allocate CCB");
1352 		return(1);
1353 	}
1354 
1355 	/* cam_getccb cleans up the header, caller has to zero the payload */
1356 	bzero(&(&ccb->ccb_h)[1],
1357 	      sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1358 
1359 	ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1360 
1361 	if (ptr == NULL) {
1362 		cam_freeccb(ccb);
1363 		warnx("can't malloc memory for identify\n");
1364 		return(1);
1365 	}
1366 	bzero(ptr, sizeof(struct ata_params));
1367 
1368 	cam_fill_ataio(&ccb->ataio,
1369 		      retry_count,
1370 		      NULL,
1371 		      /*flags*/CAM_DIR_IN,
1372 		      MSG_SIMPLE_Q_TAG,
1373 		      /*data_ptr*/(u_int8_t *)ptr,
1374 		      /*dxfer_len*/sizeof(struct ata_params),
1375 		      timeout ? timeout : 30 * 1000);
1376 	if (cgd.protocol == PROTO_ATA)
1377 		ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1378 	else
1379 		ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1380 
1381 	/* Disable freezing the device queue */
1382 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1383 
1384 	if (arglist & CAM_ARG_ERR_RECOVER)
1385 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1386 
1387 	if (cam_send_ccb(device, ccb) < 0) {
1388 		perror("error sending ATA identify");
1389 
1390 		if (arglist & CAM_ARG_VERBOSE) {
1391 			cam_error_print(device, ccb, CAM_ESF_ALL,
1392 					CAM_EPF_ALL, stderr);
1393 		}
1394 
1395 		free(ptr);
1396 		cam_freeccb(ccb);
1397 		return(1);
1398 	}
1399 
1400 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1401 		error = 1;
1402 
1403 		if (arglist & CAM_ARG_VERBOSE) {
1404 			cam_error_print(device, ccb, CAM_ESF_ALL,
1405 					CAM_EPF_ALL, stderr);
1406 		}
1407 	}
1408 
1409 	cam_freeccb(ccb);
1410 
1411 	if (error != 0) {
1412 		free(ptr);
1413 		return(error);
1414 	}
1415 
1416 	for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1417 		ptr[i] = le16toh(ptr[i]);
1418 	if (arglist & CAM_ARG_VERBOSE) {
1419 		fprintf(stdout, "%s%d: Raw identify data:\n",
1420 		    device->device_name, device->dev_unit_num);
1421 		for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1422 			if ((i % 8) == 0)
1423 			    fprintf(stdout, " %3d: ", i);
1424 			fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1425 			if ((i % 8) == 7)
1426 			    fprintf(stdout, "\n");
1427 		}
1428 	}
1429 	ident_buf = (struct ata_params *)ptr;
1430 	if (strncmp(ident_buf->model, "FX", 2) &&
1431 	    strncmp(ident_buf->model, "NEC", 3) &&
1432 	    strncmp(ident_buf->model, "Pioneer", 7) &&
1433 	    strncmp(ident_buf->model, "SHARP", 5)) {
1434 		ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1435 		ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1436 		ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1437 		ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1438 	}
1439 	ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1440 	ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1441 	ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1442 	ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1443 	ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1444 	ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1445 	ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1446 	ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1447 	    sizeof(ident_buf->media_serial));
1448 
1449 	fprintf(stdout, "%s%d: ", device->device_name,
1450 		device->dev_unit_num);
1451 	ata_print_ident(ident_buf);
1452 	camxferrate(device);
1453 	atacapprint(ident_buf);
1454 
1455 	free(ident_buf);
1456 
1457 	return(0);
1458 }
1459 #endif /* MINIMALISTIC */
1460 
1461 /*
1462  * Parse out a bus, or a bus, target and lun in the following
1463  * format:
1464  * bus
1465  * bus:target
1466  * bus:target:lun
1467  *
1468  * Returns the number of parsed components, or 0.
1469  */
1470 static int
1471 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1472 {
1473 	char *tmpstr;
1474 	int convs = 0;
1475 
1476 	while (isspace(*tstr) && (*tstr != '\0'))
1477 		tstr++;
1478 
1479 	tmpstr = (char *)strtok(tstr, ":");
1480 	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1481 		*bus = strtol(tmpstr, NULL, 0);
1482 		*arglst |= CAM_ARG_BUS;
1483 		convs++;
1484 		tmpstr = (char *)strtok(NULL, ":");
1485 		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1486 			*target = strtol(tmpstr, NULL, 0);
1487 			*arglst |= CAM_ARG_TARGET;
1488 			convs++;
1489 			tmpstr = (char *)strtok(NULL, ":");
1490 			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1491 				*lun = strtol(tmpstr, NULL, 0);
1492 				*arglst |= CAM_ARG_LUN;
1493 				convs++;
1494 			}
1495 		}
1496 	}
1497 
1498 	return convs;
1499 }
1500 
1501 static int
1502 dorescan_or_reset(int argc, char **argv, int rescan)
1503 {
1504 	static const char must[] =
1505 		"you must specify \"all\", a bus, or a bus:target:lun to %s";
1506 	int rv, error = 0;
1507 	int bus = -1, target = -1, lun = -1;
1508 	char *tstr;
1509 
1510 	if (argc < 3) {
1511 		warnx(must, rescan? "rescan" : "reset");
1512 		return(1);
1513 	}
1514 
1515 	tstr = argv[optind];
1516 	while (isspace(*tstr) && (*tstr != '\0'))
1517 		tstr++;
1518 	if (strncasecmp(tstr, "all", strlen("all")) == 0)
1519 		arglist |= CAM_ARG_BUS;
1520 	else {
1521 		rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1522 		if (rv != 1 && rv != 3) {
1523 			warnx(must, rescan? "rescan" : "reset");
1524 			return(1);
1525 		}
1526 	}
1527 
1528 	if ((arglist & CAM_ARG_BUS)
1529 	    && (arglist & CAM_ARG_TARGET)
1530 	    && (arglist & CAM_ARG_LUN))
1531 		error = scanlun_or_reset_dev(bus, target, lun, rescan);
1532 	else
1533 		error = rescan_or_reset_bus(bus, rescan);
1534 
1535 	return(error);
1536 }
1537 
1538 static int
1539 rescan_or_reset_bus(int bus, int rescan)
1540 {
1541 	union ccb ccb, matchccb;
1542 	int fd, retval;
1543 	int bufsize;
1544 
1545 	retval = 0;
1546 
1547 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1548 		warnx("error opening transport layer device %s", XPT_DEVICE);
1549 		warn("%s", XPT_DEVICE);
1550 		return(1);
1551 	}
1552 
1553 	if (bus != -1) {
1554 		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1555 		ccb.ccb_h.path_id = bus;
1556 		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1557 		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1558 		ccb.crcn.flags = CAM_FLAG_NONE;
1559 
1560 		/* run this at a low priority */
1561 		ccb.ccb_h.pinfo.priority = 5;
1562 
1563 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1564 			warn("CAMIOCOMMAND ioctl failed");
1565 			close(fd);
1566 			return(1);
1567 		}
1568 
1569 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1570 			fprintf(stdout, "%s of bus %d was successful\n",
1571 			    rescan ? "Re-scan" : "Reset", bus);
1572 		} else {
1573 			fprintf(stdout, "%s of bus %d returned error %#x\n",
1574 				rescan ? "Re-scan" : "Reset", bus,
1575 				ccb.ccb_h.status & CAM_STATUS_MASK);
1576 			retval = 1;
1577 		}
1578 
1579 		close(fd);
1580 		return(retval);
1581 
1582 	}
1583 
1584 
1585 	/*
1586 	 * The right way to handle this is to modify the xpt so that it can
1587 	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
1588 	 * that isn't implemented, so instead we enumerate the busses and
1589 	 * send the rescan or reset to those busses in the case where the
1590 	 * given bus is -1 (wildcard).  We don't send a rescan or reset
1591 	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1592 	 * no-op, sending a rescan to the xpt bus would result in a status of
1593 	 * CAM_REQ_INVALID.
1594 	 */
1595 	bzero(&(&matchccb.ccb_h)[1],
1596 	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1597 	matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1598 	matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
1599 	bufsize = sizeof(struct dev_match_result) * 20;
1600 	matchccb.cdm.match_buf_len = bufsize;
1601 	matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1602 	if (matchccb.cdm.matches == NULL) {
1603 		warnx("can't malloc memory for matches");
1604 		retval = 1;
1605 		goto bailout;
1606 	}
1607 	matchccb.cdm.num_matches = 0;
1608 
1609 	matchccb.cdm.num_patterns = 1;
1610 	matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1611 
1612 	matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1613 		matchccb.cdm.pattern_buf_len);
1614 	if (matchccb.cdm.patterns == NULL) {
1615 		warnx("can't malloc memory for patterns");
1616 		retval = 1;
1617 		goto bailout;
1618 	}
1619 	matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1620 	matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1621 
1622 	do {
1623 		unsigned int i;
1624 
1625 		if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1626 			warn("CAMIOCOMMAND ioctl failed");
1627 			retval = 1;
1628 			goto bailout;
1629 		}
1630 
1631 		if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1632 		 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1633 		   && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1634 			warnx("got CAM error %#x, CDM error %d\n",
1635 			      matchccb.ccb_h.status, matchccb.cdm.status);
1636 			retval = 1;
1637 			goto bailout;
1638 		}
1639 
1640 		for (i = 0; i < matchccb.cdm.num_matches; i++) {
1641 			struct bus_match_result *bus_result;
1642 
1643 			/* This shouldn't happen. */
1644 			if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1645 				continue;
1646 
1647 			bus_result = &matchccb.cdm.matches[i].result.bus_result;
1648 
1649 			/*
1650 			 * We don't want to rescan or reset the xpt bus.
1651 			 * See above.
1652 			 */
1653 			if ((int)bus_result->path_id == -1)
1654 				continue;
1655 
1656 			ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1657 						       XPT_RESET_BUS;
1658 			ccb.ccb_h.path_id = bus_result->path_id;
1659 			ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1660 			ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1661 			ccb.crcn.flags = CAM_FLAG_NONE;
1662 
1663 			/* run this at a low priority */
1664 			ccb.ccb_h.pinfo.priority = 5;
1665 
1666 			if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1667 				warn("CAMIOCOMMAND ioctl failed");
1668 				retval = 1;
1669 				goto bailout;
1670 			}
1671 
1672 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1673 				fprintf(stdout, "%s of bus %d was successful\n",
1674 					rescan? "Re-scan" : "Reset",
1675 					bus_result->path_id);
1676 			} else {
1677 				/*
1678 				 * Don't bail out just yet, maybe the other
1679 				 * rescan or reset commands will complete
1680 				 * successfully.
1681 				 */
1682 				fprintf(stderr, "%s of bus %d returned error "
1683 					"%#x\n", rescan? "Re-scan" : "Reset",
1684 					bus_result->path_id,
1685 					ccb.ccb_h.status & CAM_STATUS_MASK);
1686 				retval = 1;
1687 			}
1688 		}
1689 	} while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1690 		 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1691 
1692 bailout:
1693 
1694 	if (fd != -1)
1695 		close(fd);
1696 
1697 	if (matchccb.cdm.patterns != NULL)
1698 		free(matchccb.cdm.patterns);
1699 	if (matchccb.cdm.matches != NULL)
1700 		free(matchccb.cdm.matches);
1701 
1702 	return(retval);
1703 }
1704 
1705 static int
1706 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1707 {
1708 	union ccb ccb;
1709 	struct cam_device *device;
1710 	int fd;
1711 
1712 	device = NULL;
1713 
1714 	if (bus < 0) {
1715 		warnx("invalid bus number %d", bus);
1716 		return(1);
1717 	}
1718 
1719 	if (target < 0) {
1720 		warnx("invalid target number %d", target);
1721 		return(1);
1722 	}
1723 
1724 	if (lun < 0) {
1725 		warnx("invalid lun number %d", lun);
1726 		return(1);
1727 	}
1728 
1729 	fd = -1;
1730 
1731 	bzero(&ccb, sizeof(union ccb));
1732 
1733 	if (scan) {
1734 		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1735 			warnx("error opening transport layer device %s\n",
1736 			    XPT_DEVICE);
1737 			warn("%s", XPT_DEVICE);
1738 			return(1);
1739 		}
1740 	} else {
1741 		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1742 		if (device == NULL) {
1743 			warnx("%s", cam_errbuf);
1744 			return(1);
1745 		}
1746 	}
1747 
1748 	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1749 	ccb.ccb_h.path_id = bus;
1750 	ccb.ccb_h.target_id = target;
1751 	ccb.ccb_h.target_lun = lun;
1752 	ccb.ccb_h.timeout = 5000;
1753 	ccb.crcn.flags = CAM_FLAG_NONE;
1754 
1755 	/* run this at a low priority */
1756 	ccb.ccb_h.pinfo.priority = 5;
1757 
1758 	if (scan) {
1759 		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1760 			warn("CAMIOCOMMAND ioctl failed");
1761 			close(fd);
1762 			return(1);
1763 		}
1764 	} else {
1765 		if (cam_send_ccb(device, &ccb) < 0) {
1766 			warn("error sending XPT_RESET_DEV CCB");
1767 			cam_close_device(device);
1768 			return(1);
1769 		}
1770 	}
1771 
1772 	if (scan)
1773 		close(fd);
1774 	else
1775 		cam_close_device(device);
1776 
1777 	/*
1778 	 * An error code of CAM_BDR_SENT is normal for a BDR request.
1779 	 */
1780 	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1781 	 || ((!scan)
1782 	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1783 		fprintf(stdout, "%s of %d:%d:%d was successful\n",
1784 		    scan? "Re-scan" : "Reset", bus, target, lun);
1785 		return(0);
1786 	} else {
1787 		fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1788 		    scan? "Re-scan" : "Reset", bus, target, lun,
1789 		    ccb.ccb_h.status & CAM_STATUS_MASK);
1790 		return(1);
1791 	}
1792 }
1793 
1794 #ifndef MINIMALISTIC
1795 static int
1796 readdefects(struct cam_device *device, int argc, char **argv,
1797 	    char *combinedopt, int retry_count, int timeout)
1798 {
1799 	union ccb *ccb = NULL;
1800 	struct scsi_read_defect_data_10 *rdd_cdb;
1801 	u_int8_t *defect_list = NULL;
1802 	u_int32_t max_dlist_length = SRDD10_MAX_LENGTH, dlist_length = 0;
1803 	u_int32_t returned_length = 0;
1804 	u_int32_t num_returned = 0;
1805 	u_int8_t returned_format;
1806 	unsigned int i;
1807 	int c, error = 0;
1808 	int lists_specified;
1809 	int get_length = 1;
1810 
1811 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1812 		switch(c){
1813 		case 'f':
1814 		{
1815 			char *tstr;
1816 			tstr = optarg;
1817 			while (isspace(*tstr) && (*tstr != '\0'))
1818 				tstr++;
1819 			if (strcmp(tstr, "block") == 0)
1820 				arglist |= CAM_ARG_FORMAT_BLOCK;
1821 			else if (strcmp(tstr, "bfi") == 0)
1822 				arglist |= CAM_ARG_FORMAT_BFI;
1823 			else if (strcmp(tstr, "phys") == 0)
1824 				arglist |= CAM_ARG_FORMAT_PHYS;
1825 			else {
1826 				error = 1;
1827 				warnx("invalid defect format %s", tstr);
1828 				goto defect_bailout;
1829 			}
1830 			break;
1831 		}
1832 		case 'G':
1833 			arglist |= CAM_ARG_GLIST;
1834 			break;
1835 		case 'P':
1836 			arglist |= CAM_ARG_PLIST;
1837 			break;
1838 		default:
1839 			break;
1840 		}
1841 	}
1842 
1843 	ccb = cam_getccb(device);
1844 
1845 	/*
1846 	 * Eventually we should probably support the 12 byte READ DEFECT
1847 	 * DATA command.  It supports a longer parameter list, which may be
1848 	 * necessary on newer drives with lots of defects.  According to
1849 	 * the SBC-3 spec, drives are supposed to return an illegal request
1850 	 * if they have more defect data than will fit in 64K.
1851 	 */
1852 	defect_list = malloc(max_dlist_length);
1853 	if (defect_list == NULL) {
1854 		warnx("can't malloc memory for defect list");
1855 		error = 1;
1856 		goto defect_bailout;
1857 	}
1858 
1859 	/*
1860 	 * We start off asking for just the header to determine how much
1861 	 * defect data is available.  Some Hitachi drives return an error
1862 	 * if you ask for more data than the drive has.  Once we know the
1863 	 * length, we retry the command with the returned length.
1864 	 */
1865 	dlist_length = sizeof(struct scsi_read_defect_data_hdr_10);
1866 
1867 	rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1868 
1869 retry:
1870 
1871 	lists_specified = 0;
1872 
1873 	/*
1874 	 * cam_getccb() zeros the CCB header only.  So we need to zero the
1875 	 * payload portion of the ccb.
1876 	 */
1877 	bzero(&(&ccb->ccb_h)[1],
1878 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1879 
1880 	cam_fill_csio(&ccb->csio,
1881 		      /*retries*/ retry_count,
1882 		      /*cbfcnp*/ NULL,
1883 		      /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1884 					      CAM_PASS_ERR_RECOVER : 0),
1885 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
1886 		      /*data_ptr*/ defect_list,
1887 		      /*dxfer_len*/ dlist_length,
1888 		      /*sense_len*/ SSD_FULL_SIZE,
1889 		      /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1890 		      /*timeout*/ timeout ? timeout : 5000);
1891 
1892 	rdd_cdb->opcode = READ_DEFECT_DATA_10;
1893 	if (arglist & CAM_ARG_FORMAT_BLOCK)
1894 		rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1895 	else if (arglist & CAM_ARG_FORMAT_BFI)
1896 		rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1897 	else if (arglist & CAM_ARG_FORMAT_PHYS)
1898 		rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1899 	else {
1900 		error = 1;
1901 		warnx("no defect list format specified");
1902 		goto defect_bailout;
1903 	}
1904 	if (arglist & CAM_ARG_PLIST) {
1905 		rdd_cdb->format |= SRDD10_PLIST;
1906 		lists_specified++;
1907 	}
1908 
1909 	if (arglist & CAM_ARG_GLIST) {
1910 		rdd_cdb->format |= SRDD10_GLIST;
1911 		lists_specified++;
1912 	}
1913 
1914 	scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1915 
1916 	/* Disable freezing the device queue */
1917 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1918 
1919 	if (cam_send_ccb(device, ccb) < 0) {
1920 		perror("error reading defect list");
1921 
1922 		if (arglist & CAM_ARG_VERBOSE) {
1923 			cam_error_print(device, ccb, CAM_ESF_ALL,
1924 					CAM_EPF_ALL, stderr);
1925 		}
1926 
1927 		error = 1;
1928 		goto defect_bailout;
1929 	}
1930 
1931 	returned_length = scsi_2btoul(((struct
1932 		scsi_read_defect_data_hdr_10 *)defect_list)->length);
1933 
1934 	if (get_length != 0) {
1935 		get_length = 0;
1936 
1937 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1938 		     CAM_SCSI_STATUS_ERROR) {
1939 			struct scsi_sense_data *sense;
1940 			int error_code, sense_key, asc, ascq;
1941 
1942 			sense = &ccb->csio.sense_data;
1943 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
1944 			    ccb->csio.sense_resid, &error_code, &sense_key,
1945 			    &asc, &ascq, /*show_errors*/ 1);
1946 
1947 			/*
1948 			 * If the drive is reporting that it just doesn't
1949 			 * support the defect list format, go ahead and use
1950 			 * the length it reported.  Otherwise, the length
1951 			 * may not be valid, so use the maximum.
1952 			 */
1953 			if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1954 			 && (asc == 0x1c) && (ascq == 0x00)
1955 			 && (returned_length > 0)) {
1956 				dlist_length = returned_length +
1957 				    sizeof(struct scsi_read_defect_data_hdr_10);
1958 				dlist_length = min(dlist_length,
1959 						   SRDD10_MAX_LENGTH);
1960 			} else
1961 				dlist_length = max_dlist_length;
1962 		} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
1963 			    CAM_REQ_CMP){
1964 			error = 1;
1965 			warnx("Error reading defect header");
1966 			if (arglist & CAM_ARG_VERBOSE)
1967 				cam_error_print(device, ccb, CAM_ESF_ALL,
1968 						CAM_EPF_ALL, stderr);
1969 			goto defect_bailout;
1970 		} else {
1971 			dlist_length = returned_length +
1972 			    sizeof(struct scsi_read_defect_data_hdr_10);
1973 			dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
1974 		}
1975 
1976 		goto retry;
1977 	}
1978 
1979 	returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1980 			defect_list)->format;
1981 
1982 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1983 	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1984 	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1985 		struct scsi_sense_data *sense;
1986 		int error_code, sense_key, asc, ascq;
1987 
1988 		sense = &ccb->csio.sense_data;
1989 		scsi_extract_sense_len(sense, ccb->csio.sense_len -
1990 		    ccb->csio.sense_resid, &error_code, &sense_key, &asc,
1991 		    &ascq, /*show_errors*/ 1);
1992 
1993 		/*
1994 		 * According to the SCSI spec, if the disk doesn't support
1995 		 * the requested format, it will generally return a sense
1996 		 * key of RECOVERED ERROR, and an additional sense code
1997 		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1998 		 * also check to make sure that the returned length is
1999 		 * greater than 0, and then print out whatever format the
2000 		 * disk gave us.
2001 		 */
2002 		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
2003 		 && (asc == 0x1c) && (ascq == 0x00)
2004 		 && (returned_length > 0)) {
2005 			warnx("requested defect format not available");
2006 			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
2007 			case SRDD10_BLOCK_FORMAT:
2008 				warnx("Device returned block format");
2009 				break;
2010 			case SRDD10_BYTES_FROM_INDEX_FORMAT:
2011 				warnx("Device returned bytes from index"
2012 				      " format");
2013 				break;
2014 			case SRDD10_PHYSICAL_SECTOR_FORMAT:
2015 				warnx("Device returned physical sector format");
2016 				break;
2017 			default:
2018 				error = 1;
2019 				warnx("Device returned unknown defect"
2020 				     " data format %#x", returned_format);
2021 				goto defect_bailout;
2022 				break; /* NOTREACHED */
2023 			}
2024 		} else {
2025 			error = 1;
2026 			warnx("Error returned from read defect data command");
2027 			if (arglist & CAM_ARG_VERBOSE)
2028 				cam_error_print(device, ccb, CAM_ESF_ALL,
2029 						CAM_EPF_ALL, stderr);
2030 			goto defect_bailout;
2031 		}
2032 	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2033 		error = 1;
2034 		warnx("Error returned from read defect data command");
2035 		if (arglist & CAM_ARG_VERBOSE)
2036 			cam_error_print(device, ccb, CAM_ESF_ALL,
2037 					CAM_EPF_ALL, stderr);
2038 		goto defect_bailout;
2039 	}
2040 
2041 	/*
2042 	 * XXX KDM  I should probably clean up the printout format for the
2043 	 * disk defects.
2044 	 */
2045 	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
2046 		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
2047 		{
2048 			struct scsi_defect_desc_phys_sector *dlist;
2049 
2050 			dlist = (struct scsi_defect_desc_phys_sector *)
2051 				(defect_list +
2052 				sizeof(struct scsi_read_defect_data_hdr_10));
2053 
2054 			num_returned = returned_length /
2055 				sizeof(struct scsi_defect_desc_phys_sector);
2056 
2057 			fprintf(stderr, "Got %d defect", num_returned);
2058 
2059 			if ((lists_specified == 0) || (num_returned == 0)) {
2060 				fprintf(stderr, "s.\n");
2061 				break;
2062 			} else if (num_returned == 1)
2063 				fprintf(stderr, ":\n");
2064 			else
2065 				fprintf(stderr, "s:\n");
2066 
2067 			for (i = 0; i < num_returned; i++) {
2068 				fprintf(stdout, "%d:%d:%d\n",
2069 					scsi_3btoul(dlist[i].cylinder),
2070 					dlist[i].head,
2071 					scsi_4btoul(dlist[i].sector));
2072 			}
2073 			break;
2074 		}
2075 		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
2076 		{
2077 			struct scsi_defect_desc_bytes_from_index *dlist;
2078 
2079 			dlist = (struct scsi_defect_desc_bytes_from_index *)
2080 				(defect_list +
2081 				sizeof(struct scsi_read_defect_data_hdr_10));
2082 
2083 			num_returned = returned_length /
2084 			      sizeof(struct scsi_defect_desc_bytes_from_index);
2085 
2086 			fprintf(stderr, "Got %d defect", num_returned);
2087 
2088 			if ((lists_specified == 0) || (num_returned == 0)) {
2089 				fprintf(stderr, "s.\n");
2090 				break;
2091 			} else if (num_returned == 1)
2092 				fprintf(stderr, ":\n");
2093 			else
2094 				fprintf(stderr, "s:\n");
2095 
2096 			for (i = 0; i < num_returned; i++) {
2097 				fprintf(stdout, "%d:%d:%d\n",
2098 					scsi_3btoul(dlist[i].cylinder),
2099 					dlist[i].head,
2100 					scsi_4btoul(dlist[i].bytes_from_index));
2101 			}
2102 			break;
2103 		}
2104 		case SRDDH10_BLOCK_FORMAT:
2105 		{
2106 			struct scsi_defect_desc_block *dlist;
2107 
2108 			dlist = (struct scsi_defect_desc_block *)(defect_list +
2109 				sizeof(struct scsi_read_defect_data_hdr_10));
2110 
2111 			num_returned = returned_length /
2112 			      sizeof(struct scsi_defect_desc_block);
2113 
2114 			fprintf(stderr, "Got %d defect", num_returned);
2115 
2116 			if ((lists_specified == 0) || (num_returned == 0)) {
2117 				fprintf(stderr, "s.\n");
2118 				break;
2119 			} else if (num_returned == 1)
2120 				fprintf(stderr, ":\n");
2121 			else
2122 				fprintf(stderr, "s:\n");
2123 
2124 			for (i = 0; i < num_returned; i++)
2125 				fprintf(stdout, "%u\n",
2126 					scsi_4btoul(dlist[i].address));
2127 			break;
2128 		}
2129 		default:
2130 			fprintf(stderr, "Unknown defect format %d\n",
2131 				returned_format & SRDDH10_DLIST_FORMAT_MASK);
2132 			error = 1;
2133 			break;
2134 	}
2135 defect_bailout:
2136 
2137 	if (defect_list != NULL)
2138 		free(defect_list);
2139 
2140 	if (ccb != NULL)
2141 		cam_freeccb(ccb);
2142 
2143 	return(error);
2144 }
2145 #endif /* MINIMALISTIC */
2146 
2147 #if 0
2148 void
2149 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2150 {
2151 	union ccb *ccb;
2152 
2153 	ccb = cam_getccb(device);
2154 
2155 	cam_freeccb(ccb);
2156 }
2157 #endif
2158 
2159 #ifndef MINIMALISTIC
2160 void
2161 mode_sense(struct cam_device *device, int mode_page, int page_control,
2162 	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2163 {
2164 	union ccb *ccb;
2165 	int retval;
2166 
2167 	ccb = cam_getccb(device);
2168 
2169 	if (ccb == NULL)
2170 		errx(1, "mode_sense: couldn't allocate CCB");
2171 
2172 	bzero(&(&ccb->ccb_h)[1],
2173 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2174 
2175 	scsi_mode_sense(&ccb->csio,
2176 			/* retries */ retry_count,
2177 			/* cbfcnp */ NULL,
2178 			/* tag_action */ MSG_SIMPLE_Q_TAG,
2179 			/* dbd */ dbd,
2180 			/* page_code */ page_control << 6,
2181 			/* page */ mode_page,
2182 			/* param_buf */ data,
2183 			/* param_len */ datalen,
2184 			/* sense_len */ SSD_FULL_SIZE,
2185 			/* timeout */ timeout ? timeout : 5000);
2186 
2187 	if (arglist & CAM_ARG_ERR_RECOVER)
2188 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2189 
2190 	/* Disable freezing the device queue */
2191 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2192 
2193 	if (((retval = cam_send_ccb(device, ccb)) < 0)
2194 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2195 		if (arglist & CAM_ARG_VERBOSE) {
2196 			cam_error_print(device, ccb, CAM_ESF_ALL,
2197 					CAM_EPF_ALL, stderr);
2198 		}
2199 		cam_freeccb(ccb);
2200 		cam_close_device(device);
2201 		if (retval < 0)
2202 			err(1, "error sending mode sense command");
2203 		else
2204 			errx(1, "error sending mode sense command");
2205 	}
2206 
2207 	cam_freeccb(ccb);
2208 }
2209 
2210 void
2211 mode_select(struct cam_device *device, int save_pages, int retry_count,
2212 	   int timeout, u_int8_t *data, int datalen)
2213 {
2214 	union ccb *ccb;
2215 	int retval;
2216 
2217 	ccb = cam_getccb(device);
2218 
2219 	if (ccb == NULL)
2220 		errx(1, "mode_select: couldn't allocate CCB");
2221 
2222 	bzero(&(&ccb->ccb_h)[1],
2223 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2224 
2225 	scsi_mode_select(&ccb->csio,
2226 			 /* retries */ retry_count,
2227 			 /* cbfcnp */ NULL,
2228 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
2229 			 /* scsi_page_fmt */ 1,
2230 			 /* save_pages */ save_pages,
2231 			 /* param_buf */ data,
2232 			 /* param_len */ datalen,
2233 			 /* sense_len */ SSD_FULL_SIZE,
2234 			 /* timeout */ timeout ? timeout : 5000);
2235 
2236 	if (arglist & CAM_ARG_ERR_RECOVER)
2237 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2238 
2239 	/* Disable freezing the device queue */
2240 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2241 
2242 	if (((retval = cam_send_ccb(device, ccb)) < 0)
2243 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2244 		if (arglist & CAM_ARG_VERBOSE) {
2245 			cam_error_print(device, ccb, CAM_ESF_ALL,
2246 					CAM_EPF_ALL, stderr);
2247 		}
2248 		cam_freeccb(ccb);
2249 		cam_close_device(device);
2250 
2251 		if (retval < 0)
2252 			err(1, "error sending mode select command");
2253 		else
2254 			errx(1, "error sending mode select command");
2255 
2256 	}
2257 
2258 	cam_freeccb(ccb);
2259 }
2260 
2261 void
2262 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2263 	 int retry_count, int timeout)
2264 {
2265 	int c, mode_page = -1, page_control = 0;
2266 	int binary = 0, list = 0;
2267 
2268 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2269 		switch(c) {
2270 		case 'b':
2271 			binary = 1;
2272 			break;
2273 		case 'd':
2274 			arglist |= CAM_ARG_DBD;
2275 			break;
2276 		case 'e':
2277 			arglist |= CAM_ARG_MODE_EDIT;
2278 			break;
2279 		case 'l':
2280 			list = 1;
2281 			break;
2282 		case 'm':
2283 			mode_page = strtol(optarg, NULL, 0);
2284 			if (mode_page < 0)
2285 				errx(1, "invalid mode page %d", mode_page);
2286 			break;
2287 		case 'P':
2288 			page_control = strtol(optarg, NULL, 0);
2289 			if ((page_control < 0) || (page_control > 3))
2290 				errx(1, "invalid page control field %d",
2291 				     page_control);
2292 			arglist |= CAM_ARG_PAGE_CNTL;
2293 			break;
2294 		default:
2295 			break;
2296 		}
2297 	}
2298 
2299 	if (mode_page == -1 && list == 0)
2300 		errx(1, "you must specify a mode page!");
2301 
2302 	if (list) {
2303 		mode_list(device, page_control, arglist & CAM_ARG_DBD,
2304 		    retry_count, timeout);
2305 	} else {
2306 		mode_edit(device, mode_page, page_control,
2307 		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2308 		    retry_count, timeout);
2309 	}
2310 }
2311 
2312 static int
2313 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2314 	int retry_count, int timeout)
2315 {
2316 	union ccb *ccb;
2317 	u_int32_t flags = CAM_DIR_NONE;
2318 	u_int8_t *data_ptr = NULL;
2319 	u_int8_t cdb[20];
2320 	u_int8_t atacmd[12];
2321 	struct get_hook hook;
2322 	int c, data_bytes = 0;
2323 	int cdb_len = 0;
2324 	int atacmd_len = 0;
2325 	int dmacmd = 0;
2326 	int fpdmacmd = 0;
2327 	int need_res = 0;
2328 	char *datastr = NULL, *tstr, *resstr = NULL;
2329 	int error = 0;
2330 	int fd_data = 0, fd_res = 0;
2331 	int retval;
2332 
2333 	ccb = cam_getccb(device);
2334 
2335 	if (ccb == NULL) {
2336 		warnx("scsicmd: error allocating ccb");
2337 		return(1);
2338 	}
2339 
2340 	bzero(&(&ccb->ccb_h)[1],
2341 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
2342 
2343 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2344 		switch(c) {
2345 		case 'a':
2346 			tstr = optarg;
2347 			while (isspace(*tstr) && (*tstr != '\0'))
2348 				tstr++;
2349 			hook.argc = argc - optind;
2350 			hook.argv = argv + optind;
2351 			hook.got = 0;
2352 			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2353 						    iget, &hook);
2354 			/*
2355 			 * Increment optind by the number of arguments the
2356 			 * encoding routine processed.  After each call to
2357 			 * getopt(3), optind points to the argument that
2358 			 * getopt should process _next_.  In this case,
2359 			 * that means it points to the first command string
2360 			 * argument, if there is one.  Once we increment
2361 			 * this, it should point to either the next command
2362 			 * line argument, or it should be past the end of
2363 			 * the list.
2364 			 */
2365 			optind += hook.got;
2366 			break;
2367 		case 'c':
2368 			tstr = optarg;
2369 			while (isspace(*tstr) && (*tstr != '\0'))
2370 				tstr++;
2371 			hook.argc = argc - optind;
2372 			hook.argv = argv + optind;
2373 			hook.got = 0;
2374 			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2375 						    iget, &hook);
2376 			/*
2377 			 * Increment optind by the number of arguments the
2378 			 * encoding routine processed.  After each call to
2379 			 * getopt(3), optind points to the argument that
2380 			 * getopt should process _next_.  In this case,
2381 			 * that means it points to the first command string
2382 			 * argument, if there is one.  Once we increment
2383 			 * this, it should point to either the next command
2384 			 * line argument, or it should be past the end of
2385 			 * the list.
2386 			 */
2387 			optind += hook.got;
2388 			break;
2389 		case 'd':
2390 			dmacmd = 1;
2391 			break;
2392 		case 'f':
2393 			fpdmacmd = 1;
2394 			break;
2395 		case 'i':
2396 			if (arglist & CAM_ARG_CMD_OUT) {
2397 				warnx("command must either be "
2398 				      "read or write, not both");
2399 				error = 1;
2400 				goto scsicmd_bailout;
2401 			}
2402 			arglist |= CAM_ARG_CMD_IN;
2403 			flags = CAM_DIR_IN;
2404 			data_bytes = strtol(optarg, NULL, 0);
2405 			if (data_bytes <= 0) {
2406 				warnx("invalid number of input bytes %d",
2407 				      data_bytes);
2408 				error = 1;
2409 				goto scsicmd_bailout;
2410 			}
2411 			hook.argc = argc - optind;
2412 			hook.argv = argv + optind;
2413 			hook.got = 0;
2414 			optind++;
2415 			datastr = cget(&hook, NULL);
2416 			/*
2417 			 * If the user supplied "-" instead of a format, he
2418 			 * wants the data to be written to stdout.
2419 			 */
2420 			if ((datastr != NULL)
2421 			 && (datastr[0] == '-'))
2422 				fd_data = 1;
2423 
2424 			data_ptr = (u_int8_t *)malloc(data_bytes);
2425 			if (data_ptr == NULL) {
2426 				warnx("can't malloc memory for data_ptr");
2427 				error = 1;
2428 				goto scsicmd_bailout;
2429 			}
2430 			break;
2431 		case 'o':
2432 			if (arglist & CAM_ARG_CMD_IN) {
2433 				warnx("command must either be "
2434 				      "read or write, not both");
2435 				error = 1;
2436 				goto scsicmd_bailout;
2437 			}
2438 			arglist |= CAM_ARG_CMD_OUT;
2439 			flags = CAM_DIR_OUT;
2440 			data_bytes = strtol(optarg, NULL, 0);
2441 			if (data_bytes <= 0) {
2442 				warnx("invalid number of output bytes %d",
2443 				      data_bytes);
2444 				error = 1;
2445 				goto scsicmd_bailout;
2446 			}
2447 			hook.argc = argc - optind;
2448 			hook.argv = argv + optind;
2449 			hook.got = 0;
2450 			datastr = cget(&hook, NULL);
2451 			data_ptr = (u_int8_t *)malloc(data_bytes);
2452 			if (data_ptr == NULL) {
2453 				warnx("can't malloc memory for data_ptr");
2454 				error = 1;
2455 				goto scsicmd_bailout;
2456 			}
2457 			bzero(data_ptr, data_bytes);
2458 			/*
2459 			 * If the user supplied "-" instead of a format, he
2460 			 * wants the data to be read from stdin.
2461 			 */
2462 			if ((datastr != NULL)
2463 			 && (datastr[0] == '-'))
2464 				fd_data = 1;
2465 			else
2466 				buff_encode_visit(data_ptr, data_bytes, datastr,
2467 						  iget, &hook);
2468 			optind += hook.got;
2469 			break;
2470 		case 'r':
2471 			need_res = 1;
2472 			hook.argc = argc - optind;
2473 			hook.argv = argv + optind;
2474 			hook.got = 0;
2475 			resstr = cget(&hook, NULL);
2476 			if ((resstr != NULL) && (resstr[0] == '-'))
2477 				fd_res = 1;
2478 			optind += hook.got;
2479 			break;
2480 		default:
2481 			break;
2482 		}
2483 	}
2484 
2485 	/*
2486 	 * If fd_data is set, and we're writing to the device, we need to
2487 	 * read the data the user wants written from stdin.
2488 	 */
2489 	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2490 		ssize_t amt_read;
2491 		int amt_to_read = data_bytes;
2492 		u_int8_t *buf_ptr = data_ptr;
2493 
2494 		for (amt_read = 0; amt_to_read > 0;
2495 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2496 			if (amt_read == -1) {
2497 				warn("error reading data from stdin");
2498 				error = 1;
2499 				goto scsicmd_bailout;
2500 			}
2501 			amt_to_read -= amt_read;
2502 			buf_ptr += amt_read;
2503 		}
2504 	}
2505 
2506 	if (arglist & CAM_ARG_ERR_RECOVER)
2507 		flags |= CAM_PASS_ERR_RECOVER;
2508 
2509 	/* Disable freezing the device queue */
2510 	flags |= CAM_DEV_QFRZDIS;
2511 
2512 	if (cdb_len) {
2513 		/*
2514 		 * This is taken from the SCSI-3 draft spec.
2515 		 * (T10/1157D revision 0.3)
2516 		 * The top 3 bits of an opcode are the group code.
2517 		 * The next 5 bits are the command code.
2518 		 * Group 0:  six byte commands
2519 		 * Group 1:  ten byte commands
2520 		 * Group 2:  ten byte commands
2521 		 * Group 3:  reserved
2522 		 * Group 4:  sixteen byte commands
2523 		 * Group 5:  twelve byte commands
2524 		 * Group 6:  vendor specific
2525 		 * Group 7:  vendor specific
2526 		 */
2527 		switch((cdb[0] >> 5) & 0x7) {
2528 			case 0:
2529 				cdb_len = 6;
2530 				break;
2531 			case 1:
2532 			case 2:
2533 				cdb_len = 10;
2534 				break;
2535 			case 3:
2536 			case 6:
2537 			case 7:
2538 			        /* computed by buff_encode_visit */
2539 				break;
2540 			case 4:
2541 				cdb_len = 16;
2542 				break;
2543 			case 5:
2544 				cdb_len = 12;
2545 				break;
2546 		}
2547 
2548 		/*
2549 		 * We should probably use csio_build_visit or something like that
2550 		 * here, but it's easier to encode arguments as you go.  The
2551 		 * alternative would be skipping the CDB argument and then encoding
2552 		 * it here, since we've got the data buffer argument by now.
2553 		 */
2554 		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2555 
2556 		cam_fill_csio(&ccb->csio,
2557 		      /*retries*/ retry_count,
2558 		      /*cbfcnp*/ NULL,
2559 		      /*flags*/ flags,
2560 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
2561 		      /*data_ptr*/ data_ptr,
2562 		      /*dxfer_len*/ data_bytes,
2563 		      /*sense_len*/ SSD_FULL_SIZE,
2564 		      /*cdb_len*/ cdb_len,
2565 		      /*timeout*/ timeout ? timeout : 5000);
2566 	} else {
2567 		atacmd_len = 12;
2568 		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2569 		if (need_res)
2570 			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2571 		if (dmacmd)
2572 			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2573 		if (fpdmacmd)
2574 			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2575 
2576 		cam_fill_ataio(&ccb->ataio,
2577 		      /*retries*/ retry_count,
2578 		      /*cbfcnp*/ NULL,
2579 		      /*flags*/ flags,
2580 		      /*tag_action*/ 0,
2581 		      /*data_ptr*/ data_ptr,
2582 		      /*dxfer_len*/ data_bytes,
2583 		      /*timeout*/ timeout ? timeout : 5000);
2584 	}
2585 
2586 	if (((retval = cam_send_ccb(device, ccb)) < 0)
2587 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2588 		const char warnstr[] = "error sending command";
2589 
2590 		if (retval < 0)
2591 			warn(warnstr);
2592 		else
2593 			warnx(warnstr);
2594 
2595 		if (arglist & CAM_ARG_VERBOSE) {
2596 			cam_error_print(device, ccb, CAM_ESF_ALL,
2597 					CAM_EPF_ALL, stderr);
2598 		}
2599 
2600 		error = 1;
2601 		goto scsicmd_bailout;
2602 	}
2603 
2604 	if (atacmd_len && need_res) {
2605 		if (fd_res == 0) {
2606 			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2607 					  arg_put, NULL);
2608 			fprintf(stdout, "\n");
2609 		} else {
2610 			fprintf(stdout,
2611 			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2612 			    ccb->ataio.res.status,
2613 			    ccb->ataio.res.error,
2614 			    ccb->ataio.res.lba_low,
2615 			    ccb->ataio.res.lba_mid,
2616 			    ccb->ataio.res.lba_high,
2617 			    ccb->ataio.res.device,
2618 			    ccb->ataio.res.lba_low_exp,
2619 			    ccb->ataio.res.lba_mid_exp,
2620 			    ccb->ataio.res.lba_high_exp,
2621 			    ccb->ataio.res.sector_count,
2622 			    ccb->ataio.res.sector_count_exp);
2623 			fflush(stdout);
2624 		}
2625 	}
2626 
2627 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2628 	 && (arglist & CAM_ARG_CMD_IN)
2629 	 && (data_bytes > 0)) {
2630 		if (fd_data == 0) {
2631 			buff_decode_visit(data_ptr, data_bytes, datastr,
2632 					  arg_put, NULL);
2633 			fprintf(stdout, "\n");
2634 		} else {
2635 			ssize_t amt_written;
2636 			int amt_to_write = data_bytes;
2637 			u_int8_t *buf_ptr = data_ptr;
2638 
2639 			for (amt_written = 0; (amt_to_write > 0) &&
2640 			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2641 				amt_to_write -= amt_written;
2642 				buf_ptr += amt_written;
2643 			}
2644 			if (amt_written == -1) {
2645 				warn("error writing data to stdout");
2646 				error = 1;
2647 				goto scsicmd_bailout;
2648 			} else if ((amt_written == 0)
2649 				&& (amt_to_write > 0)) {
2650 				warnx("only wrote %u bytes out of %u",
2651 				      data_bytes - amt_to_write, data_bytes);
2652 			}
2653 		}
2654 	}
2655 
2656 scsicmd_bailout:
2657 
2658 	if ((data_bytes > 0) && (data_ptr != NULL))
2659 		free(data_ptr);
2660 
2661 	cam_freeccb(ccb);
2662 
2663 	return(error);
2664 }
2665 
2666 static int
2667 camdebug(int argc, char **argv, char *combinedopt)
2668 {
2669 	int c, fd;
2670 	int bus = -1, target = -1, lun = -1;
2671 	char *tstr, *tmpstr = NULL;
2672 	union ccb ccb;
2673 	int error = 0;
2674 
2675 	bzero(&ccb, sizeof(union ccb));
2676 
2677 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2678 		switch(c) {
2679 		case 'I':
2680 			arglist |= CAM_ARG_DEBUG_INFO;
2681 			ccb.cdbg.flags |= CAM_DEBUG_INFO;
2682 			break;
2683 		case 'P':
2684 			arglist |= CAM_ARG_DEBUG_PERIPH;
2685 			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2686 			break;
2687 		case 'S':
2688 			arglist |= CAM_ARG_DEBUG_SUBTRACE;
2689 			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2690 			break;
2691 		case 'T':
2692 			arglist |= CAM_ARG_DEBUG_TRACE;
2693 			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2694 			break;
2695 		case 'X':
2696 			arglist |= CAM_ARG_DEBUG_XPT;
2697 			ccb.cdbg.flags |= CAM_DEBUG_XPT;
2698 			break;
2699 		case 'c':
2700 			arglist |= CAM_ARG_DEBUG_CDB;
2701 			ccb.cdbg.flags |= CAM_DEBUG_CDB;
2702 			break;
2703 		case 'p':
2704 			arglist |= CAM_ARG_DEBUG_PROBE;
2705 			ccb.cdbg.flags |= CAM_DEBUG_PROBE;
2706 			break;
2707 		default:
2708 			break;
2709 		}
2710 	}
2711 
2712 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2713 		warnx("error opening transport layer device %s", XPT_DEVICE);
2714 		warn("%s", XPT_DEVICE);
2715 		return(1);
2716 	}
2717 	argc -= optind;
2718 	argv += optind;
2719 
2720 	if (argc <= 0) {
2721 		warnx("you must specify \"off\", \"all\" or a bus,");
2722 		warnx("bus:target, or bus:target:lun");
2723 		close(fd);
2724 		return(1);
2725 	}
2726 
2727 	tstr = *argv;
2728 
2729 	while (isspace(*tstr) && (*tstr != '\0'))
2730 		tstr++;
2731 
2732 	if (strncmp(tstr, "off", 3) == 0) {
2733 		ccb.cdbg.flags = CAM_DEBUG_NONE;
2734 		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2735 			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2736 			     CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
2737 	} else if (strncmp(tstr, "all", 3) != 0) {
2738 		tmpstr = (char *)strtok(tstr, ":");
2739 		if ((tmpstr != NULL) && (*tmpstr != '\0')){
2740 			bus = strtol(tmpstr, NULL, 0);
2741 			arglist |= CAM_ARG_BUS;
2742 			tmpstr = (char *)strtok(NULL, ":");
2743 			if ((tmpstr != NULL) && (*tmpstr != '\0')){
2744 				target = strtol(tmpstr, NULL, 0);
2745 				arglist |= CAM_ARG_TARGET;
2746 				tmpstr = (char *)strtok(NULL, ":");
2747 				if ((tmpstr != NULL) && (*tmpstr != '\0')){
2748 					lun = strtol(tmpstr, NULL, 0);
2749 					arglist |= CAM_ARG_LUN;
2750 				}
2751 			}
2752 		} else {
2753 			error = 1;
2754 			warnx("you must specify \"all\", \"off\", or a bus,");
2755 			warnx("bus:target, or bus:target:lun to debug");
2756 		}
2757 	}
2758 
2759 	if (error == 0) {
2760 
2761 		ccb.ccb_h.func_code = XPT_DEBUG;
2762 		ccb.ccb_h.path_id = bus;
2763 		ccb.ccb_h.target_id = target;
2764 		ccb.ccb_h.target_lun = lun;
2765 
2766 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2767 			warn("CAMIOCOMMAND ioctl failed");
2768 			error = 1;
2769 		}
2770 
2771 		if (error == 0) {
2772 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2773 			     CAM_FUNC_NOTAVAIL) {
2774 				warnx("CAM debugging not available");
2775 				warnx("you need to put options CAMDEBUG in"
2776 				      " your kernel config file!");
2777 				error = 1;
2778 			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2779 				    CAM_REQ_CMP) {
2780 				warnx("XPT_DEBUG CCB failed with status %#x",
2781 				      ccb.ccb_h.status);
2782 				error = 1;
2783 			} else {
2784 				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2785 					fprintf(stderr,
2786 						"Debugging turned off\n");
2787 				} else {
2788 					fprintf(stderr,
2789 						"Debugging enabled for "
2790 						"%d:%d:%d\n",
2791 						bus, target, lun);
2792 				}
2793 			}
2794 		}
2795 		close(fd);
2796 	}
2797 
2798 	return(error);
2799 }
2800 
2801 static int
2802 tagcontrol(struct cam_device *device, int argc, char **argv,
2803 	   char *combinedopt)
2804 {
2805 	int c;
2806 	union ccb *ccb;
2807 	int numtags = -1;
2808 	int retval = 0;
2809 	int quiet = 0;
2810 	char pathstr[1024];
2811 
2812 	ccb = cam_getccb(device);
2813 
2814 	if (ccb == NULL) {
2815 		warnx("tagcontrol: error allocating ccb");
2816 		return(1);
2817 	}
2818 
2819 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2820 		switch(c) {
2821 		case 'N':
2822 			numtags = strtol(optarg, NULL, 0);
2823 			if (numtags < 0) {
2824 				warnx("tag count %d is < 0", numtags);
2825 				retval = 1;
2826 				goto tagcontrol_bailout;
2827 			}
2828 			break;
2829 		case 'q':
2830 			quiet++;
2831 			break;
2832 		default:
2833 			break;
2834 		}
2835 	}
2836 
2837 	cam_path_string(device, pathstr, sizeof(pathstr));
2838 
2839 	if (numtags >= 0) {
2840 		bzero(&(&ccb->ccb_h)[1],
2841 		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2842 		ccb->ccb_h.func_code = XPT_REL_SIMQ;
2843 		ccb->ccb_h.flags = CAM_DEV_QFREEZE;
2844 		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2845 		ccb->crs.openings = numtags;
2846 
2847 
2848 		if (cam_send_ccb(device, ccb) < 0) {
2849 			perror("error sending XPT_REL_SIMQ CCB");
2850 			retval = 1;
2851 			goto tagcontrol_bailout;
2852 		}
2853 
2854 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2855 			warnx("XPT_REL_SIMQ CCB failed");
2856 			cam_error_print(device, ccb, CAM_ESF_ALL,
2857 					CAM_EPF_ALL, stderr);
2858 			retval = 1;
2859 			goto tagcontrol_bailout;
2860 		}
2861 
2862 
2863 		if (quiet == 0)
2864 			fprintf(stdout, "%stagged openings now %d\n",
2865 				pathstr, ccb->crs.openings);
2866 	}
2867 
2868 	bzero(&(&ccb->ccb_h)[1],
2869 	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2870 
2871 	ccb->ccb_h.func_code = XPT_GDEV_STATS;
2872 
2873 	if (cam_send_ccb(device, ccb) < 0) {
2874 		perror("error sending XPT_GDEV_STATS CCB");
2875 		retval = 1;
2876 		goto tagcontrol_bailout;
2877 	}
2878 
2879 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2880 		warnx("XPT_GDEV_STATS CCB failed");
2881 		cam_error_print(device, ccb, CAM_ESF_ALL,
2882 				CAM_EPF_ALL, stderr);
2883 		retval = 1;
2884 		goto tagcontrol_bailout;
2885 	}
2886 
2887 	if (arglist & CAM_ARG_VERBOSE) {
2888 		fprintf(stdout, "%s", pathstr);
2889 		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2890 		fprintf(stdout, "%s", pathstr);
2891 		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2892 		fprintf(stdout, "%s", pathstr);
2893 		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2894 		fprintf(stdout, "%s", pathstr);
2895 		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2896 		fprintf(stdout, "%s", pathstr);
2897 		fprintf(stdout, "held          %d\n", ccb->cgds.held);
2898 		fprintf(stdout, "%s", pathstr);
2899 		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2900 		fprintf(stdout, "%s", pathstr);
2901 		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2902 	} else {
2903 		if (quiet == 0) {
2904 			fprintf(stdout, "%s", pathstr);
2905 			fprintf(stdout, "device openings: ");
2906 		}
2907 		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2908 			ccb->cgds.dev_active);
2909 	}
2910 
2911 tagcontrol_bailout:
2912 
2913 	cam_freeccb(ccb);
2914 	return(retval);
2915 }
2916 
2917 static void
2918 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2919 {
2920 	char pathstr[1024];
2921 
2922 	cam_path_string(device, pathstr, sizeof(pathstr));
2923 
2924 	if (cts->transport == XPORT_SPI) {
2925 		struct ccb_trans_settings_spi *spi =
2926 		    &cts->xport_specific.spi;
2927 
2928 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2929 
2930 			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2931 				spi->sync_period);
2932 
2933 			if (spi->sync_offset != 0) {
2934 				u_int freq;
2935 
2936 				freq = scsi_calc_syncsrate(spi->sync_period);
2937 				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2938 					pathstr, freq / 1000, freq % 1000);
2939 			}
2940 		}
2941 
2942 		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2943 			fprintf(stdout, "%soffset: %d\n", pathstr,
2944 			    spi->sync_offset);
2945 		}
2946 
2947 		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2948 			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2949 				(0x01 << spi->bus_width) * 8);
2950 		}
2951 
2952 		if (spi->valid & CTS_SPI_VALID_DISC) {
2953 			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2954 				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2955 				"enabled" : "disabled");
2956 		}
2957 	}
2958 	if (cts->transport == XPORT_FC) {
2959 		struct ccb_trans_settings_fc *fc =
2960 		    &cts->xport_specific.fc;
2961 
2962 		if (fc->valid & CTS_FC_VALID_WWNN)
2963 			fprintf(stdout, "%sWWNN: 0x%llx", pathstr,
2964 			    (long long) fc->wwnn);
2965 		if (fc->valid & CTS_FC_VALID_WWPN)
2966 			fprintf(stdout, "%sWWPN: 0x%llx", pathstr,
2967 			    (long long) fc->wwpn);
2968 		if (fc->valid & CTS_FC_VALID_PORT)
2969 			fprintf(stdout, "%sPortID: 0x%x", pathstr, fc->port);
2970 		if (fc->valid & CTS_FC_VALID_SPEED)
2971 			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2972 			    pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
2973 	}
2974 	if (cts->transport == XPORT_SAS) {
2975 		struct ccb_trans_settings_sas *sas =
2976 		    &cts->xport_specific.sas;
2977 
2978 		if (sas->valid & CTS_SAS_VALID_SPEED)
2979 			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2980 			    pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
2981 	}
2982 	if (cts->transport == XPORT_ATA) {
2983 		struct ccb_trans_settings_pata *pata =
2984 		    &cts->xport_specific.ata;
2985 
2986 		if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
2987 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
2988 				ata_mode2string(pata->mode));
2989 		}
2990 		if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2991 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2992 				pata->atapi);
2993 		}
2994 		if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2995 			fprintf(stdout, "%sPIO transaction length: %d\n",
2996 				pathstr, pata->bytecount);
2997 		}
2998 	}
2999 	if (cts->transport == XPORT_SATA) {
3000 		struct ccb_trans_settings_sata *sata =
3001 		    &cts->xport_specific.sata;
3002 
3003 		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
3004 			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
3005 				sata->revision);
3006 		}
3007 		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
3008 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
3009 				ata_mode2string(sata->mode));
3010 		}
3011 		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
3012 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
3013 				sata->atapi);
3014 		}
3015 		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
3016 			fprintf(stdout, "%sPIO transaction length: %d\n",
3017 				pathstr, sata->bytecount);
3018 		}
3019 		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
3020 			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
3021 				sata->pm_present);
3022 		}
3023 		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
3024 			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
3025 				sata->tags);
3026 		}
3027 		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
3028 			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
3029 				sata->caps);
3030 		}
3031 	}
3032 	if (cts->protocol == PROTO_ATA) {
3033 		struct ccb_trans_settings_ata *ata=
3034 		    &cts->proto_specific.ata;
3035 
3036 		if (ata->valid & CTS_ATA_VALID_TQ) {
3037 			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
3038 				(ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
3039 				"enabled" : "disabled");
3040 		}
3041 	}
3042 	if (cts->protocol == PROTO_SCSI) {
3043 		struct ccb_trans_settings_scsi *scsi=
3044 		    &cts->proto_specific.scsi;
3045 
3046 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
3047 			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
3048 				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
3049 				"enabled" : "disabled");
3050 		}
3051 	}
3052 
3053 }
3054 
3055 /*
3056  * Get a path inquiry CCB for the specified device.
3057  */
3058 static int
3059 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
3060 {
3061 	union ccb *ccb;
3062 	int retval = 0;
3063 
3064 	ccb = cam_getccb(device);
3065 	if (ccb == NULL) {
3066 		warnx("get_cpi: couldn't allocate CCB");
3067 		return(1);
3068 	}
3069 	bzero(&(&ccb->ccb_h)[1],
3070 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3071 	ccb->ccb_h.func_code = XPT_PATH_INQ;
3072 	if (cam_send_ccb(device, ccb) < 0) {
3073 		warn("get_cpi: error sending Path Inquiry CCB");
3074 		if (arglist & CAM_ARG_VERBOSE)
3075 			cam_error_print(device, ccb, CAM_ESF_ALL,
3076 					CAM_EPF_ALL, stderr);
3077 		retval = 1;
3078 		goto get_cpi_bailout;
3079 	}
3080 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3081 		if (arglist & CAM_ARG_VERBOSE)
3082 			cam_error_print(device, ccb, CAM_ESF_ALL,
3083 					CAM_EPF_ALL, stderr);
3084 		retval = 1;
3085 		goto get_cpi_bailout;
3086 	}
3087 	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
3088 
3089 get_cpi_bailout:
3090 	cam_freeccb(ccb);
3091 	return(retval);
3092 }
3093 
3094 /*
3095  * Get a get device CCB for the specified device.
3096  */
3097 static int
3098 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
3099 {
3100 	union ccb *ccb;
3101 	int retval = 0;
3102 
3103 	ccb = cam_getccb(device);
3104 	if (ccb == NULL) {
3105 		warnx("get_cgd: couldn't allocate CCB");
3106 		return(1);
3107 	}
3108 	bzero(&(&ccb->ccb_h)[1],
3109 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3110 	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
3111 	if (cam_send_ccb(device, ccb) < 0) {
3112 		warn("get_cgd: error sending Path Inquiry CCB");
3113 		if (arglist & CAM_ARG_VERBOSE)
3114 			cam_error_print(device, ccb, CAM_ESF_ALL,
3115 					CAM_EPF_ALL, stderr);
3116 		retval = 1;
3117 		goto get_cgd_bailout;
3118 	}
3119 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3120 		if (arglist & CAM_ARG_VERBOSE)
3121 			cam_error_print(device, ccb, CAM_ESF_ALL,
3122 					CAM_EPF_ALL, stderr);
3123 		retval = 1;
3124 		goto get_cgd_bailout;
3125 	}
3126 	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3127 
3128 get_cgd_bailout:
3129 	cam_freeccb(ccb);
3130 	return(retval);
3131 }
3132 
3133 /* return the type of disk (really the command type) */
3134 static const char *
3135 get_disk_type(struct cam_device *device)
3136 {
3137 	struct ccb_getdev	cgd;
3138 
3139 	(void) memset(&cgd, 0x0, sizeof(cgd));
3140 	get_cgd(device, &cgd);
3141 	switch(cgd.protocol) {
3142 	case PROTO_SCSI:
3143 		return "scsi";
3144 	case PROTO_ATA:
3145 	case PROTO_ATAPI:
3146 	case PROTO_SATAPM:
3147 		return "ata";
3148 	default:
3149 		return "unknown";
3150 	}
3151 }
3152 
3153 static void
3154 cpi_print(struct ccb_pathinq *cpi)
3155 {
3156 	char adapter_str[1024];
3157 	int i;
3158 
3159 	snprintf(adapter_str, sizeof(adapter_str),
3160 		 "%s%d:", cpi->dev_name, cpi->unit_number);
3161 
3162 	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3163 		cpi->version_num);
3164 
3165 	for (i = 1; i < 0xff; i = i << 1) {
3166 		const char *str;
3167 
3168 		if ((i & cpi->hba_inquiry) == 0)
3169 			continue;
3170 
3171 		fprintf(stdout, "%s supports ", adapter_str);
3172 
3173 		switch(i) {
3174 		case PI_MDP_ABLE:
3175 			str = "MDP message";
3176 			break;
3177 		case PI_WIDE_32:
3178 			str = "32 bit wide SCSI";
3179 			break;
3180 		case PI_WIDE_16:
3181 			str = "16 bit wide SCSI";
3182 			break;
3183 		case PI_SDTR_ABLE:
3184 			str = "SDTR message";
3185 			break;
3186 		case PI_LINKED_CDB:
3187 			str = "linked CDBs";
3188 			break;
3189 		case PI_TAG_ABLE:
3190 			str = "tag queue messages";
3191 			break;
3192 		case PI_SOFT_RST:
3193 			str = "soft reset alternative";
3194 			break;
3195 		case PI_SATAPM:
3196 			str = "SATA Port Multiplier";
3197 			break;
3198 		default:
3199 			str = "unknown PI bit set";
3200 			break;
3201 		}
3202 		fprintf(stdout, "%s\n", str);
3203 	}
3204 
3205 	for (i = 1; i < 0xff; i = i << 1) {
3206 		const char *str;
3207 
3208 		if ((i & cpi->hba_misc) == 0)
3209 			continue;
3210 
3211 		fprintf(stdout, "%s ", adapter_str);
3212 
3213 		switch(i) {
3214 		case PIM_SCANHILO:
3215 			str = "bus scans from high ID to low ID";
3216 			break;
3217 		case PIM_NOREMOVE:
3218 			str = "removable devices not included in scan";
3219 			break;
3220 		case PIM_NOINITIATOR:
3221 			str = "initiator role not supported";
3222 			break;
3223 		case PIM_NOBUSRESET:
3224 			str = "user has disabled initial BUS RESET or"
3225 			      " controller is in target/mixed mode";
3226 			break;
3227 		case PIM_NO_6_BYTE:
3228 			str = "do not send 6-byte commands";
3229 			break;
3230 		case PIM_SEQSCAN:
3231 			str = "scan bus sequentially";
3232 			break;
3233 		default:
3234 			str = "unknown PIM bit set";
3235 			break;
3236 		}
3237 		fprintf(stdout, "%s\n", str);
3238 	}
3239 
3240 	for (i = 1; i < 0xff; i = i << 1) {
3241 		const char *str;
3242 
3243 		if ((i & cpi->target_sprt) == 0)
3244 			continue;
3245 
3246 		fprintf(stdout, "%s supports ", adapter_str);
3247 		switch(i) {
3248 		case PIT_PROCESSOR:
3249 			str = "target mode processor mode";
3250 			break;
3251 		case PIT_PHASE:
3252 			str = "target mode phase cog. mode";
3253 			break;
3254 		case PIT_DISCONNECT:
3255 			str = "disconnects in target mode";
3256 			break;
3257 		case PIT_TERM_IO:
3258 			str = "terminate I/O message in target mode";
3259 			break;
3260 		case PIT_GRP_6:
3261 			str = "group 6 commands in target mode";
3262 			break;
3263 		case PIT_GRP_7:
3264 			str = "group 7 commands in target mode";
3265 			break;
3266 		default:
3267 			str = "unknown PIT bit set";
3268 			break;
3269 		}
3270 
3271 		fprintf(stdout, "%s\n", str);
3272 	}
3273 	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3274 		cpi->hba_eng_cnt);
3275 	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3276 		cpi->max_target);
3277 	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3278 		cpi->max_lun);
3279 	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3280 		adapter_str, cpi->hpath_id);
3281 	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3282 		cpi->initiator_id);
3283 	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3284 	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3285 	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
3286 	    adapter_str, cpi->hba_vendor);
3287 	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
3288 	    adapter_str, cpi->hba_device);
3289 	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
3290 	    adapter_str, cpi->hba_subvendor);
3291 	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
3292 	    adapter_str, cpi->hba_subdevice);
3293 	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3294 	fprintf(stdout, "%s base transfer speed: ", adapter_str);
3295 	if (cpi->base_transfer_speed > 1000)
3296 		fprintf(stdout, "%d.%03dMB/sec\n",
3297 			cpi->base_transfer_speed / 1000,
3298 			cpi->base_transfer_speed % 1000);
3299 	else
3300 		fprintf(stdout, "%dKB/sec\n",
3301 			(cpi->base_transfer_speed % 1000) * 1000);
3302 	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
3303 	    adapter_str, cpi->maxio);
3304 }
3305 
3306 static int
3307 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3308 	      struct ccb_trans_settings *cts)
3309 {
3310 	int retval;
3311 	union ccb *ccb;
3312 
3313 	retval = 0;
3314 	ccb = cam_getccb(device);
3315 
3316 	if (ccb == NULL) {
3317 		warnx("get_print_cts: error allocating ccb");
3318 		return(1);
3319 	}
3320 
3321 	bzero(&(&ccb->ccb_h)[1],
3322 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3323 
3324 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3325 
3326 	if (user_settings == 0)
3327 		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3328 	else
3329 		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3330 
3331 	if (cam_send_ccb(device, ccb) < 0) {
3332 		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3333 		if (arglist & CAM_ARG_VERBOSE)
3334 			cam_error_print(device, ccb, CAM_ESF_ALL,
3335 					CAM_EPF_ALL, stderr);
3336 		retval = 1;
3337 		goto get_print_cts_bailout;
3338 	}
3339 
3340 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3341 		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3342 		if (arglist & CAM_ARG_VERBOSE)
3343 			cam_error_print(device, ccb, CAM_ESF_ALL,
3344 					CAM_EPF_ALL, stderr);
3345 		retval = 1;
3346 		goto get_print_cts_bailout;
3347 	}
3348 
3349 	if (quiet == 0)
3350 		cts_print(device, &ccb->cts);
3351 
3352 	if (cts != NULL)
3353 		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3354 
3355 get_print_cts_bailout:
3356 
3357 	cam_freeccb(ccb);
3358 
3359 	return(retval);
3360 }
3361 
3362 static int
3363 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3364 	    int argc, char **argv, char *combinedopt)
3365 {
3366 	int c;
3367 	union ccb *ccb;
3368 	int user_settings = 0;
3369 	int retval = 0;
3370 	int disc_enable = -1, tag_enable = -1;
3371 	int mode = -1;
3372 	int offset = -1;
3373 	double syncrate = -1;
3374 	int bus_width = -1;
3375 	int quiet = 0;
3376 	int change_settings = 0, send_tur = 0;
3377 	struct ccb_pathinq cpi;
3378 
3379 	ccb = cam_getccb(device);
3380 	if (ccb == NULL) {
3381 		warnx("ratecontrol: error allocating ccb");
3382 		return(1);
3383 	}
3384 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3385 		switch(c){
3386 		case 'a':
3387 			send_tur = 1;
3388 			break;
3389 		case 'c':
3390 			user_settings = 0;
3391 			break;
3392 		case 'D':
3393 			if (strncasecmp(optarg, "enable", 6) == 0)
3394 				disc_enable = 1;
3395 			else if (strncasecmp(optarg, "disable", 7) == 0)
3396 				disc_enable = 0;
3397 			else {
3398 				warnx("-D argument \"%s\" is unknown", optarg);
3399 				retval = 1;
3400 				goto ratecontrol_bailout;
3401 			}
3402 			change_settings = 1;
3403 			break;
3404 		case 'M':
3405 			mode = ata_string2mode(optarg);
3406 			if (mode < 0) {
3407 				warnx("unknown mode '%s'", optarg);
3408 				retval = 1;
3409 				goto ratecontrol_bailout;
3410 			}
3411 			change_settings = 1;
3412 			break;
3413 		case 'O':
3414 			offset = strtol(optarg, NULL, 0);
3415 			if (offset < 0) {
3416 				warnx("offset value %d is < 0", offset);
3417 				retval = 1;
3418 				goto ratecontrol_bailout;
3419 			}
3420 			change_settings = 1;
3421 			break;
3422 		case 'q':
3423 			quiet++;
3424 			break;
3425 		case 'R':
3426 			syncrate = atof(optarg);
3427 			if (syncrate < 0) {
3428 				warnx("sync rate %f is < 0", syncrate);
3429 				retval = 1;
3430 				goto ratecontrol_bailout;
3431 			}
3432 			change_settings = 1;
3433 			break;
3434 		case 'T':
3435 			if (strncasecmp(optarg, "enable", 6) == 0)
3436 				tag_enable = 1;
3437 			else if (strncasecmp(optarg, "disable", 7) == 0)
3438 				tag_enable = 0;
3439 			else {
3440 				warnx("-T argument \"%s\" is unknown", optarg);
3441 				retval = 1;
3442 				goto ratecontrol_bailout;
3443 			}
3444 			change_settings = 1;
3445 			break;
3446 		case 'U':
3447 			user_settings = 1;
3448 			break;
3449 		case 'W':
3450 			bus_width = strtol(optarg, NULL, 0);
3451 			if (bus_width < 0) {
3452 				warnx("bus width %d is < 0", bus_width);
3453 				retval = 1;
3454 				goto ratecontrol_bailout;
3455 			}
3456 			change_settings = 1;
3457 			break;
3458 		default:
3459 			break;
3460 		}
3461 	}
3462 	bzero(&(&ccb->ccb_h)[1],
3463 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3464 	/*
3465 	 * Grab path inquiry information, so we can determine whether
3466 	 * or not the initiator is capable of the things that the user
3467 	 * requests.
3468 	 */
3469 	ccb->ccb_h.func_code = XPT_PATH_INQ;
3470 	if (cam_send_ccb(device, ccb) < 0) {
3471 		perror("error sending XPT_PATH_INQ CCB");
3472 		if (arglist & CAM_ARG_VERBOSE) {
3473 			cam_error_print(device, ccb, CAM_ESF_ALL,
3474 					CAM_EPF_ALL, stderr);
3475 		}
3476 		retval = 1;
3477 		goto ratecontrol_bailout;
3478 	}
3479 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3480 		warnx("XPT_PATH_INQ CCB failed");
3481 		if (arglist & CAM_ARG_VERBOSE) {
3482 			cam_error_print(device, ccb, CAM_ESF_ALL,
3483 					CAM_EPF_ALL, stderr);
3484 		}
3485 		retval = 1;
3486 		goto ratecontrol_bailout;
3487 	}
3488 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3489 	bzero(&(&ccb->ccb_h)[1],
3490 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3491 	if (quiet == 0) {
3492 		fprintf(stdout, "%s parameters:\n",
3493 		    user_settings ? "User" : "Current");
3494 	}
3495 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3496 	if (retval != 0)
3497 		goto ratecontrol_bailout;
3498 
3499 	if (arglist & CAM_ARG_VERBOSE)
3500 		cpi_print(&cpi);
3501 
3502 	if (change_settings) {
3503 		int didsettings = 0;
3504 		struct ccb_trans_settings_spi *spi = NULL;
3505 		struct ccb_trans_settings_pata *pata = NULL;
3506 		struct ccb_trans_settings_sata *sata = NULL;
3507 		struct ccb_trans_settings_ata *ata = NULL;
3508 		struct ccb_trans_settings_scsi *scsi = NULL;
3509 
3510 		if (ccb->cts.transport == XPORT_SPI)
3511 			spi = &ccb->cts.xport_specific.spi;
3512 		if (ccb->cts.transport == XPORT_ATA)
3513 			pata = &ccb->cts.xport_specific.ata;
3514 		if (ccb->cts.transport == XPORT_SATA)
3515 			sata = &ccb->cts.xport_specific.sata;
3516 		if (ccb->cts.protocol == PROTO_ATA)
3517 			ata = &ccb->cts.proto_specific.ata;
3518 		if (ccb->cts.protocol == PROTO_SCSI)
3519 			scsi = &ccb->cts.proto_specific.scsi;
3520 		ccb->cts.xport_specific.valid = 0;
3521 		ccb->cts.proto_specific.valid = 0;
3522 		if (spi && disc_enable != -1) {
3523 			spi->valid |= CTS_SPI_VALID_DISC;
3524 			if (disc_enable == 0)
3525 				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3526 			else
3527 				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3528 			didsettings++;
3529 		}
3530 		if (tag_enable != -1) {
3531 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3532 				warnx("HBA does not support tagged queueing, "
3533 				      "so you cannot modify tag settings");
3534 				retval = 1;
3535 				goto ratecontrol_bailout;
3536 			}
3537 			if (ata) {
3538 				ata->valid |= CTS_SCSI_VALID_TQ;
3539 				if (tag_enable == 0)
3540 					ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
3541 				else
3542 					ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
3543 				didsettings++;
3544 			} else if (scsi) {
3545 				scsi->valid |= CTS_SCSI_VALID_TQ;
3546 				if (tag_enable == 0)
3547 					scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3548 				else
3549 					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3550 				didsettings++;
3551 			}
3552 		}
3553 		if (spi && offset != -1) {
3554 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3555 				warnx("HBA is not capable of changing offset");
3556 				retval = 1;
3557 				goto ratecontrol_bailout;
3558 			}
3559 			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3560 			spi->sync_offset = offset;
3561 			didsettings++;
3562 		}
3563 		if (spi && syncrate != -1) {
3564 			int prelim_sync_period;
3565 
3566 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3567 				warnx("HBA is not capable of changing "
3568 				      "transfer rates");
3569 				retval = 1;
3570 				goto ratecontrol_bailout;
3571 			}
3572 			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3573 			/*
3574 			 * The sync rate the user gives us is in MHz.
3575 			 * We need to translate it into KHz for this
3576 			 * calculation.
3577 			 */
3578 			syncrate *= 1000;
3579 			/*
3580 			 * Next, we calculate a "preliminary" sync period
3581 			 * in tenths of a nanosecond.
3582 			 */
3583 			if (syncrate == 0)
3584 				prelim_sync_period = 0;
3585 			else
3586 				prelim_sync_period = 10000000 / syncrate;
3587 			spi->sync_period =
3588 				scsi_calc_syncparam(prelim_sync_period);
3589 			didsettings++;
3590 		}
3591 		if (sata && syncrate != -1) {
3592 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3593 				warnx("HBA is not capable of changing "
3594 				      "transfer rates");
3595 				retval = 1;
3596 				goto ratecontrol_bailout;
3597 			}
3598 			if  (!user_settings) {
3599 				warnx("You can modify only user rate "
3600 				    "settings for SATA");
3601 				retval = 1;
3602 				goto ratecontrol_bailout;
3603 			}
3604 			sata->revision = ata_speed2revision(syncrate * 100);
3605 			if (sata->revision < 0) {
3606 				warnx("Invalid rate %f", syncrate);
3607 				retval = 1;
3608 				goto ratecontrol_bailout;
3609 			}
3610 			sata->valid |= CTS_SATA_VALID_REVISION;
3611 			didsettings++;
3612 		}
3613 		if ((pata || sata) && mode != -1) {
3614 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3615 				warnx("HBA is not capable of changing "
3616 				      "transfer rates");
3617 				retval = 1;
3618 				goto ratecontrol_bailout;
3619 			}
3620 			if  (!user_settings) {
3621 				warnx("You can modify only user mode "
3622 				    "settings for ATA/SATA");
3623 				retval = 1;
3624 				goto ratecontrol_bailout;
3625 			}
3626 			if (pata) {
3627 				pata->mode = mode;
3628 				pata->valid |= CTS_ATA_VALID_MODE;
3629 			} else {
3630 				sata->mode = mode;
3631 				sata->valid |= CTS_SATA_VALID_MODE;
3632 			}
3633 			didsettings++;
3634 		}
3635 		/*
3636 		 * The bus_width argument goes like this:
3637 		 * 0 == 8 bit
3638 		 * 1 == 16 bit
3639 		 * 2 == 32 bit
3640 		 * Therefore, if you shift the number of bits given on the
3641 		 * command line right by 4, you should get the correct
3642 		 * number.
3643 		 */
3644 		if (spi && bus_width != -1) {
3645 			/*
3646 			 * We might as well validate things here with a
3647 			 * decipherable error message, rather than what
3648 			 * will probably be an indecipherable error message
3649 			 * by the time it gets back to us.
3650 			 */
3651 			if ((bus_width == 16)
3652 			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3653 				warnx("HBA does not support 16 bit bus width");
3654 				retval = 1;
3655 				goto ratecontrol_bailout;
3656 			} else if ((bus_width == 32)
3657 				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3658 				warnx("HBA does not support 32 bit bus width");
3659 				retval = 1;
3660 				goto ratecontrol_bailout;
3661 			} else if ((bus_width != 8)
3662 				&& (bus_width != 16)
3663 				&& (bus_width != 32)) {
3664 				warnx("Invalid bus width %d", bus_width);
3665 				retval = 1;
3666 				goto ratecontrol_bailout;
3667 			}
3668 			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3669 			spi->bus_width = bus_width >> 4;
3670 			didsettings++;
3671 		}
3672 		if  (didsettings == 0) {
3673 			goto ratecontrol_bailout;
3674 		}
3675 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3676 		if (cam_send_ccb(device, ccb) < 0) {
3677 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3678 			if (arglist & CAM_ARG_VERBOSE) {
3679 				cam_error_print(device, ccb, CAM_ESF_ALL,
3680 						CAM_EPF_ALL, stderr);
3681 			}
3682 			retval = 1;
3683 			goto ratecontrol_bailout;
3684 		}
3685 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3686 			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3687 			if (arglist & CAM_ARG_VERBOSE) {
3688 				cam_error_print(device, ccb, CAM_ESF_ALL,
3689 						CAM_EPF_ALL, stderr);
3690 			}
3691 			retval = 1;
3692 			goto ratecontrol_bailout;
3693 		}
3694 	}
3695 	if (send_tur) {
3696 		retval = testunitready(device, retry_count, timeout,
3697 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3698 		/*
3699 		 * If the TUR didn't succeed, just bail.
3700 		 */
3701 		if (retval != 0) {
3702 			if (quiet == 0)
3703 				fprintf(stderr, "Test Unit Ready failed\n");
3704 			goto ratecontrol_bailout;
3705 		}
3706 	}
3707 	if ((change_settings || send_tur) && !quiet &&
3708 	    (ccb->cts.transport == XPORT_ATA ||
3709 	     ccb->cts.transport == XPORT_SATA || send_tur)) {
3710 		fprintf(stdout, "New parameters:\n");
3711 		retval = get_print_cts(device, user_settings, 0, NULL);
3712 	}
3713 
3714 ratecontrol_bailout:
3715 	cam_freeccb(ccb);
3716 	return(retval);
3717 }
3718 
3719 static int
3720 scsiformat(struct cam_device *device, int argc, char **argv,
3721 	   char *combinedopt, int retry_count, int timeout)
3722 {
3723 	union ccb *ccb;
3724 	int c;
3725 	int ycount = 0, quiet = 0;
3726 	int error = 0, retval = 0;
3727 	int use_timeout = 10800 * 1000;
3728 	int immediate = 1;
3729 	struct format_defect_list_header fh;
3730 	u_int8_t *data_ptr = NULL;
3731 	u_int32_t dxfer_len = 0;
3732 	u_int8_t byte2 = 0;
3733 	int num_warnings = 0;
3734 	int reportonly = 0;
3735 
3736 	ccb = cam_getccb(device);
3737 
3738 	if (ccb == NULL) {
3739 		warnx("scsiformat: error allocating ccb");
3740 		return(1);
3741 	}
3742 
3743 	bzero(&(&ccb->ccb_h)[1],
3744 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3745 
3746 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3747 		switch(c) {
3748 		case 'q':
3749 			quiet++;
3750 			break;
3751 		case 'r':
3752 			reportonly = 1;
3753 			break;
3754 		case 'w':
3755 			immediate = 0;
3756 			break;
3757 		case 'y':
3758 			ycount++;
3759 			break;
3760 		}
3761 	}
3762 
3763 	if (reportonly)
3764 		goto doreport;
3765 
3766 	if (quiet == 0) {
3767 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3768 			"following device:\n");
3769 
3770 		error = scsidoinquiry(device, argc, argv, combinedopt,
3771 				      retry_count, timeout);
3772 
3773 		if (error != 0) {
3774 			warnx("scsiformat: error sending inquiry");
3775 			goto scsiformat_bailout;
3776 		}
3777 	}
3778 
3779 	if (ycount == 0) {
3780 		if (!get_confirmation()) {
3781 			error = 1;
3782 			goto scsiformat_bailout;
3783 		}
3784 	}
3785 
3786 	if (timeout != 0)
3787 		use_timeout = timeout;
3788 
3789 	if (quiet == 0) {
3790 		fprintf(stdout, "Current format timeout is %d seconds\n",
3791 			use_timeout / 1000);
3792 	}
3793 
3794 	/*
3795 	 * If the user hasn't disabled questions and didn't specify a
3796 	 * timeout on the command line, ask them if they want the current
3797 	 * timeout.
3798 	 */
3799 	if ((ycount == 0)
3800 	 && (timeout == 0)) {
3801 		char str[1024];
3802 		int new_timeout = 0;
3803 
3804 		fprintf(stdout, "Enter new timeout in seconds or press\n"
3805 			"return to keep the current timeout [%d] ",
3806 			use_timeout / 1000);
3807 
3808 		if (fgets(str, sizeof(str), stdin) != NULL) {
3809 			if (str[0] != '\0')
3810 				new_timeout = atoi(str);
3811 		}
3812 
3813 		if (new_timeout != 0) {
3814 			use_timeout = new_timeout * 1000;
3815 			fprintf(stdout, "Using new timeout value %d\n",
3816 				use_timeout / 1000);
3817 		}
3818 	}
3819 
3820 	/*
3821 	 * Keep this outside the if block below to silence any unused
3822 	 * variable warnings.
3823 	 */
3824 	bzero(&fh, sizeof(fh));
3825 
3826 	/*
3827 	 * If we're in immediate mode, we've got to include the format
3828 	 * header
3829 	 */
3830 	if (immediate != 0) {
3831 		fh.byte2 = FU_DLH_IMMED;
3832 		data_ptr = (u_int8_t *)&fh;
3833 		dxfer_len = sizeof(fh);
3834 		byte2 = FU_FMT_DATA;
3835 	} else if (quiet == 0) {
3836 		fprintf(stdout, "Formatting...");
3837 		fflush(stdout);
3838 	}
3839 
3840 	scsi_format_unit(&ccb->csio,
3841 			 /* retries */ retry_count,
3842 			 /* cbfcnp */ NULL,
3843 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
3844 			 /* byte2 */ byte2,
3845 			 /* ileave */ 0,
3846 			 /* data_ptr */ data_ptr,
3847 			 /* dxfer_len */ dxfer_len,
3848 			 /* sense_len */ SSD_FULL_SIZE,
3849 			 /* timeout */ use_timeout);
3850 
3851 	/* Disable freezing the device queue */
3852 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3853 
3854 	if (arglist & CAM_ARG_ERR_RECOVER)
3855 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3856 
3857 	if (((retval = cam_send_ccb(device, ccb)) < 0)
3858 	 || ((immediate == 0)
3859 	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3860 		const char errstr[] = "error sending format command";
3861 
3862 		if (retval < 0)
3863 			warn(errstr);
3864 		else
3865 			warnx(errstr);
3866 
3867 		if (arglist & CAM_ARG_VERBOSE) {
3868 			cam_error_print(device, ccb, CAM_ESF_ALL,
3869 					CAM_EPF_ALL, stderr);
3870 		}
3871 		error = 1;
3872 		goto scsiformat_bailout;
3873 	}
3874 
3875 	/*
3876 	 * If we ran in non-immediate mode, we already checked for errors
3877 	 * above and printed out any necessary information.  If we're in
3878 	 * immediate mode, we need to loop through and get status
3879 	 * information periodically.
3880 	 */
3881 	if (immediate == 0) {
3882 		if (quiet == 0) {
3883 			fprintf(stdout, "Format Complete\n");
3884 		}
3885 		goto scsiformat_bailout;
3886 	}
3887 
3888 doreport:
3889 	do {
3890 		cam_status status;
3891 
3892 		bzero(&(&ccb->ccb_h)[1],
3893 		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3894 
3895 		/*
3896 		 * There's really no need to do error recovery or
3897 		 * retries here, since we're just going to sit in a
3898 		 * loop and wait for the device to finish formatting.
3899 		 */
3900 		scsi_test_unit_ready(&ccb->csio,
3901 				     /* retries */ 0,
3902 				     /* cbfcnp */ NULL,
3903 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
3904 				     /* sense_len */ SSD_FULL_SIZE,
3905 				     /* timeout */ 5000);
3906 
3907 		/* Disable freezing the device queue */
3908 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3909 
3910 		retval = cam_send_ccb(device, ccb);
3911 
3912 		/*
3913 		 * If we get an error from the ioctl, bail out.  SCSI
3914 		 * errors are expected.
3915 		 */
3916 		if (retval < 0) {
3917 			warn("error sending CAMIOCOMMAND ioctl");
3918 			if (arglist & CAM_ARG_VERBOSE) {
3919 				cam_error_print(device, ccb, CAM_ESF_ALL,
3920 						CAM_EPF_ALL, stderr);
3921 			}
3922 			error = 1;
3923 			goto scsiformat_bailout;
3924 		}
3925 
3926 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
3927 
3928 		if ((status != CAM_REQ_CMP)
3929 		 && (status == CAM_SCSI_STATUS_ERROR)
3930 		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3931 			struct scsi_sense_data *sense;
3932 			int error_code, sense_key, asc, ascq;
3933 
3934 			sense = &ccb->csio.sense_data;
3935 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
3936 			    ccb->csio.sense_resid, &error_code, &sense_key,
3937 			    &asc, &ascq, /*show_errors*/ 1);
3938 
3939 			/*
3940 			 * According to the SCSI-2 and SCSI-3 specs, a
3941 			 * drive that is in the middle of a format should
3942 			 * return NOT READY with an ASC of "logical unit
3943 			 * not ready, format in progress".  The sense key
3944 			 * specific bytes will then be a progress indicator.
3945 			 */
3946 			if ((sense_key == SSD_KEY_NOT_READY)
3947 			 && (asc == 0x04) && (ascq == 0x04)) {
3948 				uint8_t sks[3];
3949 
3950 				if ((scsi_get_sks(sense, ccb->csio.sense_len -
3951 				     ccb->csio.sense_resid, sks) == 0)
3952 				 && (quiet == 0)) {
3953 					int val;
3954 					u_int64_t percentage;
3955 
3956 					val = scsi_2btoul(&sks[1]);
3957 					percentage = 10000 * val;
3958 
3959 					fprintf(stdout,
3960 						"\rFormatting:  %ju.%02u %% "
3961 						"(%d/%d) done",
3962 						(uintmax_t)(percentage /
3963 						(0x10000 * 100)),
3964 						(unsigned)((percentage /
3965 						0x10000) % 100),
3966 						val, 0x10000);
3967 					fflush(stdout);
3968 				} else if ((quiet == 0)
3969 					&& (++num_warnings <= 1)) {
3970 					warnx("Unexpected SCSI Sense Key "
3971 					      "Specific value returned "
3972 					      "during format:");
3973 					scsi_sense_print(device, &ccb->csio,
3974 							 stderr);
3975 					warnx("Unable to print status "
3976 					      "information, but format will "
3977 					      "proceed.");
3978 					warnx("will exit when format is "
3979 					      "complete");
3980 				}
3981 				sleep(1);
3982 			} else {
3983 				warnx("Unexpected SCSI error during format");
3984 				cam_error_print(device, ccb, CAM_ESF_ALL,
3985 						CAM_EPF_ALL, stderr);
3986 				error = 1;
3987 				goto scsiformat_bailout;
3988 			}
3989 
3990 		} else if (status != CAM_REQ_CMP) {
3991 			warnx("Unexpected CAM status %#x", status);
3992 			if (arglist & CAM_ARG_VERBOSE)
3993 				cam_error_print(device, ccb, CAM_ESF_ALL,
3994 						CAM_EPF_ALL, stderr);
3995 			error = 1;
3996 			goto scsiformat_bailout;
3997 		}
3998 
3999 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
4000 
4001 	if (quiet == 0)
4002 		fprintf(stdout, "\nFormat Complete\n");
4003 
4004 scsiformat_bailout:
4005 
4006 	cam_freeccb(ccb);
4007 
4008 	return(error);
4009 }
4010 
4011 static int
4012 scsireportluns(struct cam_device *device, int argc, char **argv,
4013 	       char *combinedopt, int retry_count, int timeout)
4014 {
4015 	union ccb *ccb;
4016 	int c, countonly, lunsonly;
4017 	struct scsi_report_luns_data *lundata;
4018 	int alloc_len;
4019 	uint8_t report_type;
4020 	uint32_t list_len, i, j;
4021 	int retval;
4022 
4023 	retval = 0;
4024 	lundata = NULL;
4025 	report_type = RPL_REPORT_DEFAULT;
4026 	ccb = cam_getccb(device);
4027 
4028 	if (ccb == NULL) {
4029 		warnx("%s: error allocating ccb", __func__);
4030 		return (1);
4031 	}
4032 
4033 	bzero(&(&ccb->ccb_h)[1],
4034 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4035 
4036 	countonly = 0;
4037 	lunsonly = 0;
4038 
4039 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4040 		switch (c) {
4041 		case 'c':
4042 			countonly++;
4043 			break;
4044 		case 'l':
4045 			lunsonly++;
4046 			break;
4047 		case 'r':
4048 			if (strcasecmp(optarg, "default") == 0)
4049 				report_type = RPL_REPORT_DEFAULT;
4050 			else if (strcasecmp(optarg, "wellknown") == 0)
4051 				report_type = RPL_REPORT_WELLKNOWN;
4052 			else if (strcasecmp(optarg, "all") == 0)
4053 				report_type = RPL_REPORT_ALL;
4054 			else {
4055 				warnx("%s: invalid report type \"%s\"",
4056 				      __func__, optarg);
4057 				retval = 1;
4058 				goto bailout;
4059 			}
4060 			break;
4061 		default:
4062 			break;
4063 		}
4064 	}
4065 
4066 	if ((countonly != 0)
4067 	 && (lunsonly != 0)) {
4068 		warnx("%s: you can only specify one of -c or -l", __func__);
4069 		retval = 1;
4070 		goto bailout;
4071 	}
4072 	/*
4073 	 * According to SPC-4, the allocation length must be at least 16
4074 	 * bytes -- enough for the header and one LUN.
4075 	 */
4076 	alloc_len = sizeof(*lundata) + 8;
4077 
4078 retry:
4079 
4080 	lundata = malloc(alloc_len);
4081 
4082 	if (lundata == NULL) {
4083 		warn("%s: error mallocing %d bytes", __func__, alloc_len);
4084 		retval = 1;
4085 		goto bailout;
4086 	}
4087 
4088 	scsi_report_luns(&ccb->csio,
4089 			 /*retries*/ retry_count,
4090 			 /*cbfcnp*/ NULL,
4091 			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4092 			 /*select_report*/ report_type,
4093 			 /*rpl_buf*/ lundata,
4094 			 /*alloc_len*/ alloc_len,
4095 			 /*sense_len*/ SSD_FULL_SIZE,
4096 			 /*timeout*/ timeout ? timeout : 5000);
4097 
4098 	/* Disable freezing the device queue */
4099 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4100 
4101 	if (arglist & CAM_ARG_ERR_RECOVER)
4102 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4103 
4104 	if (cam_send_ccb(device, ccb) < 0) {
4105 		warn("error sending REPORT LUNS command");
4106 
4107 		if (arglist & CAM_ARG_VERBOSE)
4108 			cam_error_print(device, ccb, CAM_ESF_ALL,
4109 					CAM_EPF_ALL, stderr);
4110 
4111 		retval = 1;
4112 		goto bailout;
4113 	}
4114 
4115 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4116 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4117 		retval = 1;
4118 		goto bailout;
4119 	}
4120 
4121 
4122 	list_len = scsi_4btoul(lundata->length);
4123 
4124 	/*
4125 	 * If we need to list the LUNs, and our allocation
4126 	 * length was too short, reallocate and retry.
4127 	 */
4128 	if ((countonly == 0)
4129 	 && (list_len > (alloc_len - sizeof(*lundata)))) {
4130 		alloc_len = list_len + sizeof(*lundata);
4131 		free(lundata);
4132 		goto retry;
4133 	}
4134 
4135 	if (lunsonly == 0)
4136 		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
4137 			((list_len / 8) > 1) ? "s" : "");
4138 
4139 	if (countonly != 0)
4140 		goto bailout;
4141 
4142 	for (i = 0; i < (list_len / 8); i++) {
4143 		int no_more;
4144 
4145 		no_more = 0;
4146 		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4147 			if (j != 0)
4148 				fprintf(stdout, ",");
4149 			switch (lundata->luns[i].lundata[j] &
4150 				RPL_LUNDATA_ATYP_MASK) {
4151 			case RPL_LUNDATA_ATYP_PERIPH:
4152 				if ((lundata->luns[i].lundata[j] &
4153 				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4154 					fprintf(stdout, "%d:",
4155 						lundata->luns[i].lundata[j] &
4156 						RPL_LUNDATA_PERIPH_BUS_MASK);
4157 				else if ((j == 0)
4158 				      && ((lundata->luns[i].lundata[j+2] &
4159 					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4160 					no_more = 1;
4161 
4162 				fprintf(stdout, "%d",
4163 					lundata->luns[i].lundata[j+1]);
4164 				break;
4165 			case RPL_LUNDATA_ATYP_FLAT: {
4166 				uint8_t tmplun[2];
4167 				tmplun[0] = lundata->luns[i].lundata[j] &
4168 					RPL_LUNDATA_FLAT_LUN_MASK;
4169 				tmplun[1] = lundata->luns[i].lundata[j+1];
4170 
4171 				fprintf(stdout, "%d", scsi_2btoul(tmplun));
4172 				no_more = 1;
4173 				break;
4174 			}
4175 			case RPL_LUNDATA_ATYP_LUN:
4176 				fprintf(stdout, "%d:%d:%d",
4177 					(lundata->luns[i].lundata[j+1] &
4178 					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4179 					lundata->luns[i].lundata[j] &
4180 					RPL_LUNDATA_LUN_TARG_MASK,
4181 					lundata->luns[i].lundata[j+1] &
4182 					RPL_LUNDATA_LUN_LUN_MASK);
4183 				break;
4184 			case RPL_LUNDATA_ATYP_EXTLUN: {
4185 				int field_len_code, eam_code;
4186 
4187 				eam_code = lundata->luns[i].lundata[j] &
4188 					RPL_LUNDATA_EXT_EAM_MASK;
4189 				field_len_code = (lundata->luns[i].lundata[j] &
4190 					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4191 
4192 				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4193 				 && (field_len_code == 0x00)) {
4194 					fprintf(stdout, "%d",
4195 						lundata->luns[i].lundata[j+1]);
4196 				} else if ((eam_code ==
4197 					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4198 					&& (field_len_code == 0x03)) {
4199 					uint8_t tmp_lun[8];
4200 
4201 					/*
4202 					 * This format takes up all 8 bytes.
4203 					 * If we aren't starting at offset 0,
4204 					 * that's a bug.
4205 					 */
4206 					if (j != 0) {
4207 						fprintf(stdout, "Invalid "
4208 							"offset %d for "
4209 							"Extended LUN not "
4210 							"specified format", j);
4211 						no_more = 1;
4212 						break;
4213 					}
4214 					bzero(tmp_lun, sizeof(tmp_lun));
4215 					bcopy(&lundata->luns[i].lundata[j+1],
4216 					      &tmp_lun[1], sizeof(tmp_lun) - 1);
4217 					fprintf(stdout, "%#jx",
4218 					       (intmax_t)scsi_8btou64(tmp_lun));
4219 					no_more = 1;
4220 				} else {
4221 					fprintf(stderr, "Unknown Extended LUN"
4222 						"Address method %#x, length "
4223 						"code %#x", eam_code,
4224 						field_len_code);
4225 					no_more = 1;
4226 				}
4227 				break;
4228 			}
4229 			default:
4230 				fprintf(stderr, "Unknown LUN address method "
4231 					"%#x\n", lundata->luns[i].lundata[0] &
4232 					RPL_LUNDATA_ATYP_MASK);
4233 				break;
4234 			}
4235 			/*
4236 			 * For the flat addressing method, there are no
4237 			 * other levels after it.
4238 			 */
4239 			if (no_more != 0)
4240 				break;
4241 		}
4242 		fprintf(stdout, "\n");
4243 	}
4244 
4245 bailout:
4246 
4247 	cam_freeccb(ccb);
4248 
4249 	free(lundata);
4250 
4251 	return (retval);
4252 }
4253 
4254 static int
4255 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4256 		 char *combinedopt, int retry_count, int timeout)
4257 {
4258 	union ccb *ccb;
4259 	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4260 	struct scsi_read_capacity_data rcap;
4261 	struct scsi_read_capacity_data_long rcaplong;
4262 	uint64_t maxsector;
4263 	uint32_t block_len;
4264 	int retval;
4265 	int c;
4266 
4267 	blocksizeonly = 0;
4268 	humanize = 0;
4269 	numblocks = 0;
4270 	quiet = 0;
4271 	sizeonly = 0;
4272 	baseten = 0;
4273 	retval = 0;
4274 
4275 	ccb = cam_getccb(device);
4276 
4277 	if (ccb == NULL) {
4278 		warnx("%s: error allocating ccb", __func__);
4279 		return (1);
4280 	}
4281 
4282 	bzero(&(&ccb->ccb_h)[1],
4283 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4284 
4285 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4286 		switch (c) {
4287 		case 'b':
4288 			blocksizeonly++;
4289 			break;
4290 		case 'h':
4291 			humanize++;
4292 			baseten = 0;
4293 			break;
4294 		case 'H':
4295 			humanize++;
4296 			baseten++;
4297 			break;
4298 		case 'N':
4299 			numblocks++;
4300 			break;
4301 		case 'q':
4302 			quiet++;
4303 			break;
4304 		case 's':
4305 			sizeonly++;
4306 			break;
4307 		default:
4308 			break;
4309 		}
4310 	}
4311 
4312 	if ((blocksizeonly != 0)
4313 	 && (numblocks != 0)) {
4314 		warnx("%s: you can only specify one of -b or -N", __func__);
4315 		retval = 1;
4316 		goto bailout;
4317 	}
4318 
4319 	if ((blocksizeonly != 0)
4320 	 && (sizeonly != 0)) {
4321 		warnx("%s: you can only specify one of -b or -s", __func__);
4322 		retval = 1;
4323 		goto bailout;
4324 	}
4325 
4326 	if ((humanize != 0)
4327 	 && (quiet != 0)) {
4328 		warnx("%s: you can only specify one of -h/-H or -q", __func__);
4329 		retval = 1;
4330 		goto bailout;
4331 	}
4332 
4333 	if ((humanize != 0)
4334 	 && (blocksizeonly != 0)) {
4335 		warnx("%s: you can only specify one of -h/-H or -b", __func__);
4336 		retval = 1;
4337 		goto bailout;
4338 	}
4339 
4340 	scsi_read_capacity(&ccb->csio,
4341 			   /*retries*/ retry_count,
4342 			   /*cbfcnp*/ NULL,
4343 			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
4344 			   &rcap,
4345 			   SSD_FULL_SIZE,
4346 			   /*timeout*/ timeout ? timeout : 5000);
4347 
4348 	/* Disable freezing the device queue */
4349 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4350 
4351 	if (arglist & CAM_ARG_ERR_RECOVER)
4352 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4353 
4354 	if (cam_send_ccb(device, ccb) < 0) {
4355 		warn("error sending READ CAPACITY command");
4356 
4357 		if (arglist & CAM_ARG_VERBOSE)
4358 			cam_error_print(device, ccb, CAM_ESF_ALL,
4359 					CAM_EPF_ALL, stderr);
4360 
4361 		retval = 1;
4362 		goto bailout;
4363 	}
4364 
4365 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4366 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4367 		retval = 1;
4368 		goto bailout;
4369 	}
4370 
4371 	maxsector = scsi_4btoul(rcap.addr);
4372 	block_len = scsi_4btoul(rcap.length);
4373 
4374 	/*
4375 	 * A last block of 2^32-1 means that the true capacity is over 2TB,
4376 	 * and we need to issue the long READ CAPACITY to get the real
4377 	 * capacity.  Otherwise, we're all set.
4378 	 */
4379 	if (maxsector != 0xffffffff)
4380 		goto do_print;
4381 
4382 	scsi_read_capacity_16(&ccb->csio,
4383 			      /*retries*/ retry_count,
4384 			      /*cbfcnp*/ NULL,
4385 			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
4386 			      /*lba*/ 0,
4387 			      /*reladdr*/ 0,
4388 			      /*pmi*/ 0,
4389 			      /*rcap_buf*/ (uint8_t *)&rcaplong,
4390 			      /*rcap_buf_len*/ sizeof(rcaplong),
4391 			      /*sense_len*/ SSD_FULL_SIZE,
4392 			      /*timeout*/ timeout ? timeout : 5000);
4393 
4394 	/* Disable freezing the device queue */
4395 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4396 
4397 	if (arglist & CAM_ARG_ERR_RECOVER)
4398 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4399 
4400 	if (cam_send_ccb(device, ccb) < 0) {
4401 		warn("error sending READ CAPACITY (16) command");
4402 
4403 		if (arglist & CAM_ARG_VERBOSE)
4404 			cam_error_print(device, ccb, CAM_ESF_ALL,
4405 					CAM_EPF_ALL, stderr);
4406 
4407 		retval = 1;
4408 		goto bailout;
4409 	}
4410 
4411 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4412 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4413 		retval = 1;
4414 		goto bailout;
4415 	}
4416 
4417 	maxsector = scsi_8btou64(rcaplong.addr);
4418 	block_len = scsi_4btoul(rcaplong.length);
4419 
4420 do_print:
4421 	if (blocksizeonly == 0) {
4422 		/*
4423 		 * Humanize implies !quiet, and also implies numblocks.
4424 		 */
4425 		if (humanize != 0) {
4426 			char tmpstr[6];
4427 			int64_t tmpbytes;
4428 			int ret;
4429 
4430 			tmpbytes = (maxsector + 1) * block_len;
4431 			ret = humanize_number(tmpstr, sizeof(tmpstr),
4432 					      tmpbytes, "", HN_AUTOSCALE,
4433 					      HN_B | HN_DECIMAL |
4434 					      ((baseten != 0) ?
4435 					      HN_DIVISOR_1000 : 0));
4436 			if (ret == -1) {
4437 				warnx("%s: humanize_number failed!", __func__);
4438 				retval = 1;
4439 				goto bailout;
4440 			}
4441 			fprintf(stdout, "Device Size: %s%s", tmpstr,
4442 				(sizeonly == 0) ?  ", " : "\n");
4443 		} else if (numblocks != 0) {
4444 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4445 				"Blocks: " : "", (uintmax_t)maxsector + 1,
4446 				(sizeonly == 0) ? ", " : "\n");
4447 		} else {
4448 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4449 				"Last Block: " : "", (uintmax_t)maxsector,
4450 				(sizeonly == 0) ? ", " : "\n");
4451 		}
4452 	}
4453 	if (sizeonly == 0)
4454 		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4455 			"Block Length: " : "", block_len, (quiet == 0) ?
4456 			" bytes" : "");
4457 bailout:
4458 	cam_freeccb(ccb);
4459 
4460 	return (retval);
4461 }
4462 
4463 static int
4464 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4465        int retry_count, int timeout)
4466 {
4467 	int c, error = 0;
4468 	union ccb *ccb;
4469 	uint8_t *smp_request = NULL, *smp_response = NULL;
4470 	int request_size = 0, response_size = 0;
4471 	int fd_request = 0, fd_response = 0;
4472 	char *datastr = NULL;
4473 	struct get_hook hook;
4474 	int retval;
4475 	int flags = 0;
4476 
4477 	/*
4478 	 * Note that at the moment we don't support sending SMP CCBs to
4479 	 * devices that aren't probed by CAM.
4480 	 */
4481 	ccb = cam_getccb(device);
4482 	if (ccb == NULL) {
4483 		warnx("%s: error allocating CCB", __func__);
4484 		return (1);
4485 	}
4486 
4487 	bzero(&(&ccb->ccb_h)[1],
4488 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4489 
4490 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4491 		switch (c) {
4492 		case 'R':
4493 			arglist |= CAM_ARG_CMD_IN;
4494 			response_size = strtol(optarg, NULL, 0);
4495 			if (response_size <= 0) {
4496 				warnx("invalid number of response bytes %d",
4497 				      response_size);
4498 				error = 1;
4499 				goto smpcmd_bailout;
4500 			}
4501 			hook.argc = argc - optind;
4502 			hook.argv = argv + optind;
4503 			hook.got = 0;
4504 			optind++;
4505 			datastr = cget(&hook, NULL);
4506 			/*
4507 			 * If the user supplied "-" instead of a format, he
4508 			 * wants the data to be written to stdout.
4509 			 */
4510 			if ((datastr != NULL)
4511 			 && (datastr[0] == '-'))
4512 				fd_response = 1;
4513 
4514 			smp_response = (u_int8_t *)malloc(response_size);
4515 			if (smp_response == NULL) {
4516 				warn("can't malloc memory for SMP response");
4517 				error = 1;
4518 				goto smpcmd_bailout;
4519 			}
4520 			break;
4521 		case 'r':
4522 			arglist |= CAM_ARG_CMD_OUT;
4523 			request_size = strtol(optarg, NULL, 0);
4524 			if (request_size <= 0) {
4525 				warnx("invalid number of request bytes %d",
4526 				      request_size);
4527 				error = 1;
4528 				goto smpcmd_bailout;
4529 			}
4530 			hook.argc = argc - optind;
4531 			hook.argv = argv + optind;
4532 			hook.got = 0;
4533 			datastr = cget(&hook, NULL);
4534 			smp_request = (u_int8_t *)malloc(request_size);
4535 			if (smp_request == NULL) {
4536 				warn("can't malloc memory for SMP request");
4537 				error = 1;
4538 				goto smpcmd_bailout;
4539 			}
4540 			bzero(smp_request, request_size);
4541 			/*
4542 			 * If the user supplied "-" instead of a format, he
4543 			 * wants the data to be read from stdin.
4544 			 */
4545 			if ((datastr != NULL)
4546 			 && (datastr[0] == '-'))
4547 				fd_request = 1;
4548 			else
4549 				buff_encode_visit(smp_request, request_size,
4550 						  datastr,
4551 						  iget, &hook);
4552 			optind += hook.got;
4553 			break;
4554 		default:
4555 			break;
4556 		}
4557 	}
4558 
4559 	/*
4560 	 * If fd_data is set, and we're writing to the device, we need to
4561 	 * read the data the user wants written from stdin.
4562 	 */
4563 	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4564 		ssize_t amt_read;
4565 		int amt_to_read = request_size;
4566 		u_int8_t *buf_ptr = smp_request;
4567 
4568 		for (amt_read = 0; amt_to_read > 0;
4569 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4570 			if (amt_read == -1) {
4571 				warn("error reading data from stdin");
4572 				error = 1;
4573 				goto smpcmd_bailout;
4574 			}
4575 			amt_to_read -= amt_read;
4576 			buf_ptr += amt_read;
4577 		}
4578 	}
4579 
4580 	if (((arglist & CAM_ARG_CMD_IN) == 0)
4581 	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
4582 		warnx("%s: need both the request (-r) and response (-R) "
4583 		      "arguments", __func__);
4584 		error = 1;
4585 		goto smpcmd_bailout;
4586 	}
4587 
4588 	flags |= CAM_DEV_QFRZDIS;
4589 
4590 	cam_fill_smpio(&ccb->smpio,
4591 		       /*retries*/ retry_count,
4592 		       /*cbfcnp*/ NULL,
4593 		       /*flags*/ flags,
4594 		       /*smp_request*/ smp_request,
4595 		       /*smp_request_len*/ request_size,
4596 		       /*smp_response*/ smp_response,
4597 		       /*smp_response_len*/ response_size,
4598 		       /*timeout*/ timeout ? timeout : 5000);
4599 
4600 	ccb->smpio.flags = SMP_FLAG_NONE;
4601 
4602 	if (((retval = cam_send_ccb(device, ccb)) < 0)
4603 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4604 		const char warnstr[] = "error sending command";
4605 
4606 		if (retval < 0)
4607 			warn(warnstr);
4608 		else
4609 			warnx(warnstr);
4610 
4611 		if (arglist & CAM_ARG_VERBOSE) {
4612 			cam_error_print(device, ccb, CAM_ESF_ALL,
4613 					CAM_EPF_ALL, stderr);
4614 		}
4615 	}
4616 
4617 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4618 	 && (response_size > 0)) {
4619 		if (fd_response == 0) {
4620 			buff_decode_visit(smp_response, response_size,
4621 					  datastr, arg_put, NULL);
4622 			fprintf(stdout, "\n");
4623 		} else {
4624 			ssize_t amt_written;
4625 			int amt_to_write = response_size;
4626 			u_int8_t *buf_ptr = smp_response;
4627 
4628 			for (amt_written = 0; (amt_to_write > 0) &&
4629 			     (amt_written = write(STDOUT_FILENO, buf_ptr,
4630 						  amt_to_write)) > 0;){
4631 				amt_to_write -= amt_written;
4632 				buf_ptr += amt_written;
4633 			}
4634 			if (amt_written == -1) {
4635 				warn("error writing data to stdout");
4636 				error = 1;
4637 				goto smpcmd_bailout;
4638 			} else if ((amt_written == 0)
4639 				&& (amt_to_write > 0)) {
4640 				warnx("only wrote %u bytes out of %u",
4641 				      response_size - amt_to_write,
4642 				      response_size);
4643 			}
4644 		}
4645 	}
4646 smpcmd_bailout:
4647 	if (ccb != NULL)
4648 		cam_freeccb(ccb);
4649 
4650 	if (smp_request != NULL)
4651 		free(smp_request);
4652 
4653 	if (smp_response != NULL)
4654 		free(smp_response);
4655 
4656 	return (error);
4657 }
4658 
4659 static int
4660 smpreportgeneral(struct cam_device *device, int argc, char **argv,
4661 		 char *combinedopt, int retry_count, int timeout)
4662 {
4663 	union ccb *ccb;
4664 	struct smp_report_general_request *request = NULL;
4665 	struct smp_report_general_response *response = NULL;
4666 	struct sbuf *sb = NULL;
4667 	int error = 0;
4668 	int c, long_response = 0;
4669 	int retval;
4670 
4671 	/*
4672 	 * Note that at the moment we don't support sending SMP CCBs to
4673 	 * devices that aren't probed by CAM.
4674 	 */
4675 	ccb = cam_getccb(device);
4676 	if (ccb == NULL) {
4677 		warnx("%s: error allocating CCB", __func__);
4678 		return (1);
4679 	}
4680 
4681 	bzero(&(&ccb->ccb_h)[1],
4682 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4683 
4684 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4685 		switch (c) {
4686 		case 'l':
4687 			long_response = 1;
4688 			break;
4689 		default:
4690 			break;
4691 		}
4692 	}
4693 	request = malloc(sizeof(*request));
4694 	if (request == NULL) {
4695 		warn("%s: unable to allocate %zd bytes", __func__,
4696 		     sizeof(*request));
4697 		error = 1;
4698 		goto bailout;
4699 	}
4700 
4701 	response = malloc(sizeof(*response));
4702 	if (response == NULL) {
4703 		warn("%s: unable to allocate %zd bytes", __func__,
4704 		     sizeof(*response));
4705 		error = 1;
4706 		goto bailout;
4707 	}
4708 
4709 try_long:
4710 	smp_report_general(&ccb->smpio,
4711 			   retry_count,
4712 			   /*cbfcnp*/ NULL,
4713 			   request,
4714 			   /*request_len*/ sizeof(*request),
4715 			   (uint8_t *)response,
4716 			   /*response_len*/ sizeof(*response),
4717 			   /*long_response*/ long_response,
4718 			   timeout);
4719 
4720 	if (((retval = cam_send_ccb(device, ccb)) < 0)
4721 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4722 		const char warnstr[] = "error sending command";
4723 
4724 		if (retval < 0)
4725 			warn(warnstr);
4726 		else
4727 			warnx(warnstr);
4728 
4729 		if (arglist & CAM_ARG_VERBOSE) {
4730 			cam_error_print(device, ccb, CAM_ESF_ALL,
4731 					CAM_EPF_ALL, stderr);
4732 		}
4733 		error = 1;
4734 		goto bailout;
4735 	}
4736 
4737 	/*
4738 	 * If the device supports the long response bit, try again and see
4739 	 * if we can get all of the data.
4740 	 */
4741 	if ((response->long_response & SMP_RG_LONG_RESPONSE)
4742 	 && (long_response == 0)) {
4743 		ccb->ccb_h.status = CAM_REQ_INPROG;
4744 		bzero(&(&ccb->ccb_h)[1],
4745 		      sizeof(union ccb) - sizeof(struct ccb_hdr));
4746 		long_response = 1;
4747 		goto try_long;
4748 	}
4749 
4750 	/*
4751 	 * XXX KDM detect and decode SMP errors here.
4752 	 */
4753 	sb = sbuf_new_auto();
4754 	if (sb == NULL) {
4755 		warnx("%s: error allocating sbuf", __func__);
4756 		goto bailout;
4757 	}
4758 
4759 	smp_report_general_sbuf(response, sizeof(*response), sb);
4760 
4761 	if (sbuf_finish(sb) != 0) {
4762 		warnx("%s: sbuf_finish", __func__);
4763 		goto bailout;
4764 	}
4765 
4766 	printf("%s", sbuf_data(sb));
4767 
4768 bailout:
4769 	if (ccb != NULL)
4770 		cam_freeccb(ccb);
4771 
4772 	if (request != NULL)
4773 		free(request);
4774 
4775 	if (response != NULL)
4776 		free(response);
4777 
4778 	if (sb != NULL)
4779 		sbuf_delete(sb);
4780 
4781 	return (error);
4782 }
4783 
4784 static struct camcontrol_opts phy_ops[] = {
4785 	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
4786 	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
4787 	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
4788 	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
4789 	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
4790 	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
4791 	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
4792 	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
4793 	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
4794 	{NULL, 0, 0, NULL}
4795 };
4796 
4797 static int
4798 smpphycontrol(struct cam_device *device, int argc, char **argv,
4799 	      char *combinedopt, int retry_count, int timeout)
4800 {
4801 	union ccb *ccb;
4802 	struct smp_phy_control_request *request = NULL;
4803 	struct smp_phy_control_response *response = NULL;
4804 	int long_response = 0;
4805 	int retval = 0;
4806 	int phy = -1;
4807 	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
4808 	int phy_op_set = 0;
4809 	uint64_t attached_dev_name = 0;
4810 	int dev_name_set = 0;
4811 	uint32_t min_plr = 0, max_plr = 0;
4812 	uint32_t pp_timeout_val = 0;
4813 	int slumber_partial = 0;
4814 	int set_pp_timeout_val = 0;
4815 	int c;
4816 
4817 	/*
4818 	 * Note that at the moment we don't support sending SMP CCBs to
4819 	 * devices that aren't probed by CAM.
4820 	 */
4821 	ccb = cam_getccb(device);
4822 	if (ccb == NULL) {
4823 		warnx("%s: error allocating CCB", __func__);
4824 		return (1);
4825 	}
4826 
4827 	bzero(&(&ccb->ccb_h)[1],
4828 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4829 
4830 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4831 		switch (c) {
4832 		case 'a':
4833 		case 'A':
4834 		case 's':
4835 		case 'S': {
4836 			int enable = -1;
4837 
4838 			if (strcasecmp(optarg, "enable") == 0)
4839 				enable = 1;
4840 			else if (strcasecmp(optarg, "disable") == 0)
4841 				enable = 2;
4842 			else {
4843 				warnx("%s: Invalid argument %s", __func__,
4844 				      optarg);
4845 				retval = 1;
4846 				goto bailout;
4847 			}
4848 			switch (c) {
4849 			case 's':
4850 				slumber_partial |= enable <<
4851 						   SMP_PC_SAS_SLUMBER_SHIFT;
4852 				break;
4853 			case 'S':
4854 				slumber_partial |= enable <<
4855 						   SMP_PC_SAS_PARTIAL_SHIFT;
4856 				break;
4857 			case 'a':
4858 				slumber_partial |= enable <<
4859 						   SMP_PC_SATA_SLUMBER_SHIFT;
4860 				break;
4861 			case 'A':
4862 				slumber_partial |= enable <<
4863 						   SMP_PC_SATA_PARTIAL_SHIFT;
4864 				break;
4865 			default:
4866 				warnx("%s: programmer error", __func__);
4867 				retval = 1;
4868 				goto bailout;
4869 				break; /*NOTREACHED*/
4870 			}
4871 			break;
4872 		}
4873 		case 'd':
4874 			attached_dev_name = (uintmax_t)strtoumax(optarg,
4875 								 NULL,0);
4876 			dev_name_set = 1;
4877 			break;
4878 		case 'l':
4879 			long_response = 1;
4880 			break;
4881 		case 'm':
4882 			/*
4883 			 * We don't do extensive checking here, so this
4884 			 * will continue to work when new speeds come out.
4885 			 */
4886 			min_plr = strtoul(optarg, NULL, 0);
4887 			if ((min_plr == 0)
4888 			 || (min_plr > 0xf)) {
4889 				warnx("%s: invalid link rate %x",
4890 				      __func__, min_plr);
4891 				retval = 1;
4892 				goto bailout;
4893 			}
4894 			break;
4895 		case 'M':
4896 			/*
4897 			 * We don't do extensive checking here, so this
4898 			 * will continue to work when new speeds come out.
4899 			 */
4900 			max_plr = strtoul(optarg, NULL, 0);
4901 			if ((max_plr == 0)
4902 			 || (max_plr > 0xf)) {
4903 				warnx("%s: invalid link rate %x",
4904 				      __func__, max_plr);
4905 				retval = 1;
4906 				goto bailout;
4907 			}
4908 			break;
4909 		case 'o': {
4910 			camcontrol_optret optreturn;
4911 			cam_argmask argnums;
4912 			const char *subopt;
4913 
4914 			if (phy_op_set != 0) {
4915 				warnx("%s: only one phy operation argument "
4916 				      "(-o) allowed", __func__);
4917 				retval = 1;
4918 				goto bailout;
4919 			}
4920 
4921 			phy_op_set = 1;
4922 
4923 			/*
4924 			 * Allow the user to specify the phy operation
4925 			 * numerically, as well as with a name.  This will
4926 			 * future-proof it a bit, so options that are added
4927 			 * in future specs can be used.
4928 			 */
4929 			if (isdigit(optarg[0])) {
4930 				phy_operation = strtoul(optarg, NULL, 0);
4931 				if ((phy_operation == 0)
4932 				 || (phy_operation > 0xff)) {
4933 					warnx("%s: invalid phy operation %#x",
4934 					      __func__, phy_operation);
4935 					retval = 1;
4936 					goto bailout;
4937 				}
4938 				break;
4939 			}
4940 			optreturn = getoption(phy_ops, optarg, &phy_operation,
4941 					      &argnums, &subopt);
4942 
4943 			if (optreturn == CC_OR_AMBIGUOUS) {
4944 				warnx("%s: ambiguous option %s", __func__,
4945 				      optarg);
4946 				usage(0);
4947 				retval = 1;
4948 				goto bailout;
4949 			} else if (optreturn == CC_OR_NOT_FOUND) {
4950 				warnx("%s: option %s not found", __func__,
4951 				      optarg);
4952 				usage(0);
4953 				retval = 1;
4954 				goto bailout;
4955 			}
4956 			break;
4957 		}
4958 		case 'p':
4959 			phy = atoi(optarg);
4960 			break;
4961 		case 'T':
4962 			pp_timeout_val = strtoul(optarg, NULL, 0);
4963 			if (pp_timeout_val > 15) {
4964 				warnx("%s: invalid partial pathway timeout "
4965 				      "value %u, need a value less than 16",
4966 				      __func__, pp_timeout_val);
4967 				retval = 1;
4968 				goto bailout;
4969 			}
4970 			set_pp_timeout_val = 1;
4971 			break;
4972 		default:
4973 			break;
4974 		}
4975 	}
4976 
4977 	if (phy == -1) {
4978 		warnx("%s: a PHY (-p phy) argument is required",__func__);
4979 		retval = 1;
4980 		goto bailout;
4981 	}
4982 
4983 	if (((dev_name_set != 0)
4984 	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
4985 	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
4986 	  && (dev_name_set == 0))) {
4987 		warnx("%s: -d name and -o setdevname arguments both "
4988 		      "required to set device name", __func__);
4989 		retval = 1;
4990 		goto bailout;
4991 	}
4992 
4993 	request = malloc(sizeof(*request));
4994 	if (request == NULL) {
4995 		warn("%s: unable to allocate %zd bytes", __func__,
4996 		     sizeof(*request));
4997 		retval = 1;
4998 		goto bailout;
4999 	}
5000 
5001 	response = malloc(sizeof(*response));
5002 	if (response == NULL) {
5003 		warn("%s: unable to allocate %zd bytes", __func__,
5004 		     sizeof(*request));
5005 		retval = 1;
5006 		goto bailout;
5007 	}
5008 
5009 	smp_phy_control(&ccb->smpio,
5010 			retry_count,
5011 			/*cbfcnp*/ NULL,
5012 			request,
5013 			sizeof(*request),
5014 			(uint8_t *)response,
5015 			sizeof(*response),
5016 			long_response,
5017 			/*expected_exp_change_count*/ 0,
5018 			phy,
5019 			phy_operation,
5020 			(set_pp_timeout_val != 0) ? 1 : 0,
5021 			attached_dev_name,
5022 			min_plr,
5023 			max_plr,
5024 			slumber_partial,
5025 			pp_timeout_val,
5026 			timeout);
5027 
5028 	if (((retval = cam_send_ccb(device, ccb)) < 0)
5029 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5030 		const char warnstr[] = "error sending command";
5031 
5032 		if (retval < 0)
5033 			warn(warnstr);
5034 		else
5035 			warnx(warnstr);
5036 
5037 		if (arglist & CAM_ARG_VERBOSE) {
5038 			/*
5039 			 * Use CAM_EPF_NORMAL so we only get one line of
5040 			 * SMP command decoding.
5041 			 */
5042 			cam_error_print(device, ccb, CAM_ESF_ALL,
5043 					CAM_EPF_NORMAL, stderr);
5044 		}
5045 		retval = 1;
5046 		goto bailout;
5047 	}
5048 
5049 	/* XXX KDM print out something here for success? */
5050 bailout:
5051 	if (ccb != NULL)
5052 		cam_freeccb(ccb);
5053 
5054 	if (request != NULL)
5055 		free(request);
5056 
5057 	if (response != NULL)
5058 		free(response);
5059 
5060 	return (retval);
5061 }
5062 
5063 static int
5064 smpmaninfo(struct cam_device *device, int argc, char **argv,
5065 	   char *combinedopt, int retry_count, int timeout)
5066 {
5067 	union ccb *ccb;
5068 	struct smp_report_manuf_info_request request;
5069 	struct smp_report_manuf_info_response response;
5070 	struct sbuf *sb = NULL;
5071 	int long_response = 0;
5072 	int retval = 0;
5073 	int c;
5074 
5075 	/*
5076 	 * Note that at the moment we don't support sending SMP CCBs to
5077 	 * devices that aren't probed by CAM.
5078 	 */
5079 	ccb = cam_getccb(device);
5080 	if (ccb == NULL) {
5081 		warnx("%s: error allocating CCB", __func__);
5082 		return (1);
5083 	}
5084 
5085 	bzero(&(&ccb->ccb_h)[1],
5086 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5087 
5088 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5089 		switch (c) {
5090 		case 'l':
5091 			long_response = 1;
5092 			break;
5093 		default:
5094 			break;
5095 		}
5096 	}
5097 	bzero(&request, sizeof(request));
5098 	bzero(&response, sizeof(response));
5099 
5100 	smp_report_manuf_info(&ccb->smpio,
5101 			      retry_count,
5102 			      /*cbfcnp*/ NULL,
5103 			      &request,
5104 			      sizeof(request),
5105 			      (uint8_t *)&response,
5106 			      sizeof(response),
5107 			      long_response,
5108 			      timeout);
5109 
5110 	if (((retval = cam_send_ccb(device, ccb)) < 0)
5111 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5112 		const char warnstr[] = "error sending command";
5113 
5114 		if (retval < 0)
5115 			warn(warnstr);
5116 		else
5117 			warnx(warnstr);
5118 
5119 		if (arglist & CAM_ARG_VERBOSE) {
5120 			cam_error_print(device, ccb, CAM_ESF_ALL,
5121 					CAM_EPF_ALL, stderr);
5122 		}
5123 		retval = 1;
5124 		goto bailout;
5125 	}
5126 
5127 	sb = sbuf_new_auto();
5128 	if (sb == NULL) {
5129 		warnx("%s: error allocating sbuf", __func__);
5130 		goto bailout;
5131 	}
5132 
5133 	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
5134 
5135 	if (sbuf_finish(sb) != 0) {
5136 		warnx("%s: sbuf_finish", __func__);
5137 		goto bailout;
5138 	}
5139 
5140 	printf("%s", sbuf_data(sb));
5141 
5142 bailout:
5143 
5144 	if (ccb != NULL)
5145 		cam_freeccb(ccb);
5146 
5147 	if (sb != NULL)
5148 		sbuf_delete(sb);
5149 
5150 	return (retval);
5151 }
5152 
5153 static int
5154 getdevid(struct cam_devitem *item)
5155 {
5156 	int retval = 0;
5157 	union ccb *ccb = NULL;
5158 
5159 	struct cam_device *dev;
5160 
5161 	dev = cam_open_btl(item->dev_match.path_id,
5162 			   item->dev_match.target_id,
5163 			   item->dev_match.target_lun, O_RDWR, NULL);
5164 
5165 	if (dev == NULL) {
5166 		warnx("%s", cam_errbuf);
5167 		retval = 1;
5168 		goto bailout;
5169 	}
5170 
5171 	item->device_id_len = 0;
5172 
5173 	ccb = cam_getccb(dev);
5174 	if (ccb == NULL) {
5175 		warnx("%s: error allocating CCB", __func__);
5176 		retval = 1;
5177 		goto bailout;
5178 	}
5179 
5180 	bzero(&(&ccb->ccb_h)[1],
5181 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5182 
5183 	/*
5184 	 * On the first try, we just probe for the size of the data, and
5185 	 * then allocate that much memory and try again.
5186 	 */
5187 retry:
5188 	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
5189 	ccb->ccb_h.flags = CAM_DIR_IN;
5190 	ccb->cdai.flags = 0;
5191 	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
5192 	ccb->cdai.bufsiz = item->device_id_len;
5193 	if (item->device_id_len != 0)
5194 		ccb->cdai.buf = (uint8_t *)item->device_id;
5195 
5196 	if (cam_send_ccb(dev, ccb) < 0) {
5197 		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
5198 		retval = 1;
5199 		goto bailout;
5200 	}
5201 
5202 	if (ccb->ccb_h.status != CAM_REQ_CMP) {
5203 		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
5204 		retval = 1;
5205 		goto bailout;
5206 	}
5207 
5208 	if (item->device_id_len == 0) {
5209 		/*
5210 		 * This is our first time through.  Allocate the buffer,
5211 		 * and then go back to get the data.
5212 		 */
5213 		if (ccb->cdai.provsiz == 0) {
5214 			warnx("%s: invalid .provsiz field returned with "
5215 			     "XPT_GDEV_ADVINFO CCB", __func__);
5216 			retval = 1;
5217 			goto bailout;
5218 		}
5219 		item->device_id_len = ccb->cdai.provsiz;
5220 		item->device_id = malloc(item->device_id_len);
5221 		if (item->device_id == NULL) {
5222 			warn("%s: unable to allocate %d bytes", __func__,
5223 			     item->device_id_len);
5224 			retval = 1;
5225 			goto bailout;
5226 		}
5227 		ccb->ccb_h.status = CAM_REQ_INPROG;
5228 		goto retry;
5229 	}
5230 
5231 bailout:
5232 	if (dev != NULL)
5233 		cam_close_device(dev);
5234 
5235 	if (ccb != NULL)
5236 		cam_freeccb(ccb);
5237 
5238 	return (retval);
5239 }
5240 
5241 /*
5242  * XXX KDM merge this code with getdevtree()?
5243  */
5244 static int
5245 buildbusdevlist(struct cam_devlist *devlist)
5246 {
5247 	union ccb ccb;
5248 	int bufsize, fd = -1;
5249 	struct dev_match_pattern *patterns;
5250 	struct cam_devitem *item = NULL;
5251 	int skip_device = 0;
5252 	int retval = 0;
5253 
5254 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
5255 		warn("couldn't open %s", XPT_DEVICE);
5256 		return(1);
5257 	}
5258 
5259 	bzero(&ccb, sizeof(union ccb));
5260 
5261 	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
5262 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
5263 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
5264 
5265 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
5266 	bufsize = sizeof(struct dev_match_result) * 100;
5267 	ccb.cdm.match_buf_len = bufsize;
5268 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
5269 	if (ccb.cdm.matches == NULL) {
5270 		warnx("can't malloc memory for matches");
5271 		close(fd);
5272 		return(1);
5273 	}
5274 	ccb.cdm.num_matches = 0;
5275 	ccb.cdm.num_patterns = 2;
5276 	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
5277 		ccb.cdm.num_patterns;
5278 
5279 	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
5280 	if (patterns == NULL) {
5281 		warnx("can't malloc memory for patterns");
5282 		retval = 1;
5283 		goto bailout;
5284 	}
5285 
5286 	ccb.cdm.patterns = patterns;
5287 	bzero(patterns, ccb.cdm.pattern_buf_len);
5288 
5289 	patterns[0].type = DEV_MATCH_DEVICE;
5290 	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
5291 	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
5292 	patterns[1].type = DEV_MATCH_PERIPH;
5293 	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
5294 	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
5295 
5296 	/*
5297 	 * We do the ioctl multiple times if necessary, in case there are
5298 	 * more than 100 nodes in the EDT.
5299 	 */
5300 	do {
5301 		unsigned int i;
5302 
5303 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
5304 			warn("error sending CAMIOCOMMAND ioctl");
5305 			retval = 1;
5306 			goto bailout;
5307 		}
5308 
5309 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
5310 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
5311 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
5312 			warnx("got CAM error %#x, CDM error %d\n",
5313 			      ccb.ccb_h.status, ccb.cdm.status);
5314 			retval = 1;
5315 			goto bailout;
5316 		}
5317 
5318 		for (i = 0; i < ccb.cdm.num_matches; i++) {
5319 			switch (ccb.cdm.matches[i].type) {
5320 			case DEV_MATCH_DEVICE: {
5321 				struct device_match_result *dev_result;
5322 
5323 				dev_result =
5324 				     &ccb.cdm.matches[i].result.device_result;
5325 
5326 				if (dev_result->flags &
5327 				    DEV_RESULT_UNCONFIGURED) {
5328 					skip_device = 1;
5329 					break;
5330 				} else
5331 					skip_device = 0;
5332 
5333 				item = malloc(sizeof(*item));
5334 				if (item == NULL) {
5335 					warn("%s: unable to allocate %zd bytes",
5336 					     __func__, sizeof(*item));
5337 					retval = 1;
5338 					goto bailout;
5339 				}
5340 				bzero(item, sizeof(*item));
5341 				bcopy(dev_result, &item->dev_match,
5342 				      sizeof(*dev_result));
5343 				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
5344 						   links);
5345 
5346 				if (getdevid(item) != 0) {
5347 					retval = 1;
5348 					goto bailout;
5349 				}
5350 				break;
5351 			}
5352 			case DEV_MATCH_PERIPH: {
5353 				struct periph_match_result *periph_result;
5354 
5355 				periph_result =
5356 				      &ccb.cdm.matches[i].result.periph_result;
5357 
5358 				if (skip_device != 0)
5359 					break;
5360 				item->num_periphs++;
5361 				item->periph_matches = realloc(
5362 					item->periph_matches,
5363 					item->num_periphs *
5364 					sizeof(struct periph_match_result));
5365 				if (item->periph_matches == NULL) {
5366 					warn("%s: error allocating periph "
5367 					     "list", __func__);
5368 					retval = 1;
5369 					goto bailout;
5370 				}
5371 				bcopy(periph_result, &item->periph_matches[
5372 				      item->num_periphs - 1],
5373 				      sizeof(*periph_result));
5374 				break;
5375 			}
5376 			default:
5377 				fprintf(stderr, "%s: unexpected match "
5378 					"type %d\n", __func__,
5379 					ccb.cdm.matches[i].type);
5380 				retval = 1;
5381 				goto bailout;
5382 				break; /*NOTREACHED*/
5383 			}
5384 		}
5385 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
5386 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
5387 bailout:
5388 
5389 	if (fd != -1)
5390 		close(fd);
5391 
5392 	free(patterns);
5393 
5394 	free(ccb.cdm.matches);
5395 
5396 	if (retval != 0)
5397 		freebusdevlist(devlist);
5398 
5399 	return (retval);
5400 }
5401 
5402 static void
5403 freebusdevlist(struct cam_devlist *devlist)
5404 {
5405 	struct cam_devitem *item, *item2;
5406 
5407 	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
5408 		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
5409 			      links);
5410 		free(item->device_id);
5411 		free(item->periph_matches);
5412 		free(item);
5413 	}
5414 }
5415 
5416 static struct cam_devitem *
5417 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
5418 {
5419 	struct cam_devitem *item;
5420 
5421 	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
5422 		uint8_t *item_addr;
5423 
5424 		/*
5425 		 * XXX KDM look for LUN IDs as well?
5426 		 */
5427 		item_addr = scsi_get_devid(item->device_id,
5428 					   item->device_id_len,
5429 					   scsi_devid_is_sas_target);
5430 		if (item_addr == NULL)
5431 			continue;
5432 
5433 		if (scsi_8btou64(item_addr) == sasaddr)
5434 			return (item);
5435 	}
5436 
5437 	return (NULL);
5438 }
5439 
5440 static int
5441 smpphylist(struct cam_device *device, int argc, char **argv,
5442 	   char *combinedopt, int retry_count, int timeout)
5443 {
5444 	struct smp_report_general_request *rgrequest = NULL;
5445 	struct smp_report_general_response *rgresponse = NULL;
5446 	struct smp_discover_request *disrequest = NULL;
5447 	struct smp_discover_response *disresponse = NULL;
5448 	struct cam_devlist devlist;
5449 	union ccb *ccb;
5450 	int long_response = 0;
5451 	int num_phys = 0;
5452 	int quiet = 0;
5453 	int retval;
5454 	int i, c;
5455 
5456 	/*
5457 	 * Note that at the moment we don't support sending SMP CCBs to
5458 	 * devices that aren't probed by CAM.
5459 	 */
5460 	ccb = cam_getccb(device);
5461 	if (ccb == NULL) {
5462 		warnx("%s: error allocating CCB", __func__);
5463 		return (1);
5464 	}
5465 
5466 	bzero(&(&ccb->ccb_h)[1],
5467 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5468 	STAILQ_INIT(&devlist.dev_queue);
5469 
5470 	rgrequest = malloc(sizeof(*rgrequest));
5471 	if (rgrequest == NULL) {
5472 		warn("%s: unable to allocate %zd bytes", __func__,
5473 		     sizeof(*rgrequest));
5474 		retval = 1;
5475 		goto bailout;
5476 	}
5477 
5478 	rgresponse = malloc(sizeof(*rgresponse));
5479 	if (rgresponse == NULL) {
5480 		warn("%s: unable to allocate %zd bytes", __func__,
5481 		     sizeof(*rgresponse));
5482 		retval = 1;
5483 		goto bailout;
5484 	}
5485 
5486 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5487 		switch (c) {
5488 		case 'l':
5489 			long_response = 1;
5490 			break;
5491 		case 'q':
5492 			quiet = 1;
5493 			break;
5494 		default:
5495 			break;
5496 		}
5497 	}
5498 
5499 	smp_report_general(&ccb->smpio,
5500 			   retry_count,
5501 			   /*cbfcnp*/ NULL,
5502 			   rgrequest,
5503 			   /*request_len*/ sizeof(*rgrequest),
5504 			   (uint8_t *)rgresponse,
5505 			   /*response_len*/ sizeof(*rgresponse),
5506 			   /*long_response*/ long_response,
5507 			   timeout);
5508 
5509 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5510 
5511 	if (((retval = cam_send_ccb(device, ccb)) < 0)
5512 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5513 		const char warnstr[] = "error sending command";
5514 
5515 		if (retval < 0)
5516 			warn(warnstr);
5517 		else
5518 			warnx(warnstr);
5519 
5520 		if (arglist & CAM_ARG_VERBOSE) {
5521 			cam_error_print(device, ccb, CAM_ESF_ALL,
5522 					CAM_EPF_ALL, stderr);
5523 		}
5524 		retval = 1;
5525 		goto bailout;
5526 	}
5527 
5528 	num_phys = rgresponse->num_phys;
5529 
5530 	if (num_phys == 0) {
5531 		if (quiet == 0)
5532 			fprintf(stdout, "%s: No Phys reported\n", __func__);
5533 		retval = 1;
5534 		goto bailout;
5535 	}
5536 
5537 	devlist.path_id = device->path_id;
5538 
5539 	retval = buildbusdevlist(&devlist);
5540 	if (retval != 0)
5541 		goto bailout;
5542 
5543 	if (quiet == 0) {
5544 		fprintf(stdout, "%d PHYs:\n", num_phys);
5545 		fprintf(stdout, "PHY  Attached SAS Address\n");
5546 	}
5547 
5548 	disrequest = malloc(sizeof(*disrequest));
5549 	if (disrequest == NULL) {
5550 		warn("%s: unable to allocate %zd bytes", __func__,
5551 		     sizeof(*disrequest));
5552 		retval = 1;
5553 		goto bailout;
5554 	}
5555 
5556 	disresponse = malloc(sizeof(*disresponse));
5557 	if (disresponse == NULL) {
5558 		warn("%s: unable to allocate %zd bytes", __func__,
5559 		     sizeof(*disresponse));
5560 		retval = 1;
5561 		goto bailout;
5562 	}
5563 
5564 	for (i = 0; i < num_phys; i++) {
5565 		struct cam_devitem *item;
5566 		struct device_match_result *dev_match;
5567 		char vendor[16], product[48], revision[16];
5568 		char tmpstr[256];
5569 		int j;
5570 
5571 		bzero(&(&ccb->ccb_h)[1],
5572 		      sizeof(union ccb) - sizeof(struct ccb_hdr));
5573 
5574 		ccb->ccb_h.status = CAM_REQ_INPROG;
5575 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5576 
5577 		smp_discover(&ccb->smpio,
5578 			     retry_count,
5579 			     /*cbfcnp*/ NULL,
5580 			     disrequest,
5581 			     sizeof(*disrequest),
5582 			     (uint8_t *)disresponse,
5583 			     sizeof(*disresponse),
5584 			     long_response,
5585 			     /*ignore_zone_group*/ 0,
5586 			     /*phy*/ i,
5587 			     timeout);
5588 
5589 		if (((retval = cam_send_ccb(device, ccb)) < 0)
5590 		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
5591 		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
5592 			const char warnstr[] = "error sending command";
5593 
5594 			if (retval < 0)
5595 				warn(warnstr);
5596 			else
5597 				warnx(warnstr);
5598 
5599 			if (arglist & CAM_ARG_VERBOSE) {
5600 				cam_error_print(device, ccb, CAM_ESF_ALL,
5601 						CAM_EPF_ALL, stderr);
5602 			}
5603 			retval = 1;
5604 			goto bailout;
5605 		}
5606 
5607 		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
5608 			if (quiet == 0)
5609 				fprintf(stdout, "%3d  <vacant>\n", i);
5610 			continue;
5611 		}
5612 
5613 		item = findsasdevice(&devlist,
5614 			scsi_8btou64(disresponse->attached_sas_address));
5615 
5616 		if ((quiet == 0)
5617 		 || (item != NULL)) {
5618 			fprintf(stdout, "%3d  0x%016jx", i,
5619 				(uintmax_t)scsi_8btou64(
5620 				disresponse->attached_sas_address));
5621 			if (item == NULL) {
5622 				fprintf(stdout, "\n");
5623 				continue;
5624 			}
5625 		} else if (quiet != 0)
5626 			continue;
5627 
5628 		dev_match = &item->dev_match;
5629 
5630 		if (dev_match->protocol == PROTO_SCSI) {
5631 			cam_strvis(vendor, dev_match->inq_data.vendor,
5632 				   sizeof(dev_match->inq_data.vendor),
5633 				   sizeof(vendor));
5634 			cam_strvis(product, dev_match->inq_data.product,
5635 				   sizeof(dev_match->inq_data.product),
5636 				   sizeof(product));
5637 			cam_strvis(revision, dev_match->inq_data.revision,
5638 				   sizeof(dev_match->inq_data.revision),
5639 				   sizeof(revision));
5640 			sprintf(tmpstr, "<%s %s %s>", vendor, product,
5641 				revision);
5642 		} else if ((dev_match->protocol == PROTO_ATA)
5643 			|| (dev_match->protocol == PROTO_SATAPM)) {
5644 			cam_strvis(product, dev_match->ident_data.model,
5645 				   sizeof(dev_match->ident_data.model),
5646 				   sizeof(product));
5647 			cam_strvis(revision, dev_match->ident_data.revision,
5648 				   sizeof(dev_match->ident_data.revision),
5649 				   sizeof(revision));
5650 			sprintf(tmpstr, "<%s %s>", product, revision);
5651 		} else {
5652 			sprintf(tmpstr, "<>");
5653 		}
5654 		fprintf(stdout, "   %-33s ", tmpstr);
5655 
5656 		/*
5657 		 * If we have 0 periphs, that's a bug...
5658 		 */
5659 		if (item->num_periphs == 0) {
5660 			fprintf(stdout, "\n");
5661 			continue;
5662 		}
5663 
5664 		fprintf(stdout, "(");
5665 		for (j = 0; j < item->num_periphs; j++) {
5666 			if (j > 0)
5667 				fprintf(stdout, ",");
5668 
5669 			fprintf(stdout, "%s%d",
5670 				item->periph_matches[j].periph_name,
5671 				item->periph_matches[j].unit_number);
5672 
5673 		}
5674 		fprintf(stdout, ")\n");
5675 	}
5676 bailout:
5677 	if (ccb != NULL)
5678 		cam_freeccb(ccb);
5679 
5680 	free(rgrequest);
5681 
5682 	free(rgresponse);
5683 
5684 	free(disrequest);
5685 
5686 	free(disresponse);
5687 
5688 	freebusdevlist(&devlist);
5689 
5690 	return (retval);
5691 }
5692 
5693 static int
5694 atapm(struct cam_device *device, int argc, char **argv,
5695 		 char *combinedopt, int retry_count, int timeout)
5696 {
5697 	union ccb *ccb;
5698 	int retval = 0;
5699 	int t = -1;
5700 	int c;
5701 	u_char cmd, sc;
5702 
5703 	ccb = cam_getccb(device);
5704 
5705 	if (ccb == NULL) {
5706 		warnx("%s: error allocating ccb", __func__);
5707 		return (1);
5708 	}
5709 
5710 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5711 		switch (c) {
5712 		case 't':
5713 			t = atoi(optarg);
5714 			break;
5715 		default:
5716 			break;
5717 		}
5718 	}
5719 	if (strcmp(argv[1], "idle") == 0) {
5720 		if (t == -1)
5721 			cmd = ATA_IDLE_IMMEDIATE;
5722 		else
5723 			cmd = ATA_IDLE_CMD;
5724 	} else if (strcmp(argv[1], "standby") == 0) {
5725 		if (t == -1)
5726 			cmd = ATA_STANDBY_IMMEDIATE;
5727 		else
5728 			cmd = ATA_STANDBY_CMD;
5729 	} else {
5730 		cmd = ATA_SLEEP;
5731 		t = -1;
5732 	}
5733 
5734 	if (t < 0)
5735 		sc = 0;
5736 	else if (t <= (240 * 5))
5737 		sc = (t + 4) / 5;
5738 	else if (t <= (252 * 5))
5739 		/* special encoding for 21 minutes */
5740 		sc = 252;
5741 	else if (t <= (11 * 30 * 60))
5742 		sc = (t - 1) / (30 * 60) + 241;
5743 	else
5744 		sc = 253;
5745 
5746 	cam_fill_ataio(&ccb->ataio,
5747 		      retry_count,
5748 		      NULL,
5749 		      /*flags*/CAM_DIR_NONE,
5750 		      MSG_SIMPLE_Q_TAG,
5751 		      /*data_ptr*/NULL,
5752 		      /*dxfer_len*/0,
5753 		      timeout ? timeout : 30 * 1000);
5754 	ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
5755 
5756 	/* Disable freezing the device queue */
5757 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5758 
5759 	if (arglist & CAM_ARG_ERR_RECOVER)
5760 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5761 
5762 	if (cam_send_ccb(device, ccb) < 0) {
5763 		warn("error sending command");
5764 
5765 		if (arglist & CAM_ARG_VERBOSE)
5766 			cam_error_print(device, ccb, CAM_ESF_ALL,
5767 					CAM_EPF_ALL, stderr);
5768 
5769 		retval = 1;
5770 		goto bailout;
5771 	}
5772 
5773 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5774 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5775 		retval = 1;
5776 		goto bailout;
5777 	}
5778 bailout:
5779 	cam_freeccb(ccb);
5780 	return (retval);
5781 }
5782 
5783 #endif /* MINIMALISTIC */
5784 
5785 void
5786 usage(int printlong)
5787 {
5788 
5789 	fprintf(printlong ? stdout : stderr,
5790 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
5791 "        camcontrol devlist    [-v]\n"
5792 #ifndef MINIMALISTIC
5793 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
5794 "        camcontrol tur        [dev_id][generic args]\n"
5795 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
5796 "        camcontrol identify   [dev_id][generic args] [-v]\n"
5797 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
5798 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
5799 "                              [-q] [-s]\n"
5800 "        camcontrol start      [dev_id][generic args]\n"
5801 "        camcontrol stop       [dev_id][generic args]\n"
5802 "        camcontrol load       [dev_id][generic args]\n"
5803 "        camcontrol eject      [dev_id][generic args]\n"
5804 #endif /* MINIMALISTIC */
5805 "        camcontrol rescan     <all | bus[:target:lun]>\n"
5806 "        camcontrol reset      <all | bus[:target:lun]>\n"
5807 #ifndef MINIMALISTIC
5808 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
5809 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
5810 "                              [-P pagectl][-e | -b][-d]\n"
5811 "        camcontrol cmd        [dev_id][generic args]\n"
5812 "                              <-a cmd [args] | -c cmd [args]>\n"
5813 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
5814 "        camcontrol smpcmd     [dev_id][generic args]\n"
5815 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
5816 "        camcontrol smprg      [dev_id][generic args][-l]\n"
5817 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
5818 "                              [-o operation][-d name][-m rate][-M rate]\n"
5819 "                              [-T pp_timeout][-a enable|disable]\n"
5820 "                              [-A enable|disable][-s enable|disable]\n"
5821 "                              [-S enable|disable]\n"
5822 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
5823 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
5824 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
5825 "                              <all|bus[:target[:lun]]|off>\n"
5826 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
5827 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
5828 "                              [-D <enable|disable>][-M mode][-O offset]\n"
5829 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
5830 "                              [-U][-W bus_width]\n"
5831 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
5832 "        camcontrol idle       [dev_id][generic args][-t time]\n"
5833 "        camcontrol standby    [dev_id][generic args][-t time]\n"
5834 "        camcontrol sleep      [dev_id][generic args]\n"
5835 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
5836 #endif /* MINIMALISTIC */
5837 "        camcontrol help\n");
5838 	if (!printlong)
5839 		return;
5840 #ifndef MINIMALISTIC
5841 	fprintf(stdout,
5842 "Specify one of the following options:\n"
5843 "devlist     list all CAM devices\n"
5844 "periphlist  list all CAM peripheral drivers attached to a device\n"
5845 "tur         send a test unit ready to the named device\n"
5846 "inquiry     send a SCSI inquiry command to the named device\n"
5847 "identify    send a ATA identify command to the named device\n"
5848 "reportluns  send a SCSI report luns command to the device\n"
5849 "readcap     send a SCSI read capacity command to the device\n"
5850 "start       send a Start Unit command to the device\n"
5851 "stop        send a Stop Unit command to the device\n"
5852 "load        send a Start Unit command to the device with the load bit set\n"
5853 "eject       send a Stop Unit command to the device with the eject bit set\n"
5854 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
5855 "reset       reset all busses, the given bus, or bus:target:lun\n"
5856 "defects     read the defect list of the specified device\n"
5857 "modepage    display or edit (-e) the given mode page\n"
5858 "cmd         send the given SCSI command, may need -i or -o as well\n"
5859 "smpcmd      send the given SMP command, requires -o and -i\n"
5860 "smprg       send the SMP Report General command\n"
5861 "smppc       send the SMP PHY Control command, requires -p\n"
5862 "smpphylist  display phys attached to a SAS expander\n"
5863 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
5864 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
5865 "tags        report or set the number of transaction slots for a device\n"
5866 "negotiate   report or set device negotiation parameters\n"
5867 "format      send the SCSI FORMAT UNIT command to the named device\n"
5868 "idle        send the ATA IDLE command to the named device\n"
5869 "standby     send the ATA STANDBY command to the named device\n"
5870 "sleep       send the ATA SLEEP command to the named device\n"
5871 "fwdownload  program firmware of the named device with the given image"
5872 "help        this message\n"
5873 "Device Identifiers:\n"
5874 "bus:target        specify the bus and target, lun defaults to 0\n"
5875 "bus:target:lun    specify the bus, target and lun\n"
5876 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
5877 "Generic arguments:\n"
5878 "-v                be verbose, print out sense information\n"
5879 "-t timeout        command timeout in seconds, overrides default timeout\n"
5880 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
5881 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
5882 "-E                have the kernel attempt to perform SCSI error recovery\n"
5883 "-C count          specify the SCSI command retry count (needs -E to work)\n"
5884 "modepage arguments:\n"
5885 "-l                list all available mode pages\n"
5886 "-m page           specify the mode page to view or edit\n"
5887 "-e                edit the specified mode page\n"
5888 "-b                force view to binary mode\n"
5889 "-d                disable block descriptors for mode sense\n"
5890 "-P pgctl          page control field 0-3\n"
5891 "defects arguments:\n"
5892 "-f format         specify defect list format (block, bfi or phys)\n"
5893 "-G                get the grown defect list\n"
5894 "-P                get the permanent defect list\n"
5895 "inquiry arguments:\n"
5896 "-D                get the standard inquiry data\n"
5897 "-S                get the serial number\n"
5898 "-R                get the transfer rate, etc.\n"
5899 "reportluns arguments:\n"
5900 "-c                only report a count of available LUNs\n"
5901 "-l                only print out luns, and not a count\n"
5902 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
5903 "readcap arguments\n"
5904 "-b                only report the blocksize\n"
5905 "-h                human readable device size, base 2\n"
5906 "-H                human readable device size, base 10\n"
5907 "-N                print the number of blocks instead of last block\n"
5908 "-q                quiet, print numbers only\n"
5909 "-s                only report the last block/device size\n"
5910 "cmd arguments:\n"
5911 "-c cdb [args]     specify the SCSI CDB\n"
5912 "-i len fmt        specify input data and input data format\n"
5913 "-o len fmt [args] specify output data and output data fmt\n"
5914 "smpcmd arguments:\n"
5915 "-r len fmt [args] specify the SMP command to be sent\n"
5916 "-R len fmt [args] specify SMP response format\n"
5917 "smprg arguments:\n"
5918 "-l                specify the long response format\n"
5919 "smppc arguments:\n"
5920 "-p phy            specify the PHY to operate on\n"
5921 "-l                specify the long request/response format\n"
5922 "-o operation      specify the phy control operation\n"
5923 "-d name           set the attached device name\n"
5924 "-m rate           set the minimum physical link rate\n"
5925 "-M rate           set the maximum physical link rate\n"
5926 "-T pp_timeout     set the partial pathway timeout value\n"
5927 "-a enable|disable enable or disable SATA slumber\n"
5928 "-A enable|disable enable or disable SATA partial phy power\n"
5929 "-s enable|disable enable or disable SAS slumber\n"
5930 "-S enable|disable enable or disable SAS partial phy power\n"
5931 "smpphylist arguments:\n"
5932 "-l                specify the long response format\n"
5933 "-q                only print phys with attached devices\n"
5934 "smpmaninfo arguments:\n"
5935 "-l                specify the long response format\n"
5936 "debug arguments:\n"
5937 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
5938 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
5939 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
5940 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
5941 "tags arguments:\n"
5942 "-N tags           specify the number of tags to use for this device\n"
5943 "-q                be quiet, don't report the number of tags\n"
5944 "-v                report a number of tag-related parameters\n"
5945 "negotiate arguments:\n"
5946 "-a                send a test unit ready after negotiation\n"
5947 "-c                report/set current negotiation settings\n"
5948 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
5949 "-M mode           set ATA mode\n"
5950 "-O offset         set command delay offset\n"
5951 "-q                be quiet, don't report anything\n"
5952 "-R syncrate       synchronization rate in MHz\n"
5953 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
5954 "-U                report/set user negotiation settings\n"
5955 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
5956 "-v                also print a Path Inquiry CCB for the controller\n"
5957 "format arguments:\n"
5958 "-q                be quiet, don't print status messages\n"
5959 "-r                run in report only mode\n"
5960 "-w                don't send immediate format command\n"
5961 "-y                don't ask any questions\n"
5962 "idle/standby arguments:\n"
5963 "-t <arg>          number of seconds before respective state.\n"
5964 "fwdownload arguments:\n"
5965 "-f fw_image       path to firmware image file\n"
5966 "-y                don't ask any questions\n"
5967 "-s                run in simulation mode\n"
5968 "-v                print info for every firmware segment sent to device\n");
5969 #endif /* MINIMALISTIC */
5970 }
5971 
5972 int
5973 main(int argc, char **argv)
5974 {
5975 	int c;
5976 	char *device = NULL;
5977 	int unit = 0;
5978 	struct cam_device *cam_dev = NULL;
5979 	int timeout = 0, retry_count = 1;
5980 	camcontrol_optret optreturn;
5981 	char *tstr;
5982 	const char *mainopt = "C:En:t:u:v";
5983 	const char *subopt = NULL;
5984 	char combinedopt[256];
5985 	int error = 0, optstart = 2;
5986 	int devopen = 1;
5987 #ifndef MINIMALISTIC
5988 	int bus, target, lun;
5989 #endif /* MINIMALISTIC */
5990 
5991 	cmdlist = CAM_CMD_NONE;
5992 	arglist = CAM_ARG_NONE;
5993 
5994 	if (argc < 2) {
5995 		usage(0);
5996 		exit(1);
5997 	}
5998 
5999 	/*
6000 	 * Get the base option.
6001 	 */
6002 	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
6003 
6004 	if (optreturn == CC_OR_AMBIGUOUS) {
6005 		warnx("ambiguous option %s", argv[1]);
6006 		usage(0);
6007 		exit(1);
6008 	} else if (optreturn == CC_OR_NOT_FOUND) {
6009 		warnx("option %s not found", argv[1]);
6010 		usage(0);
6011 		exit(1);
6012 	}
6013 
6014 	/*
6015 	 * Ahh, getopt(3) is a pain.
6016 	 *
6017 	 * This is a gross hack.  There really aren't many other good
6018 	 * options (excuse the pun) for parsing options in a situation like
6019 	 * this.  getopt is kinda braindead, so you end up having to run
6020 	 * through the options twice, and give each invocation of getopt
6021 	 * the option string for the other invocation.
6022 	 *
6023 	 * You would think that you could just have two groups of options.
6024 	 * The first group would get parsed by the first invocation of
6025 	 * getopt, and the second group would get parsed by the second
6026 	 * invocation of getopt.  It doesn't quite work out that way.  When
6027 	 * the first invocation of getopt finishes, it leaves optind pointing
6028 	 * to the argument _after_ the first argument in the second group.
6029 	 * So when the second invocation of getopt comes around, it doesn't
6030 	 * recognize the first argument it gets and then bails out.
6031 	 *
6032 	 * A nice alternative would be to have a flag for getopt that says
6033 	 * "just keep parsing arguments even when you encounter an unknown
6034 	 * argument", but there isn't one.  So there's no real clean way to
6035 	 * easily parse two sets of arguments without having one invocation
6036 	 * of getopt know about the other.
6037 	 *
6038 	 * Without this hack, the first invocation of getopt would work as
6039 	 * long as the generic arguments are first, but the second invocation
6040 	 * (in the subfunction) would fail in one of two ways.  In the case
6041 	 * where you don't set optreset, it would fail because optind may be
6042 	 * pointing to the argument after the one it should be pointing at.
6043 	 * In the case where you do set optreset, and reset optind, it would
6044 	 * fail because getopt would run into the first set of options, which
6045 	 * it doesn't understand.
6046 	 *
6047 	 * All of this would "sort of" work if you could somehow figure out
6048 	 * whether optind had been incremented one option too far.  The
6049 	 * mechanics of that, however, are more daunting than just giving
6050 	 * both invocations all of the expect options for either invocation.
6051 	 *
6052 	 * Needless to say, I wouldn't mind if someone invented a better
6053 	 * (non-GPL!) command line parsing interface than getopt.  I
6054 	 * wouldn't mind if someone added more knobs to getopt to make it
6055 	 * work better.  Who knows, I may talk myself into doing it someday,
6056 	 * if the standards weenies let me.  As it is, it just leads to
6057 	 * hackery like this and causes people to avoid it in some cases.
6058 	 *
6059 	 * KDM, September 8th, 1998
6060 	 */
6061 	if (subopt != NULL)
6062 		sprintf(combinedopt, "%s%s", mainopt, subopt);
6063 	else
6064 		sprintf(combinedopt, "%s", mainopt);
6065 
6066 	/*
6067 	 * For these options we do not parse optional device arguments and
6068 	 * we do not open a passthrough device.
6069 	 */
6070 	if ((cmdlist == CAM_CMD_RESCAN)
6071 	 || (cmdlist == CAM_CMD_RESET)
6072 	 || (cmdlist == CAM_CMD_DEVTREE)
6073 	 || (cmdlist == CAM_CMD_USAGE)
6074 	 || (cmdlist == CAM_CMD_DEBUG))
6075 		devopen = 0;
6076 
6077 #ifndef MINIMALISTIC
6078 	if ((devopen == 1)
6079 	 && (argc > 2 && argv[2][0] != '-')) {
6080 		char name[30];
6081 		int rv;
6082 
6083 		if (isdigit(argv[2][0])) {
6084 			/* device specified as bus:target[:lun] */
6085 			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
6086 			if (rv < 2)
6087 				errx(1, "numeric device specification must "
6088 				     "be either bus:target, or "
6089 				     "bus:target:lun");
6090 			/* default to 0 if lun was not specified */
6091 			if ((arglist & CAM_ARG_LUN) == 0) {
6092 				lun = 0;
6093 				arglist |= CAM_ARG_LUN;
6094 			}
6095 			optstart++;
6096 		} else {
6097 			if (cam_get_device(argv[2], name, sizeof name, &unit)
6098 			    == -1)
6099 				errx(1, "%s", cam_errbuf);
6100 			device = strdup(name);
6101 			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
6102 			optstart++;
6103 		}
6104 	}
6105 #endif /* MINIMALISTIC */
6106 	/*
6107 	 * Start getopt processing at argv[2/3], since we've already
6108 	 * accepted argv[1..2] as the command name, and as a possible
6109 	 * device name.
6110 	 */
6111 	optind = optstart;
6112 
6113 	/*
6114 	 * Now we run through the argument list looking for generic
6115 	 * options, and ignoring options that possibly belong to
6116 	 * subfunctions.
6117 	 */
6118 	while ((c = getopt(argc, argv, combinedopt))!= -1){
6119 		switch(c) {
6120 			case 'C':
6121 				retry_count = strtol(optarg, NULL, 0);
6122 				if (retry_count < 0)
6123 					errx(1, "retry count %d is < 0",
6124 					     retry_count);
6125 				arglist |= CAM_ARG_RETRIES;
6126 				break;
6127 			case 'E':
6128 				arglist |= CAM_ARG_ERR_RECOVER;
6129 				break;
6130 			case 'n':
6131 				arglist |= CAM_ARG_DEVICE;
6132 				tstr = optarg;
6133 				while (isspace(*tstr) && (*tstr != '\0'))
6134 					tstr++;
6135 				device = (char *)strdup(tstr);
6136 				break;
6137 			case 't':
6138 				timeout = strtol(optarg, NULL, 0);
6139 				if (timeout < 0)
6140 					errx(1, "invalid timeout %d", timeout);
6141 				/* Convert the timeout from seconds to ms */
6142 				timeout *= 1000;
6143 				arglist |= CAM_ARG_TIMEOUT;
6144 				break;
6145 			case 'u':
6146 				arglist |= CAM_ARG_UNIT;
6147 				unit = strtol(optarg, NULL, 0);
6148 				break;
6149 			case 'v':
6150 				arglist |= CAM_ARG_VERBOSE;
6151 				break;
6152 			default:
6153 				break;
6154 		}
6155 	}
6156 
6157 #ifndef MINIMALISTIC
6158 	/*
6159 	 * For most commands we'll want to open the passthrough device
6160 	 * associated with the specified device.  In the case of the rescan
6161 	 * commands, we don't use a passthrough device at all, just the
6162 	 * transport layer device.
6163 	 */
6164 	if (devopen == 1) {
6165 		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
6166 		 && (((arglist & CAM_ARG_DEVICE) == 0)
6167 		  || ((arglist & CAM_ARG_UNIT) == 0))) {
6168 			errx(1, "subcommand \"%s\" requires a valid device "
6169 			     "identifier", argv[1]);
6170 		}
6171 
6172 		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
6173 				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
6174 				cam_open_spec_device(device,unit,O_RDWR,NULL)))
6175 		     == NULL)
6176 			errx(1,"%s", cam_errbuf);
6177 	}
6178 #endif /* MINIMALISTIC */
6179 
6180 	/*
6181 	 * Reset optind to 2, and reset getopt, so these routines can parse
6182 	 * the arguments again.
6183 	 */
6184 	optind = optstart;
6185 	optreset = 1;
6186 
6187 	switch(cmdlist) {
6188 #ifndef MINIMALISTIC
6189 		case CAM_CMD_DEVLIST:
6190 			error = getdevlist(cam_dev);
6191 			break;
6192 #endif /* MINIMALISTIC */
6193 		case CAM_CMD_DEVTREE:
6194 			error = getdevtree();
6195 			break;
6196 #ifndef MINIMALISTIC
6197 		case CAM_CMD_TUR:
6198 			error = testunitready(cam_dev, retry_count, timeout, 0);
6199 			break;
6200 		case CAM_CMD_INQUIRY:
6201 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
6202 					      retry_count, timeout);
6203 			break;
6204 		case CAM_CMD_IDENTIFY:
6205 			error = ataidentify(cam_dev, retry_count, timeout);
6206 			break;
6207 		case CAM_CMD_STARTSTOP:
6208 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
6209 					  arglist & CAM_ARG_EJECT, retry_count,
6210 					  timeout);
6211 			break;
6212 #endif /* MINIMALISTIC */
6213 		case CAM_CMD_RESCAN:
6214 			error = dorescan_or_reset(argc, argv, 1);
6215 			break;
6216 		case CAM_CMD_RESET:
6217 			error = dorescan_or_reset(argc, argv, 0);
6218 			break;
6219 #ifndef MINIMALISTIC
6220 		case CAM_CMD_READ_DEFECTS:
6221 			error = readdefects(cam_dev, argc, argv, combinedopt,
6222 					    retry_count, timeout);
6223 			break;
6224 		case CAM_CMD_MODE_PAGE:
6225 			modepage(cam_dev, argc, argv, combinedopt,
6226 				 retry_count, timeout);
6227 			break;
6228 		case CAM_CMD_SCSI_CMD:
6229 			error = scsicmd(cam_dev, argc, argv, combinedopt,
6230 					retry_count, timeout);
6231 			break;
6232 		case CAM_CMD_SMP_CMD:
6233 			error = smpcmd(cam_dev, argc, argv, combinedopt,
6234 				       retry_count, timeout);
6235 			break;
6236 		case CAM_CMD_SMP_RG:
6237 			error = smpreportgeneral(cam_dev, argc, argv,
6238 						 combinedopt, retry_count,
6239 						 timeout);
6240 			break;
6241 		case CAM_CMD_SMP_PC:
6242 			error = smpphycontrol(cam_dev, argc, argv, combinedopt,
6243 					      retry_count, timeout);
6244 			break;
6245 		case CAM_CMD_SMP_PHYLIST:
6246 			error = smpphylist(cam_dev, argc, argv, combinedopt,
6247 					   retry_count, timeout);
6248 			break;
6249 		case CAM_CMD_SMP_MANINFO:
6250 			error = smpmaninfo(cam_dev, argc, argv, combinedopt,
6251 					   retry_count, timeout);
6252 			break;
6253 		case CAM_CMD_DEBUG:
6254 			error = camdebug(argc, argv, combinedopt);
6255 			break;
6256 		case CAM_CMD_TAG:
6257 			error = tagcontrol(cam_dev, argc, argv, combinedopt);
6258 			break;
6259 		case CAM_CMD_RATE:
6260 			error = ratecontrol(cam_dev, retry_count, timeout,
6261 					    argc, argv, combinedopt);
6262 			break;
6263 		case CAM_CMD_FORMAT:
6264 			error = scsiformat(cam_dev, argc, argv,
6265 					   combinedopt, retry_count, timeout);
6266 			break;
6267 		case CAM_CMD_REPORTLUNS:
6268 			error = scsireportluns(cam_dev, argc, argv,
6269 					       combinedopt, retry_count,
6270 					       timeout);
6271 			break;
6272 		case CAM_CMD_READCAP:
6273 			error = scsireadcapacity(cam_dev, argc, argv,
6274 						 combinedopt, retry_count,
6275 						 timeout);
6276 			break;
6277 		case CAM_CMD_IDLE:
6278 		case CAM_CMD_STANDBY:
6279 		case CAM_CMD_SLEEP:
6280 			error = atapm(cam_dev, argc, argv,
6281 						 combinedopt, retry_count,
6282 						 timeout);
6283 			break;
6284 		case CAM_CMD_DOWNLOAD_FW:
6285 			error = fwdownload(cam_dev, argc, argv, combinedopt,
6286 			    arglist & CAM_ARG_VERBOSE, retry_count, timeout,
6287 			    get_disk_type(cam_dev));
6288 			break;
6289 #endif /* MINIMALISTIC */
6290 		case CAM_CMD_USAGE:
6291 			usage(1);
6292 			break;
6293 		default:
6294 			usage(0);
6295 			error = 1;
6296 			break;
6297 	}
6298 
6299 	if (cam_dev != NULL)
6300 		cam_close_device(cam_dev);
6301 
6302 	exit(error);
6303 }
6304