xref: /freebsd/sbin/camcontrol/camcontrol.c (revision 788ca347b816afd83b2885e0c79aeeb88649b2ab)
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/stat.h>
36 #include <sys/endian.h>
37 #include <sys/sbuf.h>
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <inttypes.h>
44 #include <limits.h>
45 #include <fcntl.h>
46 #include <ctype.h>
47 #include <err.h>
48 #include <libutil.h>
49 #ifndef MINIMALISTIC
50 #include <limits.h>
51 #include <inttypes.h>
52 #endif
53 
54 #include <cam/cam.h>
55 #include <cam/cam_debug.h>
56 #include <cam/cam_ccb.h>
57 #include <cam/scsi/scsi_all.h>
58 #include <cam/scsi/scsi_da.h>
59 #include <cam/scsi/scsi_pass.h>
60 #include <cam/scsi/scsi_message.h>
61 #include <cam/scsi/smp_all.h>
62 #include <cam/ata/ata_all.h>
63 #include <camlib.h>
64 #include "camcontrol.h"
65 
66 typedef enum {
67 	CAM_CMD_NONE		= 0x00000000,
68 	CAM_CMD_DEVLIST		= 0x00000001,
69 	CAM_CMD_TUR		= 0x00000002,
70 	CAM_CMD_INQUIRY		= 0x00000003,
71 	CAM_CMD_STARTSTOP	= 0x00000004,
72 	CAM_CMD_RESCAN		= 0x00000005,
73 	CAM_CMD_READ_DEFECTS	= 0x00000006,
74 	CAM_CMD_MODE_PAGE	= 0x00000007,
75 	CAM_CMD_SCSI_CMD	= 0x00000008,
76 	CAM_CMD_DEVTREE		= 0x00000009,
77 	CAM_CMD_USAGE		= 0x0000000a,
78 	CAM_CMD_DEBUG		= 0x0000000b,
79 	CAM_CMD_RESET		= 0x0000000c,
80 	CAM_CMD_FORMAT		= 0x0000000d,
81 	CAM_CMD_TAG		= 0x0000000e,
82 	CAM_CMD_RATE		= 0x0000000f,
83 	CAM_CMD_DETACH		= 0x00000010,
84 	CAM_CMD_REPORTLUNS	= 0x00000011,
85 	CAM_CMD_READCAP		= 0x00000012,
86 	CAM_CMD_IDENTIFY	= 0x00000013,
87 	CAM_CMD_IDLE		= 0x00000014,
88 	CAM_CMD_STANDBY		= 0x00000015,
89 	CAM_CMD_SLEEP		= 0x00000016,
90 	CAM_CMD_SMP_CMD		= 0x00000017,
91 	CAM_CMD_SMP_RG		= 0x00000018,
92 	CAM_CMD_SMP_PC		= 0x00000019,
93 	CAM_CMD_SMP_PHYLIST	= 0x0000001a,
94 	CAM_CMD_SMP_MANINFO	= 0x0000001b,
95 	CAM_CMD_DOWNLOAD_FW	= 0x0000001c,
96 	CAM_CMD_SECURITY	= 0x0000001d,
97 	CAM_CMD_HPA		= 0x0000001e,
98 	CAM_CMD_SANITIZE	= 0x0000001f,
99 	CAM_CMD_PERSIST		= 0x00000020,
100 	CAM_CMD_APM		= 0x00000021,
101 	CAM_CMD_AAM		= 0x00000022
102 } cam_cmdmask;
103 
104 typedef enum {
105 	CAM_ARG_NONE		= 0x00000000,
106 	CAM_ARG_VERBOSE		= 0x00000001,
107 	CAM_ARG_DEVICE		= 0x00000002,
108 	CAM_ARG_BUS		= 0x00000004,
109 	CAM_ARG_TARGET		= 0x00000008,
110 	CAM_ARG_LUN		= 0x00000010,
111 	CAM_ARG_EJECT		= 0x00000020,
112 	CAM_ARG_UNIT		= 0x00000040,
113 	CAM_ARG_FORMAT_BLOCK	= 0x00000080,
114 	CAM_ARG_FORMAT_BFI	= 0x00000100,
115 	CAM_ARG_FORMAT_PHYS	= 0x00000200,
116 	CAM_ARG_PLIST		= 0x00000400,
117 	CAM_ARG_GLIST		= 0x00000800,
118 	CAM_ARG_GET_SERIAL	= 0x00001000,
119 	CAM_ARG_GET_STDINQ	= 0x00002000,
120 	CAM_ARG_GET_XFERRATE	= 0x00004000,
121 	CAM_ARG_INQ_MASK	= 0x00007000,
122 	CAM_ARG_MODE_EDIT	= 0x00008000,
123 	CAM_ARG_PAGE_CNTL	= 0x00010000,
124 	CAM_ARG_TIMEOUT		= 0x00020000,
125 	CAM_ARG_CMD_IN		= 0x00040000,
126 	CAM_ARG_CMD_OUT		= 0x00080000,
127 	CAM_ARG_DBD		= 0x00100000,
128 	CAM_ARG_ERR_RECOVER	= 0x00200000,
129 	CAM_ARG_RETRIES		= 0x00400000,
130 	CAM_ARG_START_UNIT	= 0x00800000,
131 	CAM_ARG_DEBUG_INFO	= 0x01000000,
132 	CAM_ARG_DEBUG_TRACE	= 0x02000000,
133 	CAM_ARG_DEBUG_SUBTRACE	= 0x04000000,
134 	CAM_ARG_DEBUG_CDB	= 0x08000000,
135 	CAM_ARG_DEBUG_XPT	= 0x10000000,
136 	CAM_ARG_DEBUG_PERIPH	= 0x20000000,
137 	CAM_ARG_DEBUG_PROBE	= 0x40000000,
138 } cam_argmask;
139 
140 struct camcontrol_opts {
141 	const char	*optname;
142 	uint32_t	cmdnum;
143 	cam_argmask	argnum;
144 	const char	*subopt;
145 };
146 
147 #ifndef MINIMALISTIC
148 struct ata_res_pass16 {
149 	u_int16_t reserved[5];
150 	u_int8_t flags;
151 	u_int8_t error;
152 	u_int8_t sector_count_exp;
153 	u_int8_t sector_count;
154 	u_int8_t lba_low_exp;
155 	u_int8_t lba_low;
156 	u_int8_t lba_mid_exp;
157 	u_int8_t lba_mid;
158 	u_int8_t lba_high_exp;
159 	u_int8_t lba_high;
160 	u_int8_t device;
161 	u_int8_t status;
162 };
163 
164 struct ata_set_max_pwd
165 {
166 	u_int16_t reserved1;
167 	u_int8_t password[32];
168 	u_int16_t reserved2[239];
169 };
170 
171 static const char scsicmd_opts[] = "a:c:dfi:o:r";
172 static const char readdefect_opts[] = "f:GPqsS:X";
173 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
174 static const char smprg_opts[] = "l";
175 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
176 static const char smpphylist_opts[] = "lq";
177 static char pwd_opt;
178 #endif
179 
180 static struct camcontrol_opts option_table[] = {
181 #ifndef MINIMALISTIC
182 	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
183 	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
184 	{"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
185 	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
186 	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
187 	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
188 	{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
189 	{"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
190 	{"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
191 #endif /* MINIMALISTIC */
192 	{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
193 	{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
194 #ifndef MINIMALISTIC
195 	{"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
196 	{"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
197 	{"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
198 	{"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
199 	{"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
200 	{"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
201 	{"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
202 	{"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
203 	{"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
204 	{"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
205 	{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
206 	{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
207 #endif /* MINIMALISTIC */
208 	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, "-b"},
209 #ifndef MINIMALISTIC
210 	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
211 	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
212 	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
213 	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
214 	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
215 	{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
216 	{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
217 	{"sanitize", CAM_CMD_SANITIZE, CAM_ARG_NONE, "a:c:IP:qrUwy"},
218 	{"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
219 	{"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
220 	{"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
221 	{"apm", CAM_CMD_APM, CAM_ARG_NONE, "l:"},
222 	{"aam", CAM_CMD_AAM, CAM_ARG_NONE, "l:"},
223 	{"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:ys"},
224 	{"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"},
225 	{"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"},
226 	{"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"},
227 #endif /* MINIMALISTIC */
228 	{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
229 	{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
230 	{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
231 	{NULL, 0, 0, NULL}
232 };
233 
234 struct cam_devitem {
235 	struct device_match_result dev_match;
236 	int num_periphs;
237 	struct periph_match_result *periph_matches;
238 	struct scsi_vpd_device_id *device_id;
239 	int device_id_len;
240 	STAILQ_ENTRY(cam_devitem) links;
241 };
242 
243 struct cam_devlist {
244 	STAILQ_HEAD(, cam_devitem) dev_queue;
245 	path_id_t path_id;
246 };
247 
248 static cam_cmdmask cmdlist;
249 static cam_argmask arglist;
250 
251 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
252 			    uint32_t *cmdnum, cam_argmask *argnum,
253 			    const char **subopt);
254 #ifndef MINIMALISTIC
255 static int getdevlist(struct cam_device *device);
256 #endif /* MINIMALISTIC */
257 static int getdevtree(int argc, char **argv, char *combinedopt);
258 #ifndef MINIMALISTIC
259 static int testunitready(struct cam_device *device, int retry_count,
260 			 int timeout, int quiet);
261 static int scsistart(struct cam_device *device, int startstop, int loadeject,
262 		     int retry_count, int timeout);
263 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
264 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
265 static int camxferrate(struct cam_device *device);
266 #endif /* MINIMALISTIC */
267 static int parse_btl(char *tstr, path_id_t *bus, target_id_t *target,
268 		     lun_id_t *lun, cam_argmask *arglst);
269 static int dorescan_or_reset(int argc, char **argv, int rescan);
270 static int rescan_or_reset_bus(path_id_t bus, int rescan);
271 static int scanlun_or_reset_dev(path_id_t bus, target_id_t target,
272     lun_id_t lun, int scan);
273 #ifndef MINIMALISTIC
274 static int readdefects(struct cam_device *device, int argc, char **argv,
275 		       char *combinedopt, int retry_count, int timeout);
276 static void modepage(struct cam_device *device, int argc, char **argv,
277 		     char *combinedopt, int retry_count, int timeout);
278 static int scsicmd(struct cam_device *device, int argc, char **argv,
279 		   char *combinedopt, int retry_count, int timeout);
280 static int smpcmd(struct cam_device *device, int argc, char **argv,
281 		  char *combinedopt, int retry_count, int timeout);
282 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
283 			    char *combinedopt, int retry_count, int timeout);
284 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
285 			 char *combinedopt, int retry_count, int timeout);
286 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
287 		      char *combinedopt, int retry_count, int timeout);
288 static int getdevid(struct cam_devitem *item);
289 static int buildbusdevlist(struct cam_devlist *devlist);
290 static void freebusdevlist(struct cam_devlist *devlist);
291 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
292 					 uint64_t sasaddr);
293 static int smpphylist(struct cam_device *device, int argc, char **argv,
294 		      char *combinedopt, int retry_count, int timeout);
295 static int tagcontrol(struct cam_device *device, int argc, char **argv,
296 		      char *combinedopt);
297 static void cts_print(struct cam_device *device,
298 		      struct ccb_trans_settings *cts);
299 static void cpi_print(struct ccb_pathinq *cpi);
300 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
301 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
302 static int get_print_cts(struct cam_device *device, int user_settings,
303 			 int quiet, struct ccb_trans_settings *cts);
304 static int ratecontrol(struct cam_device *device, int retry_count,
305 		       int timeout, int argc, char **argv, char *combinedopt);
306 static int scsiformat(struct cam_device *device, int argc, char **argv,
307 		      char *combinedopt, int retry_count, int timeout);
308 static int scsisanitize(struct cam_device *device, int argc, char **argv,
309 			char *combinedopt, int retry_count, int timeout);
310 static int scsireportluns(struct cam_device *device, int argc, char **argv,
311 			  char *combinedopt, int retry_count, int timeout);
312 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
313 			    char *combinedopt, int retry_count, int timeout);
314 static int atapm(struct cam_device *device, int argc, char **argv,
315 		 char *combinedopt, int retry_count, int timeout);
316 static int atasecurity(struct cam_device *device, int retry_count, int timeout,
317 		       int argc, char **argv, char *combinedopt);
318 static int atahpa(struct cam_device *device, int retry_count, int timeout,
319 		  int argc, char **argv, char *combinedopt);
320 
321 #endif /* MINIMALISTIC */
322 #ifndef min
323 #define min(a,b) (((a)<(b))?(a):(b))
324 #endif
325 #ifndef max
326 #define max(a,b) (((a)>(b))?(a):(b))
327 #endif
328 
329 camcontrol_optret
330 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
331 	  cam_argmask *argnum, const char **subopt)
332 {
333 	struct camcontrol_opts *opts;
334 	int num_matches = 0;
335 
336 	for (opts = table; (opts != NULL) && (opts->optname != NULL);
337 	     opts++) {
338 		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
339 			*cmdnum = opts->cmdnum;
340 			*argnum = opts->argnum;
341 			*subopt = opts->subopt;
342 			if (++num_matches > 1)
343 				return(CC_OR_AMBIGUOUS);
344 		}
345 	}
346 
347 	if (num_matches > 0)
348 		return(CC_OR_FOUND);
349 	else
350 		return(CC_OR_NOT_FOUND);
351 }
352 
353 #ifndef MINIMALISTIC
354 static int
355 getdevlist(struct cam_device *device)
356 {
357 	union ccb *ccb;
358 	char status[32];
359 	int error = 0;
360 
361 	ccb = cam_getccb(device);
362 
363 	ccb->ccb_h.func_code = XPT_GDEVLIST;
364 	ccb->ccb_h.flags = CAM_DIR_NONE;
365 	ccb->ccb_h.retry_count = 1;
366 	ccb->cgdl.index = 0;
367 	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
368 	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
369 		if (cam_send_ccb(device, ccb) < 0) {
370 			perror("error getting device list");
371 			cam_freeccb(ccb);
372 			return(1);
373 		}
374 
375 		status[0] = '\0';
376 
377 		switch (ccb->cgdl.status) {
378 			case CAM_GDEVLIST_MORE_DEVS:
379 				strcpy(status, "MORE");
380 				break;
381 			case CAM_GDEVLIST_LAST_DEVICE:
382 				strcpy(status, "LAST");
383 				break;
384 			case CAM_GDEVLIST_LIST_CHANGED:
385 				strcpy(status, "CHANGED");
386 				break;
387 			case CAM_GDEVLIST_ERROR:
388 				strcpy(status, "ERROR");
389 				error = 1;
390 				break;
391 		}
392 
393 		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
394 			ccb->cgdl.periph_name,
395 			ccb->cgdl.unit_number,
396 			ccb->cgdl.generation,
397 			ccb->cgdl.index,
398 			status);
399 
400 		/*
401 		 * If the list has changed, we need to start over from the
402 		 * beginning.
403 		 */
404 		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
405 			ccb->cgdl.index = 0;
406 	}
407 
408 	cam_freeccb(ccb);
409 
410 	return(error);
411 }
412 #endif /* MINIMALISTIC */
413 
414 static int
415 getdevtree(int argc, char **argv, char *combinedopt)
416 {
417 	union ccb ccb;
418 	int bufsize, fd;
419 	unsigned int i;
420 	int need_close = 0;
421 	int error = 0;
422 	int skip_device = 0;
423 	int busonly = 0;
424 	int c;
425 
426 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
427 		switch(c) {
428 		case 'b':
429 			if ((arglist & CAM_ARG_VERBOSE) == 0)
430 				busonly = 1;
431 			break;
432 		default:
433 			break;
434 		}
435 	}
436 
437 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
438 		warn("couldn't open %s", XPT_DEVICE);
439 		return(1);
440 	}
441 
442 	bzero(&ccb, sizeof(union ccb));
443 
444 	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
445 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
446 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
447 
448 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
449 	bufsize = sizeof(struct dev_match_result) * 100;
450 	ccb.cdm.match_buf_len = bufsize;
451 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
452 	if (ccb.cdm.matches == NULL) {
453 		warnx("can't malloc memory for matches");
454 		close(fd);
455 		return(1);
456 	}
457 	ccb.cdm.num_matches = 0;
458 
459 	/*
460 	 * We fetch all nodes, since we display most of them in the default
461 	 * case, and all in the verbose case.
462 	 */
463 	ccb.cdm.num_patterns = 0;
464 	ccb.cdm.pattern_buf_len = 0;
465 
466 	/*
467 	 * We do the ioctl multiple times if necessary, in case there are
468 	 * more than 100 nodes in the EDT.
469 	 */
470 	do {
471 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
472 			warn("error sending CAMIOCOMMAND ioctl");
473 			error = 1;
474 			break;
475 		}
476 
477 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
478 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
479 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
480 			warnx("got CAM error %#x, CDM error %d\n",
481 			      ccb.ccb_h.status, ccb.cdm.status);
482 			error = 1;
483 			break;
484 		}
485 
486 		for (i = 0; i < ccb.cdm.num_matches; i++) {
487 			switch (ccb.cdm.matches[i].type) {
488 			case DEV_MATCH_BUS: {
489 				struct bus_match_result *bus_result;
490 
491 				/*
492 				 * Only print the bus information if the
493 				 * user turns on the verbose flag.
494 				 */
495 				if ((busonly == 0) &&
496 				    (arglist & CAM_ARG_VERBOSE) == 0)
497 					break;
498 
499 				bus_result =
500 					&ccb.cdm.matches[i].result.bus_result;
501 
502 				if (need_close) {
503 					fprintf(stdout, ")\n");
504 					need_close = 0;
505 				}
506 
507 				fprintf(stdout, "scbus%d on %s%d bus %d%s\n",
508 					bus_result->path_id,
509 					bus_result->dev_name,
510 					bus_result->unit_number,
511 					bus_result->bus_id,
512 					(busonly ? "" : ":"));
513 				break;
514 			}
515 			case DEV_MATCH_DEVICE: {
516 				struct device_match_result *dev_result;
517 				char vendor[16], product[48], revision[16];
518 				char fw[5], tmpstr[256];
519 
520 				if (busonly == 1)
521 					break;
522 
523 				dev_result =
524 				     &ccb.cdm.matches[i].result.device_result;
525 
526 				if ((dev_result->flags
527 				     & DEV_RESULT_UNCONFIGURED)
528 				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
529 					skip_device = 1;
530 					break;
531 				} else
532 					skip_device = 0;
533 
534 				if (dev_result->protocol == PROTO_SCSI) {
535 				    cam_strvis(vendor, dev_result->inq_data.vendor,
536 					   sizeof(dev_result->inq_data.vendor),
537 					   sizeof(vendor));
538 				    cam_strvis(product,
539 					   dev_result->inq_data.product,
540 					   sizeof(dev_result->inq_data.product),
541 					   sizeof(product));
542 				    cam_strvis(revision,
543 					   dev_result->inq_data.revision,
544 					  sizeof(dev_result->inq_data.revision),
545 					   sizeof(revision));
546 				    sprintf(tmpstr, "<%s %s %s>", vendor, product,
547 					revision);
548 				} else if (dev_result->protocol == PROTO_ATA ||
549 				    dev_result->protocol == PROTO_SATAPM) {
550 				    cam_strvis(product,
551 					   dev_result->ident_data.model,
552 					   sizeof(dev_result->ident_data.model),
553 					   sizeof(product));
554 				    cam_strvis(revision,
555 					   dev_result->ident_data.revision,
556 					  sizeof(dev_result->ident_data.revision),
557 					   sizeof(revision));
558 				    sprintf(tmpstr, "<%s %s>", product,
559 					revision);
560 				} else if (dev_result->protocol == PROTO_SEMB) {
561 					struct sep_identify_data *sid;
562 
563 					sid = (struct sep_identify_data *)
564 					    &dev_result->ident_data;
565 					cam_strvis(vendor, sid->vendor_id,
566 					    sizeof(sid->vendor_id),
567 					    sizeof(vendor));
568 					cam_strvis(product, sid->product_id,
569 					    sizeof(sid->product_id),
570 					    sizeof(product));
571 					cam_strvis(revision, sid->product_rev,
572 					    sizeof(sid->product_rev),
573 					    sizeof(revision));
574 					cam_strvis(fw, sid->firmware_rev,
575 					    sizeof(sid->firmware_rev),
576 					    sizeof(fw));
577 					sprintf(tmpstr, "<%s %s %s %s>",
578 					    vendor, product, revision, fw);
579 				} else {
580 				    sprintf(tmpstr, "<>");
581 				}
582 				if (need_close) {
583 					fprintf(stdout, ")\n");
584 					need_close = 0;
585 				}
586 
587 				fprintf(stdout, "%-33s  at scbus%d "
588 					"target %d lun %jx (",
589 					tmpstr,
590 					dev_result->path_id,
591 					dev_result->target_id,
592 					(uintmax_t)dev_result->target_lun);
593 
594 				need_close = 1;
595 
596 				break;
597 			}
598 			case DEV_MATCH_PERIPH: {
599 				struct periph_match_result *periph_result;
600 
601 				periph_result =
602 				      &ccb.cdm.matches[i].result.periph_result;
603 
604 				if (busonly || skip_device != 0)
605 					break;
606 
607 				if (need_close > 1)
608 					fprintf(stdout, ",");
609 
610 				fprintf(stdout, "%s%d",
611 					periph_result->periph_name,
612 					periph_result->unit_number);
613 
614 				need_close++;
615 				break;
616 			}
617 			default:
618 				fprintf(stdout, "unknown match type\n");
619 				break;
620 			}
621 		}
622 
623 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
624 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
625 
626 	if (need_close)
627 		fprintf(stdout, ")\n");
628 
629 	close(fd);
630 
631 	return(error);
632 }
633 
634 #ifndef MINIMALISTIC
635 static int
636 testunitready(struct cam_device *device, int retry_count, int timeout,
637 	      int quiet)
638 {
639 	int error = 0;
640 	union ccb *ccb;
641 
642 	ccb = cam_getccb(device);
643 
644 	scsi_test_unit_ready(&ccb->csio,
645 			     /* retries */ retry_count,
646 			     /* cbfcnp */ NULL,
647 			     /* tag_action */ MSG_SIMPLE_Q_TAG,
648 			     /* sense_len */ SSD_FULL_SIZE,
649 			     /* timeout */ timeout ? timeout : 5000);
650 
651 	/* Disable freezing the device queue */
652 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
653 
654 	if (arglist & CAM_ARG_ERR_RECOVER)
655 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
656 
657 	if (cam_send_ccb(device, ccb) < 0) {
658 		if (quiet == 0)
659 			perror("error sending test unit ready");
660 
661 		if (arglist & CAM_ARG_VERBOSE) {
662 			cam_error_print(device, ccb, CAM_ESF_ALL,
663 					CAM_EPF_ALL, stderr);
664 		}
665 
666 		cam_freeccb(ccb);
667 		return(1);
668 	}
669 
670 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
671 		if (quiet == 0)
672 			fprintf(stdout, "Unit is ready\n");
673 	} else {
674 		if (quiet == 0)
675 			fprintf(stdout, "Unit is not ready\n");
676 		error = 1;
677 
678 		if (arglist & CAM_ARG_VERBOSE) {
679 			cam_error_print(device, ccb, CAM_ESF_ALL,
680 					CAM_EPF_ALL, stderr);
681 		}
682 	}
683 
684 	cam_freeccb(ccb);
685 
686 	return(error);
687 }
688 
689 static int
690 scsistart(struct cam_device *device, int startstop, int loadeject,
691 	  int retry_count, int timeout)
692 {
693 	union ccb *ccb;
694 	int error = 0;
695 
696 	ccb = cam_getccb(device);
697 
698 	/*
699 	 * If we're stopping, send an ordered tag so the drive in question
700 	 * will finish any previously queued writes before stopping.  If
701 	 * the device isn't capable of tagged queueing, or if tagged
702 	 * queueing is turned off, the tag action is a no-op.
703 	 */
704 	scsi_start_stop(&ccb->csio,
705 			/* retries */ retry_count,
706 			/* cbfcnp */ NULL,
707 			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
708 						     MSG_ORDERED_Q_TAG,
709 			/* start/stop */ startstop,
710 			/* load_eject */ loadeject,
711 			/* immediate */ 0,
712 			/* sense_len */ SSD_FULL_SIZE,
713 			/* timeout */ timeout ? timeout : 120000);
714 
715 	/* Disable freezing the device queue */
716 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
717 
718 	if (arglist & CAM_ARG_ERR_RECOVER)
719 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
720 
721 	if (cam_send_ccb(device, ccb) < 0) {
722 		perror("error sending start unit");
723 
724 		if (arglist & CAM_ARG_VERBOSE) {
725 			cam_error_print(device, ccb, CAM_ESF_ALL,
726 					CAM_EPF_ALL, stderr);
727 		}
728 
729 		cam_freeccb(ccb);
730 		return(1);
731 	}
732 
733 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
734 		if (startstop) {
735 			fprintf(stdout, "Unit started successfully");
736 			if (loadeject)
737 				fprintf(stdout,", Media loaded\n");
738 			else
739 				fprintf(stdout,"\n");
740 		} else {
741 			fprintf(stdout, "Unit stopped successfully");
742 			if (loadeject)
743 				fprintf(stdout, ", Media ejected\n");
744 			else
745 				fprintf(stdout, "\n");
746 		}
747 	else {
748 		error = 1;
749 		if (startstop)
750 			fprintf(stdout,
751 				"Error received from start unit command\n");
752 		else
753 			fprintf(stdout,
754 				"Error received from stop unit command\n");
755 
756 		if (arglist & CAM_ARG_VERBOSE) {
757 			cam_error_print(device, ccb, CAM_ESF_ALL,
758 					CAM_EPF_ALL, stderr);
759 		}
760 	}
761 
762 	cam_freeccb(ccb);
763 
764 	return(error);
765 }
766 
767 int
768 scsidoinquiry(struct cam_device *device, int argc, char **argv,
769 	      char *combinedopt, int retry_count, int timeout)
770 {
771 	int c;
772 	int error = 0;
773 
774 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
775 		switch(c) {
776 		case 'D':
777 			arglist |= CAM_ARG_GET_STDINQ;
778 			break;
779 		case 'R':
780 			arglist |= CAM_ARG_GET_XFERRATE;
781 			break;
782 		case 'S':
783 			arglist |= CAM_ARG_GET_SERIAL;
784 			break;
785 		default:
786 			break;
787 		}
788 	}
789 
790 	/*
791 	 * If the user didn't specify any inquiry options, he wants all of
792 	 * them.
793 	 */
794 	if ((arglist & CAM_ARG_INQ_MASK) == 0)
795 		arglist |= CAM_ARG_INQ_MASK;
796 
797 	if (arglist & CAM_ARG_GET_STDINQ)
798 		error = scsiinquiry(device, retry_count, timeout);
799 
800 	if (error != 0)
801 		return(error);
802 
803 	if (arglist & CAM_ARG_GET_SERIAL)
804 		scsiserial(device, retry_count, timeout);
805 
806 	if (error != 0)
807 		return(error);
808 
809 	if (arglist & CAM_ARG_GET_XFERRATE)
810 		error = camxferrate(device);
811 
812 	return(error);
813 }
814 
815 static int
816 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
817 {
818 	union ccb *ccb;
819 	struct scsi_inquiry_data *inq_buf;
820 	int error = 0;
821 
822 	ccb = cam_getccb(device);
823 
824 	if (ccb == NULL) {
825 		warnx("couldn't allocate CCB");
826 		return(1);
827 	}
828 
829 	/* cam_getccb cleans up the header, caller has to zero the payload */
830 	bzero(&(&ccb->ccb_h)[1],
831 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
832 
833 	inq_buf = (struct scsi_inquiry_data *)malloc(
834 		sizeof(struct scsi_inquiry_data));
835 
836 	if (inq_buf == NULL) {
837 		cam_freeccb(ccb);
838 		warnx("can't malloc memory for inquiry\n");
839 		return(1);
840 	}
841 	bzero(inq_buf, sizeof(*inq_buf));
842 
843 	/*
844 	 * Note that although the size of the inquiry buffer is the full
845 	 * 256 bytes specified in the SCSI spec, we only tell the device
846 	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
847 	 * two reasons for this:
848 	 *
849 	 *  - The SCSI spec says that when a length field is only 1 byte,
850 	 *    a value of 0 will be interpreted as 256.  Therefore
851 	 *    scsi_inquiry() will convert an inq_len (which is passed in as
852 	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
853 	 *    to 0.  Evidently, very few devices meet the spec in that
854 	 *    regard.  Some devices, like many Seagate disks, take the 0 as
855 	 *    0, and don't return any data.  One Pioneer DVD-R drive
856 	 *    returns more data than the command asked for.
857 	 *
858 	 *    So, since there are numerous devices that just don't work
859 	 *    right with the full inquiry size, we don't send the full size.
860 	 *
861 	 *  - The second reason not to use the full inquiry data length is
862 	 *    that we don't need it here.  The only reason we issue a
863 	 *    standard inquiry is to get the vendor name, device name,
864 	 *    and revision so scsi_print_inquiry() can print them.
865 	 *
866 	 * If, at some point in the future, more inquiry data is needed for
867 	 * some reason, this code should use a procedure similar to the
868 	 * probe code.  i.e., issue a short inquiry, and determine from
869 	 * the additional length passed back from the device how much
870 	 * inquiry data the device supports.  Once the amount the device
871 	 * supports is determined, issue an inquiry for that amount and no
872 	 * more.
873 	 *
874 	 * KDM, 2/18/2000
875 	 */
876 	scsi_inquiry(&ccb->csio,
877 		     /* retries */ retry_count,
878 		     /* cbfcnp */ NULL,
879 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
880 		     /* inq_buf */ (u_int8_t *)inq_buf,
881 		     /* inq_len */ SHORT_INQUIRY_LENGTH,
882 		     /* evpd */ 0,
883 		     /* page_code */ 0,
884 		     /* sense_len */ SSD_FULL_SIZE,
885 		     /* timeout */ timeout ? timeout : 5000);
886 
887 	/* Disable freezing the device queue */
888 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
889 
890 	if (arglist & CAM_ARG_ERR_RECOVER)
891 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
892 
893 	if (cam_send_ccb(device, ccb) < 0) {
894 		perror("error sending SCSI inquiry");
895 
896 		if (arglist & CAM_ARG_VERBOSE) {
897 			cam_error_print(device, ccb, CAM_ESF_ALL,
898 					CAM_EPF_ALL, stderr);
899 		}
900 
901 		cam_freeccb(ccb);
902 		return(1);
903 	}
904 
905 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
906 		error = 1;
907 
908 		if (arglist & CAM_ARG_VERBOSE) {
909 			cam_error_print(device, ccb, CAM_ESF_ALL,
910 					CAM_EPF_ALL, stderr);
911 		}
912 	}
913 
914 	cam_freeccb(ccb);
915 
916 	if (error != 0) {
917 		free(inq_buf);
918 		return(error);
919 	}
920 
921 	fprintf(stdout, "%s%d: ", device->device_name,
922 		device->dev_unit_num);
923 	scsi_print_inquiry(inq_buf);
924 
925 	free(inq_buf);
926 
927 	return(0);
928 }
929 
930 static int
931 scsiserial(struct cam_device *device, int retry_count, int timeout)
932 {
933 	union ccb *ccb;
934 	struct scsi_vpd_unit_serial_number *serial_buf;
935 	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
936 	int error = 0;
937 
938 	ccb = cam_getccb(device);
939 
940 	if (ccb == NULL) {
941 		warnx("couldn't allocate CCB");
942 		return(1);
943 	}
944 
945 	/* cam_getccb cleans up the header, caller has to zero the payload */
946 	bzero(&(&ccb->ccb_h)[1],
947 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
948 
949 	serial_buf = (struct scsi_vpd_unit_serial_number *)
950 		malloc(sizeof(*serial_buf));
951 
952 	if (serial_buf == NULL) {
953 		cam_freeccb(ccb);
954 		warnx("can't malloc memory for serial number");
955 		return(1);
956 	}
957 
958 	scsi_inquiry(&ccb->csio,
959 		     /*retries*/ retry_count,
960 		     /*cbfcnp*/ NULL,
961 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
962 		     /* inq_buf */ (u_int8_t *)serial_buf,
963 		     /* inq_len */ sizeof(*serial_buf),
964 		     /* evpd */ 1,
965 		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
966 		     /* sense_len */ SSD_FULL_SIZE,
967 		     /* timeout */ timeout ? timeout : 5000);
968 
969 	/* Disable freezing the device queue */
970 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
971 
972 	if (arglist & CAM_ARG_ERR_RECOVER)
973 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
974 
975 	if (cam_send_ccb(device, ccb) < 0) {
976 		warn("error getting serial number");
977 
978 		if (arglist & CAM_ARG_VERBOSE) {
979 			cam_error_print(device, ccb, CAM_ESF_ALL,
980 					CAM_EPF_ALL, stderr);
981 		}
982 
983 		cam_freeccb(ccb);
984 		free(serial_buf);
985 		return(1);
986 	}
987 
988 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
989 		error = 1;
990 
991 		if (arglist & CAM_ARG_VERBOSE) {
992 			cam_error_print(device, ccb, CAM_ESF_ALL,
993 					CAM_EPF_ALL, stderr);
994 		}
995 	}
996 
997 	cam_freeccb(ccb);
998 
999 	if (error != 0) {
1000 		free(serial_buf);
1001 		return(error);
1002 	}
1003 
1004 	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
1005 	serial_num[serial_buf->length] = '\0';
1006 
1007 	if ((arglist & CAM_ARG_GET_STDINQ)
1008 	 || (arglist & CAM_ARG_GET_XFERRATE))
1009 		fprintf(stdout, "%s%d: Serial Number ",
1010 			device->device_name, device->dev_unit_num);
1011 
1012 	fprintf(stdout, "%.60s\n", serial_num);
1013 
1014 	free(serial_buf);
1015 
1016 	return(0);
1017 }
1018 
1019 static int
1020 camxferrate(struct cam_device *device)
1021 {
1022 	struct ccb_pathinq cpi;
1023 	u_int32_t freq = 0;
1024 	u_int32_t speed = 0;
1025 	union ccb *ccb;
1026 	u_int mb;
1027 	int retval = 0;
1028 
1029 	if ((retval = get_cpi(device, &cpi)) != 0)
1030 		return (1);
1031 
1032 	ccb = cam_getccb(device);
1033 
1034 	if (ccb == NULL) {
1035 		warnx("couldn't allocate CCB");
1036 		return(1);
1037 	}
1038 
1039 	bzero(&(&ccb->ccb_h)[1],
1040 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
1041 
1042 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1043 	ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
1044 
1045 	if (((retval = cam_send_ccb(device, ccb)) < 0)
1046 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1047 		const char error_string[] = "error getting transfer settings";
1048 
1049 		if (retval < 0)
1050 			warn(error_string);
1051 		else
1052 			warnx(error_string);
1053 
1054 		if (arglist & CAM_ARG_VERBOSE)
1055 			cam_error_print(device, ccb, CAM_ESF_ALL,
1056 					CAM_EPF_ALL, stderr);
1057 
1058 		retval = 1;
1059 
1060 		goto xferrate_bailout;
1061 
1062 	}
1063 
1064 	speed = cpi.base_transfer_speed;
1065 	freq = 0;
1066 	if (ccb->cts.transport == XPORT_SPI) {
1067 		struct ccb_trans_settings_spi *spi =
1068 		    &ccb->cts.xport_specific.spi;
1069 
1070 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1071 			freq = scsi_calc_syncsrate(spi->sync_period);
1072 			speed = freq;
1073 		}
1074 		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1075 			speed *= (0x01 << spi->bus_width);
1076 		}
1077 	} else if (ccb->cts.transport == XPORT_FC) {
1078 		struct ccb_trans_settings_fc *fc =
1079 		    &ccb->cts.xport_specific.fc;
1080 
1081 		if (fc->valid & CTS_FC_VALID_SPEED)
1082 			speed = fc->bitrate;
1083 	} else if (ccb->cts.transport == XPORT_SAS) {
1084 		struct ccb_trans_settings_sas *sas =
1085 		    &ccb->cts.xport_specific.sas;
1086 
1087 		if (sas->valid & CTS_SAS_VALID_SPEED)
1088 			speed = sas->bitrate;
1089 	} else if (ccb->cts.transport == XPORT_ATA) {
1090 		struct ccb_trans_settings_pata *pata =
1091 		    &ccb->cts.xport_specific.ata;
1092 
1093 		if (pata->valid & CTS_ATA_VALID_MODE)
1094 			speed = ata_mode2speed(pata->mode);
1095 	} else if (ccb->cts.transport == XPORT_SATA) {
1096 		struct	ccb_trans_settings_sata *sata =
1097 		    &ccb->cts.xport_specific.sata;
1098 
1099 		if (sata->valid & CTS_SATA_VALID_REVISION)
1100 			speed = ata_revision2speed(sata->revision);
1101 	}
1102 
1103 	mb = speed / 1000;
1104 	if (mb > 0) {
1105 		fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1106 			device->device_name, device->dev_unit_num,
1107 			mb, speed % 1000);
1108 	} else {
1109 		fprintf(stdout, "%s%d: %dKB/s transfers",
1110 			device->device_name, device->dev_unit_num,
1111 			speed);
1112 	}
1113 
1114 	if (ccb->cts.transport == XPORT_SPI) {
1115 		struct ccb_trans_settings_spi *spi =
1116 		    &ccb->cts.xport_specific.spi;
1117 
1118 		if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1119 		 && (spi->sync_offset != 0))
1120 			fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1121 				freq % 1000, spi->sync_offset);
1122 
1123 		if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1124 		 && (spi->bus_width > 0)) {
1125 			if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1126 			 && (spi->sync_offset != 0)) {
1127 				fprintf(stdout, ", ");
1128 			} else {
1129 				fprintf(stdout, " (");
1130 			}
1131 			fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1132 		} else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1133 		 && (spi->sync_offset != 0)) {
1134 			fprintf(stdout, ")");
1135 		}
1136 	} else if (ccb->cts.transport == XPORT_ATA) {
1137 		struct ccb_trans_settings_pata *pata =
1138 		    &ccb->cts.xport_specific.ata;
1139 
1140 		printf(" (");
1141 		if (pata->valid & CTS_ATA_VALID_MODE)
1142 			printf("%s, ", ata_mode2string(pata->mode));
1143 		if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1144 			printf("ATAPI %dbytes, ", pata->atapi);
1145 		if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1146 			printf("PIO %dbytes", pata->bytecount);
1147 		printf(")");
1148 	} else if (ccb->cts.transport == XPORT_SATA) {
1149 		struct ccb_trans_settings_sata *sata =
1150 		    &ccb->cts.xport_specific.sata;
1151 
1152 		printf(" (");
1153 		if (sata->valid & CTS_SATA_VALID_REVISION)
1154 			printf("SATA %d.x, ", sata->revision);
1155 		else
1156 			printf("SATA, ");
1157 		if (sata->valid & CTS_SATA_VALID_MODE)
1158 			printf("%s, ", ata_mode2string(sata->mode));
1159 		if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1160 			printf("ATAPI %dbytes, ", sata->atapi);
1161 		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1162 			printf("PIO %dbytes", sata->bytecount);
1163 		printf(")");
1164 	}
1165 
1166 	if (ccb->cts.protocol == PROTO_SCSI) {
1167 		struct ccb_trans_settings_scsi *scsi =
1168 		    &ccb->cts.proto_specific.scsi;
1169 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
1170 			if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1171 				fprintf(stdout, ", Command Queueing Enabled");
1172 			}
1173 		}
1174 	}
1175 
1176         fprintf(stdout, "\n");
1177 
1178 xferrate_bailout:
1179 
1180 	cam_freeccb(ccb);
1181 
1182 	return(retval);
1183 }
1184 
1185 static void
1186 atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
1187 {
1188 	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1189 				((u_int32_t)parm->lba_size_2 << 16);
1190 
1191 	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1192 				((u_int64_t)parm->lba_size48_2 << 16) |
1193 				((u_int64_t)parm->lba_size48_3 << 32) |
1194 				((u_int64_t)parm->lba_size48_4 << 48);
1195 
1196 	if (header) {
1197 		printf("\nFeature                      "
1198 		       "Support  Enabled   Value\n");
1199 	}
1200 
1201 	printf("Host Protected Area (HPA)      ");
1202 	if (parm->support.command1 & ATA_SUPPORT_PROTECTED) {
1203 		u_int64_t lba = lbasize48 ? lbasize48 : lbasize;
1204 		printf("yes      %s     %ju/%ju\n", (hpasize > lba) ? "yes" : "no ",
1205 		        lba, hpasize);
1206 
1207 		printf("HPA - Security                 ");
1208 		if (parm->support.command1 & ATA_SUPPORT_MAXSECURITY)
1209 			printf("yes\n");
1210 		else
1211 			printf("no\n");
1212 	} else {
1213 		printf("no\n");
1214 	}
1215 }
1216 
1217 static int
1218 atasata(struct ata_params *parm)
1219 {
1220 
1221 
1222 	if (parm->satacapabilities != 0xffff &&
1223 	    parm->satacapabilities != 0x0000)
1224 		return 1;
1225 
1226 	return 0;
1227 }
1228 
1229 static void
1230 atacapprint(struct ata_params *parm)
1231 {
1232 	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1233 				((u_int32_t)parm->lba_size_2 << 16);
1234 
1235 	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1236 				((u_int64_t)parm->lba_size48_2 << 16) |
1237 				((u_int64_t)parm->lba_size48_3 << 32) |
1238 				((u_int64_t)parm->lba_size48_4 << 48);
1239 
1240 	printf("\n");
1241 	printf("protocol              ");
1242 	printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1243 	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1244 		if (parm->satacapabilities & ATA_SATA_GEN3)
1245 			printf(" SATA 3.x\n");
1246 		else if (parm->satacapabilities & ATA_SATA_GEN2)
1247 			printf(" SATA 2.x\n");
1248 		else if (parm->satacapabilities & ATA_SATA_GEN1)
1249 			printf(" SATA 1.x\n");
1250 		else
1251 			printf(" SATA\n");
1252 	}
1253 	else
1254 		printf("\n");
1255 	printf("device model          %.40s\n", parm->model);
1256 	printf("firmware revision     %.8s\n", parm->revision);
1257 	printf("serial number         %.20s\n", parm->serial);
1258 	if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1259 		printf("WWN                   %04x%04x%04x%04x\n",
1260 		    parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1261 	}
1262 	if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1263 		printf("media serial number   %.30s\n",
1264 		    parm->media_serial);
1265 	}
1266 
1267 	printf("cylinders             %d\n", parm->cylinders);
1268 	printf("heads                 %d\n", parm->heads);
1269 	printf("sectors/track         %d\n", parm->sectors);
1270 	printf("sector size           logical %u, physical %lu, offset %lu\n",
1271 	    ata_logical_sector_size(parm),
1272 	    (unsigned long)ata_physical_sector_size(parm),
1273 	    (unsigned long)ata_logical_sector_offset(parm));
1274 
1275 	if (parm->config == ATA_PROTO_CFA ||
1276 	    (parm->support.command2 & ATA_SUPPORT_CFA))
1277 		printf("CFA supported\n");
1278 
1279 	printf("LBA%ssupported         ",
1280 		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1281 	if (lbasize)
1282 		printf("%d sectors\n", lbasize);
1283 	else
1284 		printf("\n");
1285 
1286 	printf("LBA48%ssupported       ",
1287 		parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1288 	if (lbasize48)
1289 		printf("%ju sectors\n", (uintmax_t)lbasize48);
1290 	else
1291 		printf("\n");
1292 
1293 	printf("PIO supported         PIO");
1294 	switch (ata_max_pmode(parm)) {
1295 	case ATA_PIO4:
1296 		printf("4");
1297 		break;
1298 	case ATA_PIO3:
1299 		printf("3");
1300 		break;
1301 	case ATA_PIO2:
1302 		printf("2");
1303 		break;
1304 	case ATA_PIO1:
1305 		printf("1");
1306 		break;
1307 	default:
1308 		printf("0");
1309 	}
1310 	if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1311 		printf(" w/o IORDY");
1312 	printf("\n");
1313 
1314 	printf("DMA%ssupported         ",
1315 		parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1316 	if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1317 		if (parm->mwdmamodes & 0xff) {
1318 			printf("WDMA");
1319 			if (parm->mwdmamodes & 0x04)
1320 				printf("2");
1321 			else if (parm->mwdmamodes & 0x02)
1322 				printf("1");
1323 			else if (parm->mwdmamodes & 0x01)
1324 				printf("0");
1325 			printf(" ");
1326 		}
1327 		if ((parm->atavalid & ATA_FLAG_88) &&
1328 		    (parm->udmamodes & 0xff)) {
1329 			printf("UDMA");
1330 			if (parm->udmamodes & 0x40)
1331 				printf("6");
1332 			else if (parm->udmamodes & 0x20)
1333 				printf("5");
1334 			else if (parm->udmamodes & 0x10)
1335 				printf("4");
1336 			else if (parm->udmamodes & 0x08)
1337 				printf("3");
1338 			else if (parm->udmamodes & 0x04)
1339 				printf("2");
1340 			else if (parm->udmamodes & 0x02)
1341 				printf("1");
1342 			else if (parm->udmamodes & 0x01)
1343 				printf("0");
1344 			printf(" ");
1345 		}
1346 	}
1347 	printf("\n");
1348 
1349 	if (parm->media_rotation_rate == 1) {
1350 		printf("media RPM             non-rotating\n");
1351 	} else if (parm->media_rotation_rate >= 0x0401 &&
1352 	    parm->media_rotation_rate <= 0xFFFE) {
1353 		printf("media RPM             %d\n",
1354 			parm->media_rotation_rate);
1355 	}
1356 
1357 	printf("\nFeature                      "
1358 		"Support  Enabled   Value           Vendor\n");
1359 	printf("read ahead                     %s	%s\n",
1360 		parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1361 		parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1362 	printf("write cache                    %s	%s\n",
1363 		parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1364 		parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1365 	printf("flush cache                    %s	%s\n",
1366 		parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1367 		parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1368 	printf("overlap                        %s\n",
1369 		parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1370 	printf("Tagged Command Queuing (TCQ)   %s	%s",
1371 		parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1372 		parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1373 		if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1374 			printf("	%d tags\n",
1375 			    ATA_QUEUE_LEN(parm->queue) + 1);
1376 		} else
1377 			printf("\n");
1378 	printf("Native Command Queuing (NCQ)   ");
1379 	if (parm->satacapabilities != 0xffff &&
1380 	    (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1381 		printf("yes		%d tags\n",
1382 		    ATA_QUEUE_LEN(parm->queue) + 1);
1383 	} else
1384 		printf("no\n");
1385 
1386 	printf("NCQ Queue Management           %s\n", atasata(parm) &&
1387 		parm->satacapabilities2 & ATA_SUPPORT_NCQ_QMANAGEMENT ?
1388 		"yes" : "no");
1389 	printf("NCQ Streaming                  %s\n", atasata(parm) &&
1390 		parm->satacapabilities2 & ATA_SUPPORT_NCQ_STREAM ?
1391 		"yes" : "no");
1392 	printf("Receive & Send FPDMA Queued    %s\n", atasata(parm) &&
1393 		parm->satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED ?
1394 		"yes" : "no");
1395 
1396 	printf("SMART                          %s	%s\n",
1397 		parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1398 		parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1399 	printf("microcode download             %s	%s\n",
1400 		parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1401 		parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1402 	printf("security                       %s	%s\n",
1403 		parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1404 		parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1405 	printf("power management               %s	%s\n",
1406 		parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1407 		parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1408 	printf("advanced power management      %s	%s",
1409 		parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1410 		parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1411 		if (parm->support.command2 & ATA_SUPPORT_APM) {
1412 			printf("	%d/0x%02X\n",
1413 			    parm->apm_value & 0xff, parm->apm_value & 0xff);
1414 		} else
1415 			printf("\n");
1416 	printf("automatic acoustic management  %s	%s",
1417 		parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1418 		parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1419 		if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1420 			printf("	%d/0x%02X	%d/0x%02X\n",
1421 			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1422 			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1423 			    ATA_ACOUSTIC_VENDOR(parm->acoustic),
1424 			    ATA_ACOUSTIC_VENDOR(parm->acoustic));
1425 		} else
1426 			printf("\n");
1427 	printf("media status notification      %s	%s\n",
1428 		parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1429 		parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1430 	printf("power-up in Standby            %s	%s\n",
1431 		parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1432 		parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1433 	printf("write-read-verify              %s	%s",
1434 		parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1435 		parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1436 		if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1437 			printf("	%d/0x%x\n",
1438 			    parm->wrv_mode, parm->wrv_mode);
1439 		} else
1440 			printf("\n");
1441 	printf("unload                         %s	%s\n",
1442 		parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1443 		parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1444 	printf("general purpose logging        %s	%s\n",
1445 		parm->support.extension & ATA_SUPPORT_GENLOG ? "yes" : "no",
1446 		parm->enabled.extension & ATA_SUPPORT_GENLOG ? "yes" : "no");
1447 	printf("free-fall                      %s	%s\n",
1448 		parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1449 		parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1450 	printf("Data Set Management (DSM/TRIM) ");
1451 	if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) {
1452 		printf("yes\n");
1453 		printf("DSM - max 512byte blocks       ");
1454 		if (parm->max_dsm_blocks == 0x00)
1455 			printf("yes              not specified\n");
1456 		else
1457 			printf("yes              %d\n",
1458 				parm->max_dsm_blocks);
1459 
1460 		printf("DSM - deterministic read       ");
1461 		if (parm->support3 & ATA_SUPPORT_DRAT) {
1462 			if (parm->support3 & ATA_SUPPORT_RZAT)
1463 				printf("yes              zeroed\n");
1464 			else
1465 				printf("yes              any value\n");
1466 		} else {
1467 			printf("no\n");
1468 		}
1469 	} else {
1470 		printf("no\n");
1471 	}
1472 }
1473 
1474 static int
1475 scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
1476 {
1477 	struct ata_pass_16 *ata_pass_16;
1478 	struct ata_cmd ata_cmd;
1479 
1480 	ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
1481 	ata_cmd.command = ata_pass_16->command;
1482 	ata_cmd.control = ata_pass_16->control;
1483 	ata_cmd.features = ata_pass_16->features;
1484 
1485 	if (arglist & CAM_ARG_VERBOSE) {
1486 		warnx("sending ATA %s via pass_16 with timeout of %u msecs",
1487 		      ata_op_string(&ata_cmd),
1488 		      ccb->csio.ccb_h.timeout);
1489 	}
1490 
1491 	/* Disable freezing the device queue */
1492 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1493 
1494 	if (arglist & CAM_ARG_ERR_RECOVER)
1495 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1496 
1497 	if (cam_send_ccb(device, ccb) < 0) {
1498 		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1499 			warn("error sending ATA %s via pass_16",
1500 			     ata_op_string(&ata_cmd));
1501 		}
1502 
1503 		if (arglist & CAM_ARG_VERBOSE) {
1504 			cam_error_print(device, ccb, CAM_ESF_ALL,
1505 					CAM_EPF_ALL, stderr);
1506 		}
1507 
1508 		return (1);
1509 	}
1510 
1511 	if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
1512 	    (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1513 		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1514 			warnx("ATA %s via pass_16 failed",
1515 			      ata_op_string(&ata_cmd));
1516 		}
1517 		if (arglist & CAM_ARG_VERBOSE) {
1518 			cam_error_print(device, ccb, CAM_ESF_ALL,
1519 					CAM_EPF_ALL, stderr);
1520 		}
1521 
1522 		return (1);
1523 	}
1524 
1525 	return (0);
1526 }
1527 
1528 
1529 static int
1530 ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
1531 {
1532 	if (arglist & CAM_ARG_VERBOSE) {
1533 		warnx("sending ATA %s with timeout of %u msecs",
1534 		      ata_op_string(&(ccb->ataio.cmd)),
1535 		      ccb->ataio.ccb_h.timeout);
1536 	}
1537 
1538 	/* Disable freezing the device queue */
1539 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1540 
1541 	if (arglist & CAM_ARG_ERR_RECOVER)
1542 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1543 
1544 	if (cam_send_ccb(device, ccb) < 0) {
1545 		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1546 			warn("error sending ATA %s",
1547 			     ata_op_string(&(ccb->ataio.cmd)));
1548 		}
1549 
1550 		if (arglist & CAM_ARG_VERBOSE) {
1551 			cam_error_print(device, ccb, CAM_ESF_ALL,
1552 					CAM_EPF_ALL, stderr);
1553 		}
1554 
1555 		return (1);
1556 	}
1557 
1558 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1559 		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1560 			warnx("ATA %s failed: %d",
1561 			      ata_op_string(&(ccb->ataio.cmd)), quiet);
1562 		}
1563 
1564 		if (arglist & CAM_ARG_VERBOSE) {
1565 			cam_error_print(device, ccb, CAM_ESF_ALL,
1566 					CAM_EPF_ALL, stderr);
1567 		}
1568 
1569 		return (1);
1570 	}
1571 
1572 	return (0);
1573 }
1574 
1575 static int
1576 ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
1577 	       u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1578 	       u_int8_t tag_action, u_int8_t command, u_int8_t features,
1579 	       u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1580 	       u_int16_t dxfer_len, int timeout, int quiet)
1581 {
1582 	if (data_ptr != NULL) {
1583 		ata_flags |= AP_FLAG_BYT_BLOK_BYTES |
1584 			    AP_FLAG_TLEN_SECT_CNT;
1585 		if (flags & CAM_DIR_OUT)
1586 			ata_flags |= AP_FLAG_TDIR_TO_DEV;
1587 		else
1588 			ata_flags |= AP_FLAG_TDIR_FROM_DEV;
1589 	} else {
1590 		ata_flags |= AP_FLAG_TLEN_NO_DATA;
1591 	}
1592 
1593 	bzero(&(&ccb->ccb_h)[1],
1594 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1595 
1596 	scsi_ata_pass_16(&ccb->csio,
1597 			 retries,
1598 			 NULL,
1599 			 flags,
1600 			 tag_action,
1601 			 protocol,
1602 			 ata_flags,
1603 			 features,
1604 			 sector_count,
1605 			 lba,
1606 			 command,
1607 			 /*control*/0,
1608 			 data_ptr,
1609 			 dxfer_len,
1610 			 /*sense_len*/SSD_FULL_SIZE,
1611 			 timeout);
1612 
1613 	return scsi_cam_pass_16_send(device, ccb, quiet);
1614 }
1615 
1616 static int
1617 ata_try_pass_16(struct cam_device *device)
1618 {
1619 	struct ccb_pathinq cpi;
1620 
1621 	if (get_cpi(device, &cpi) != 0) {
1622 		warnx("couldn't get CPI");
1623 		return (-1);
1624 	}
1625 
1626 	if (cpi.protocol == PROTO_SCSI) {
1627 		/* possibly compatible with pass_16 */
1628 		return (1);
1629 	}
1630 
1631 	/* likely not compatible with pass_16 */
1632 	return (0);
1633 }
1634 
1635 static int
1636 ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries,
1637 		 u_int32_t flags, u_int8_t protocol, u_int8_t tag_action,
1638 		 u_int8_t command, u_int8_t features, u_int32_t lba,
1639 		 u_int8_t sector_count, u_int8_t *data_ptr, u_int16_t dxfer_len,
1640 		 int timeout, int quiet)
1641 {
1642 
1643 
1644 	switch (ata_try_pass_16(device)) {
1645 	case -1:
1646 		return (1);
1647 	case 1:
1648 		/* Try using SCSI Passthrough */
1649 		return ata_do_pass_16(device, ccb, retries, flags, protocol,
1650 				      0, tag_action, command, features, lba,
1651 				      sector_count, data_ptr, dxfer_len,
1652 				      timeout, quiet);
1653 	}
1654 
1655 	bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1656 	      sizeof(struct ccb_hdr));
1657 	cam_fill_ataio(&ccb->ataio,
1658 		       retries,
1659 		       NULL,
1660 		       flags,
1661 		       tag_action,
1662 		       data_ptr,
1663 		       dxfer_len,
1664 		       timeout);
1665 
1666 	ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1667 	return ata_cam_send(device, ccb, quiet);
1668 }
1669 
1670 static int
1671 ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
1672 	   u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1673 	   u_int8_t tag_action, u_int8_t command, u_int8_t features,
1674 	   u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1675 	   u_int16_t dxfer_len, int timeout, int force48bit)
1676 {
1677 	int retval;
1678 
1679 	retval = ata_try_pass_16(device);
1680 	if (retval == -1)
1681 		return (1);
1682 
1683 	if (retval == 1) {
1684 		int error;
1685 
1686 		/* Try using SCSI Passthrough */
1687 		error = ata_do_pass_16(device, ccb, retries, flags, protocol,
1688 				      ata_flags, tag_action, command, features,
1689 				      lba, sector_count, data_ptr, dxfer_len,
1690 				      timeout, 0);
1691 
1692 		if (ata_flags & AP_FLAG_CHK_COND) {
1693 			/* Decode ata_res from sense data */
1694 			struct ata_res_pass16 *res_pass16;
1695 			struct ata_res *res;
1696 			u_int i;
1697 			u_int16_t *ptr;
1698 
1699 			/* sense_data is 4 byte aligned */
1700 			ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data;
1701 			for (i = 0; i < sizeof(*res_pass16) / 2; i++)
1702 				ptr[i] = le16toh(ptr[i]);
1703 
1704 			/* sense_data is 4 byte aligned */
1705 			res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
1706 			    &ccb->csio.sense_data;
1707 			res = &ccb->ataio.res;
1708 			res->flags = res_pass16->flags;
1709 			res->status = res_pass16->status;
1710 			res->error = res_pass16->error;
1711 			res->lba_low = res_pass16->lba_low;
1712 			res->lba_mid = res_pass16->lba_mid;
1713 			res->lba_high = res_pass16->lba_high;
1714 			res->device = res_pass16->device;
1715 			res->lba_low_exp = res_pass16->lba_low_exp;
1716 			res->lba_mid_exp = res_pass16->lba_mid_exp;
1717 			res->lba_high_exp = res_pass16->lba_high_exp;
1718 			res->sector_count = res_pass16->sector_count;
1719 			res->sector_count_exp = res_pass16->sector_count_exp;
1720 		}
1721 
1722 		return (error);
1723 	}
1724 
1725 	bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1726 	      sizeof(struct ccb_hdr));
1727 	cam_fill_ataio(&ccb->ataio,
1728 		       retries,
1729 		       NULL,
1730 		       flags,
1731 		       tag_action,
1732 		       data_ptr,
1733 		       dxfer_len,
1734 		       timeout);
1735 
1736 	if (force48bit || lba > ATA_MAX_28BIT_LBA)
1737 		ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1738 	else
1739 		ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1740 
1741 	if (ata_flags & AP_FLAG_CHK_COND)
1742 		ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
1743 
1744 	return ata_cam_send(device, ccb, 0);
1745 }
1746 
1747 static void
1748 dump_data(uint16_t *ptr, uint32_t len)
1749 {
1750 	u_int i;
1751 
1752 	for (i = 0; i < len / 2; i++) {
1753 		if ((i % 8) == 0)
1754 			printf(" %3d: ", i);
1755 		printf("%04hx ", ptr[i]);
1756 		if ((i % 8) == 7)
1757 			printf("\n");
1758 	}
1759 	if ((i % 8) != 7)
1760 		printf("\n");
1761 }
1762 
1763 static int
1764 atahpa_proc_resp(struct cam_device *device, union ccb *ccb,
1765 		 int is48bit, u_int64_t *hpasize)
1766 {
1767 	struct ata_res *res;
1768 
1769 	res = &ccb->ataio.res;
1770 	if (res->status & ATA_STATUS_ERROR) {
1771 		if (arglist & CAM_ARG_VERBOSE) {
1772 			cam_error_print(device, ccb, CAM_ESF_ALL,
1773 					CAM_EPF_ALL, stderr);
1774 			printf("error = 0x%02x, sector_count = 0x%04x, "
1775 			       "device = 0x%02x, status = 0x%02x\n",
1776 			       res->error, res->sector_count,
1777 			       res->device, res->status);
1778 		}
1779 
1780 		if (res->error & ATA_ERROR_ID_NOT_FOUND) {
1781 			warnx("Max address has already been set since "
1782 			      "last power-on or hardware reset");
1783 		}
1784 
1785 		return (1);
1786 	}
1787 
1788 	if (arglist & CAM_ARG_VERBOSE) {
1789 		fprintf(stdout, "%s%d: Raw native max data:\n",
1790 			device->device_name, device->dev_unit_num);
1791 		/* res is 4 byte aligned */
1792 		dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
1793 
1794 		printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
1795 		       "status = 0x%02x\n", res->error, res->sector_count,
1796 		       res->device, res->status);
1797 	}
1798 
1799 	if (hpasize != NULL) {
1800 		if (is48bit) {
1801 			*hpasize = (((u_int64_t)((res->lba_high_exp << 16) |
1802 			    (res->lba_mid_exp << 8) | res->lba_low_exp) << 24) |
1803 			    ((res->lba_high << 16) | (res->lba_mid << 8) |
1804 			    res->lba_low)) + 1;
1805 		} else {
1806 			*hpasize = (((res->device & 0x0f) << 24) |
1807 			    (res->lba_high << 16) | (res->lba_mid << 8) |
1808 			    res->lba_low) + 1;
1809 		}
1810 	}
1811 
1812 	return (0);
1813 }
1814 
1815 static int
1816 ata_read_native_max(struct cam_device *device, int retry_count,
1817 		      u_int32_t timeout, union ccb *ccb,
1818 		      struct ata_params *parm, u_int64_t *hpasize)
1819 {
1820 	int error;
1821 	u_int cmd, is48bit;
1822 	u_int8_t protocol;
1823 
1824 	is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48;
1825 	protocol = AP_PROTO_NON_DATA;
1826 
1827 	if (is48bit) {
1828 		cmd = ATA_READ_NATIVE_MAX_ADDRESS48;
1829 		protocol |= AP_EXTEND;
1830 	} else {
1831 		cmd = ATA_READ_NATIVE_MAX_ADDRESS;
1832 	}
1833 
1834 	error = ata_do_cmd(device,
1835 			   ccb,
1836 			   retry_count,
1837 			   /*flags*/CAM_DIR_NONE,
1838 			   /*protocol*/protocol,
1839 			   /*ata_flags*/AP_FLAG_CHK_COND,
1840 			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1841 			   /*command*/cmd,
1842 			   /*features*/0,
1843 			   /*lba*/0,
1844 			   /*sector_count*/0,
1845 			   /*data_ptr*/NULL,
1846 			   /*dxfer_len*/0,
1847 			   timeout ? timeout : 1000,
1848 			   is48bit);
1849 
1850 	if (error)
1851 		return (error);
1852 
1853 	return atahpa_proc_resp(device, ccb, is48bit, hpasize);
1854 }
1855 
1856 static int
1857 atahpa_set_max(struct cam_device *device, int retry_count,
1858 	      u_int32_t timeout, union ccb *ccb,
1859 	      int is48bit, u_int64_t maxsize, int persist)
1860 {
1861 	int error;
1862 	u_int cmd;
1863 	u_int8_t protocol;
1864 
1865 	protocol = AP_PROTO_NON_DATA;
1866 
1867 	if (is48bit) {
1868 		cmd = ATA_SET_MAX_ADDRESS48;
1869 		protocol |= AP_EXTEND;
1870 	} else {
1871 		cmd = ATA_SET_MAX_ADDRESS;
1872 	}
1873 
1874 	/* lba's are zero indexed so the max lba is requested max - 1 */
1875 	if (maxsize)
1876 		maxsize--;
1877 
1878 	error = ata_do_cmd(device,
1879 			   ccb,
1880 			   retry_count,
1881 			   /*flags*/CAM_DIR_NONE,
1882 			   /*protocol*/protocol,
1883 			   /*ata_flags*/AP_FLAG_CHK_COND,
1884 			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1885 			   /*command*/cmd,
1886 			   /*features*/ATA_HPA_FEAT_MAX_ADDR,
1887 			   /*lba*/maxsize,
1888 			   /*sector_count*/persist,
1889 			   /*data_ptr*/NULL,
1890 			   /*dxfer_len*/0,
1891 			   timeout ? timeout : 1000,
1892 			   is48bit);
1893 
1894 	if (error)
1895 		return (error);
1896 
1897 	return atahpa_proc_resp(device, ccb, is48bit, NULL);
1898 }
1899 
1900 static int
1901 atahpa_password(struct cam_device *device, int retry_count,
1902 		u_int32_t timeout, union ccb *ccb,
1903 		int is48bit, struct ata_set_max_pwd *pwd)
1904 {
1905 	int error;
1906 	u_int cmd;
1907 	u_int8_t protocol;
1908 
1909 	protocol = AP_PROTO_PIO_OUT;
1910 	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1911 
1912 	error = ata_do_cmd(device,
1913 			   ccb,
1914 			   retry_count,
1915 			   /*flags*/CAM_DIR_OUT,
1916 			   /*protocol*/protocol,
1917 			   /*ata_flags*/AP_FLAG_CHK_COND,
1918 			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1919 			   /*command*/cmd,
1920 			   /*features*/ATA_HPA_FEAT_SET_PWD,
1921 			   /*lba*/0,
1922 			   /*sector_count*/0,
1923 			   /*data_ptr*/(u_int8_t*)pwd,
1924 			   /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1925 			   timeout ? timeout : 1000,
1926 			   is48bit);
1927 
1928 	if (error)
1929 		return (error);
1930 
1931 	return atahpa_proc_resp(device, ccb, is48bit, NULL);
1932 }
1933 
1934 static int
1935 atahpa_lock(struct cam_device *device, int retry_count,
1936 	    u_int32_t timeout, union ccb *ccb, int is48bit)
1937 {
1938 	int error;
1939 	u_int cmd;
1940 	u_int8_t protocol;
1941 
1942 	protocol = AP_PROTO_NON_DATA;
1943 	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1944 
1945 	error = ata_do_cmd(device,
1946 			   ccb,
1947 			   retry_count,
1948 			   /*flags*/CAM_DIR_NONE,
1949 			   /*protocol*/protocol,
1950 			   /*ata_flags*/AP_FLAG_CHK_COND,
1951 			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1952 			   /*command*/cmd,
1953 			   /*features*/ATA_HPA_FEAT_LOCK,
1954 			   /*lba*/0,
1955 			   /*sector_count*/0,
1956 			   /*data_ptr*/NULL,
1957 			   /*dxfer_len*/0,
1958 			   timeout ? timeout : 1000,
1959 			   is48bit);
1960 
1961 	if (error)
1962 		return (error);
1963 
1964 	return atahpa_proc_resp(device, ccb, is48bit, NULL);
1965 }
1966 
1967 static int
1968 atahpa_unlock(struct cam_device *device, int retry_count,
1969 	      u_int32_t timeout, union ccb *ccb,
1970 	      int is48bit, struct ata_set_max_pwd *pwd)
1971 {
1972 	int error;
1973 	u_int cmd;
1974 	u_int8_t protocol;
1975 
1976 	protocol = AP_PROTO_PIO_OUT;
1977 	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1978 
1979 	error = ata_do_cmd(device,
1980 			   ccb,
1981 			   retry_count,
1982 			   /*flags*/CAM_DIR_OUT,
1983 			   /*protocol*/protocol,
1984 			   /*ata_flags*/AP_FLAG_CHK_COND,
1985 			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1986 			   /*command*/cmd,
1987 			   /*features*/ATA_HPA_FEAT_UNLOCK,
1988 			   /*lba*/0,
1989 			   /*sector_count*/0,
1990 			   /*data_ptr*/(u_int8_t*)pwd,
1991 			   /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1992 			   timeout ? timeout : 1000,
1993 			   is48bit);
1994 
1995 	if (error)
1996 		return (error);
1997 
1998 	return atahpa_proc_resp(device, ccb, is48bit, NULL);
1999 }
2000 
2001 static int
2002 atahpa_freeze_lock(struct cam_device *device, int retry_count,
2003 		   u_int32_t timeout, union ccb *ccb, int is48bit)
2004 {
2005 	int error;
2006 	u_int cmd;
2007 	u_int8_t protocol;
2008 
2009 	protocol = AP_PROTO_NON_DATA;
2010 	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2011 
2012 	error = ata_do_cmd(device,
2013 			   ccb,
2014 			   retry_count,
2015 			   /*flags*/CAM_DIR_NONE,
2016 			   /*protocol*/protocol,
2017 			   /*ata_flags*/AP_FLAG_CHK_COND,
2018 			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2019 			   /*command*/cmd,
2020 			   /*features*/ATA_HPA_FEAT_FREEZE,
2021 			   /*lba*/0,
2022 			   /*sector_count*/0,
2023 			   /*data_ptr*/NULL,
2024 			   /*dxfer_len*/0,
2025 			   timeout ? timeout : 1000,
2026 			   is48bit);
2027 
2028 	if (error)
2029 		return (error);
2030 
2031 	return atahpa_proc_resp(device, ccb, is48bit, NULL);
2032 }
2033 
2034 
2035 static int
2036 ata_do_identify(struct cam_device *device, int retry_count, int timeout,
2037 		union ccb *ccb, struct ata_params** ident_bufp)
2038 {
2039 	struct ata_params *ident_buf;
2040 	struct ccb_pathinq cpi;
2041 	struct ccb_getdev cgd;
2042 	u_int i, error;
2043 	int16_t *ptr;
2044 	u_int8_t command, retry_command;
2045 
2046 	if (get_cpi(device, &cpi) != 0) {
2047 		warnx("couldn't get CPI");
2048 		return (-1);
2049 	}
2050 
2051 	/* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */
2052 	if (cpi.protocol == PROTO_ATA) {
2053 		if (get_cgd(device, &cgd) != 0) {
2054 			warnx("couldn't get CGD");
2055 			return (-1);
2056 		}
2057 
2058 		command = (cgd.protocol == PROTO_ATA) ?
2059 		    ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
2060 		retry_command = 0;
2061 	} else {
2062 		/* We don't know which for sure so try both */
2063 		command = ATA_ATA_IDENTIFY;
2064 		retry_command = ATA_ATAPI_IDENTIFY;
2065 	}
2066 
2067 	ptr = (uint16_t *)calloc(1, sizeof(struct ata_params));
2068 	if (ptr == NULL) {
2069 		warnx("can't calloc memory for identify\n");
2070 		return (1);
2071 	}
2072 
2073 	error = ata_do_28bit_cmd(device,
2074 				 ccb,
2075 				 /*retries*/retry_count,
2076 				 /*flags*/CAM_DIR_IN,
2077 				 /*protocol*/AP_PROTO_PIO_IN,
2078 				 /*tag_action*/MSG_SIMPLE_Q_TAG,
2079 				 /*command*/command,
2080 				 /*features*/0,
2081 				 /*lba*/0,
2082 				 /*sector_count*/(u_int8_t)sizeof(struct ata_params),
2083 				 /*data_ptr*/(u_int8_t *)ptr,
2084 				 /*dxfer_len*/sizeof(struct ata_params),
2085 				 /*timeout*/timeout ? timeout : 30 * 1000,
2086 				 /*quiet*/1);
2087 
2088 	if (error != 0) {
2089 		if (retry_command == 0) {
2090 			free(ptr);
2091 			return (1);
2092 		}
2093 		error = ata_do_28bit_cmd(device,
2094 					 ccb,
2095 					 /*retries*/retry_count,
2096 					 /*flags*/CAM_DIR_IN,
2097 					 /*protocol*/AP_PROTO_PIO_IN,
2098 					 /*tag_action*/MSG_SIMPLE_Q_TAG,
2099 					 /*command*/retry_command,
2100 					 /*features*/0,
2101 					 /*lba*/0,
2102 					 /*sector_count*/(u_int8_t)
2103 					     sizeof(struct ata_params),
2104 					 /*data_ptr*/(u_int8_t *)ptr,
2105 					 /*dxfer_len*/sizeof(struct ata_params),
2106 					 /*timeout*/timeout ? timeout : 30 * 1000,
2107 					 /*quiet*/0);
2108 
2109 		if (error != 0) {
2110 			free(ptr);
2111 			return (1);
2112 		}
2113 	}
2114 
2115 	error = 1;
2116 	for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
2117 		ptr[i] = le16toh(ptr[i]);
2118 		if (ptr[i] != 0)
2119 			error = 0;
2120 	}
2121 
2122 	if (arglist & CAM_ARG_VERBOSE) {
2123 		fprintf(stdout, "%s%d: Raw identify data:\n",
2124 		    device->device_name, device->dev_unit_num);
2125 		dump_data(ptr, sizeof(struct ata_params));
2126 	}
2127 
2128 	/* check for invalid (all zero) response */
2129 	if (error != 0) {
2130 		warnx("Invalid identify response detected");
2131 		free(ptr);
2132 		return (error);
2133 	}
2134 
2135 	ident_buf = (struct ata_params *)ptr;
2136 	if (strncmp(ident_buf->model, "FX", 2) &&
2137 	    strncmp(ident_buf->model, "NEC", 3) &&
2138 	    strncmp(ident_buf->model, "Pioneer", 7) &&
2139 	    strncmp(ident_buf->model, "SHARP", 5)) {
2140 		ata_bswap(ident_buf->model, sizeof(ident_buf->model));
2141 		ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
2142 		ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
2143 		ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2144 	}
2145 	ata_btrim(ident_buf->model, sizeof(ident_buf->model));
2146 	ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
2147 	ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
2148 	ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
2149 	ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
2150 	ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
2151 	ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2152 	ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
2153 	    sizeof(ident_buf->media_serial));
2154 
2155 	*ident_bufp = ident_buf;
2156 
2157 	return (0);
2158 }
2159 
2160 
2161 static int
2162 ataidentify(struct cam_device *device, int retry_count, int timeout)
2163 {
2164 	union ccb *ccb;
2165 	struct ata_params *ident_buf;
2166 	u_int64_t hpasize;
2167 
2168 	if ((ccb = cam_getccb(device)) == NULL) {
2169 		warnx("couldn't allocate CCB");
2170 		return (1);
2171 	}
2172 
2173 	if (ata_do_identify(device, retry_count, timeout, ccb, &ident_buf) != 0) {
2174 		cam_freeccb(ccb);
2175 		return (1);
2176 	}
2177 
2178 	if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) {
2179 		if (ata_read_native_max(device, retry_count, timeout, ccb,
2180 					ident_buf, &hpasize) != 0) {
2181 			cam_freeccb(ccb);
2182 			return (1);
2183 		}
2184 	} else {
2185 		hpasize = 0;
2186 	}
2187 
2188 	printf("%s%d: ", device->device_name, device->dev_unit_num);
2189 	ata_print_ident(ident_buf);
2190 	camxferrate(device);
2191 	atacapprint(ident_buf);
2192 	atahpa_print(ident_buf, hpasize, 0);
2193 
2194 	free(ident_buf);
2195 	cam_freeccb(ccb);
2196 
2197 	return (0);
2198 }
2199 #endif /* MINIMALISTIC */
2200 
2201 
2202 #ifndef MINIMALISTIC
2203 enum {
2204 	ATA_SECURITY_ACTION_PRINT,
2205 	ATA_SECURITY_ACTION_FREEZE,
2206 	ATA_SECURITY_ACTION_UNLOCK,
2207 	ATA_SECURITY_ACTION_DISABLE,
2208 	ATA_SECURITY_ACTION_ERASE,
2209 	ATA_SECURITY_ACTION_ERASE_ENHANCED,
2210 	ATA_SECURITY_ACTION_SET_PASSWORD
2211 };
2212 
2213 static void
2214 atasecurity_print_time(u_int16_t tw)
2215 {
2216 
2217 	if (tw == 0)
2218 		printf("unspecified");
2219 	else if (tw >= 255)
2220 		printf("> 508 min");
2221 	else
2222 		printf("%i min", 2 * tw);
2223 }
2224 
2225 static u_int32_t
2226 atasecurity_erase_timeout_msecs(u_int16_t timeout)
2227 {
2228 
2229 	if (timeout == 0)
2230 		return 2 * 3600 * 1000; /* default: two hours */
2231 	else if (timeout > 255)
2232 		return (508 + 60) * 60 * 1000; /* spec says > 508 minutes */
2233 
2234 	return ((2 * timeout) + 5) * 60 * 1000; /* add a 5min margin */
2235 }
2236 
2237 
2238 static void
2239 atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
2240 {
2241 	struct ata_cmd cmd;
2242 
2243 	bzero(&cmd, sizeof(cmd));
2244 	cmd.command = command;
2245 	printf("Issuing %s", ata_op_string(&cmd));
2246 
2247 	if (pwd != NULL) {
2248 		char pass[sizeof(pwd->password)+1];
2249 
2250 		/* pwd->password may not be null terminated */
2251 		pass[sizeof(pwd->password)] = '\0';
2252 		strncpy(pass, pwd->password, sizeof(pwd->password));
2253 		printf(" password='%s', user='%s'",
2254 			pass,
2255 			(pwd->ctrl & ATA_SECURITY_PASSWORD_MASTER) ?
2256 			"master" : "user");
2257 
2258 		if (command == ATA_SECURITY_SET_PASSWORD) {
2259 			printf(", mode='%s'",
2260 			       (pwd->ctrl & ATA_SECURITY_LEVEL_MAXIMUM) ?
2261 			       "maximum" : "high");
2262 		}
2263 	}
2264 
2265 	printf("\n");
2266 }
2267 
2268 static int
2269 atasecurity_freeze(struct cam_device *device, union ccb *ccb,
2270 		   int retry_count, u_int32_t timeout, int quiet)
2271 {
2272 
2273 	if (quiet == 0)
2274 		atasecurity_notify(ATA_SECURITY_FREEZE_LOCK, NULL);
2275 
2276 	return ata_do_28bit_cmd(device,
2277 				ccb,
2278 				retry_count,
2279 				/*flags*/CAM_DIR_NONE,
2280 				/*protocol*/AP_PROTO_NON_DATA,
2281 				/*tag_action*/MSG_SIMPLE_Q_TAG,
2282 				/*command*/ATA_SECURITY_FREEZE_LOCK,
2283 				/*features*/0,
2284 				/*lba*/0,
2285 				/*sector_count*/0,
2286 				/*data_ptr*/NULL,
2287 				/*dxfer_len*/0,
2288 				/*timeout*/timeout,
2289 				/*quiet*/0);
2290 }
2291 
2292 static int
2293 atasecurity_unlock(struct cam_device *device, union ccb *ccb,
2294 		   int retry_count, u_int32_t timeout,
2295 		   struct ata_security_password *pwd, int quiet)
2296 {
2297 
2298 	if (quiet == 0)
2299 		atasecurity_notify(ATA_SECURITY_UNLOCK, pwd);
2300 
2301 	return ata_do_28bit_cmd(device,
2302 				ccb,
2303 				retry_count,
2304 				/*flags*/CAM_DIR_OUT,
2305 				/*protocol*/AP_PROTO_PIO_OUT,
2306 				/*tag_action*/MSG_SIMPLE_Q_TAG,
2307 				/*command*/ATA_SECURITY_UNLOCK,
2308 				/*features*/0,
2309 				/*lba*/0,
2310 				/*sector_count*/0,
2311 				/*data_ptr*/(u_int8_t *)pwd,
2312 				/*dxfer_len*/sizeof(*pwd),
2313 				/*timeout*/timeout,
2314 				/*quiet*/0);
2315 }
2316 
2317 static int
2318 atasecurity_disable(struct cam_device *device, union ccb *ccb,
2319 		    int retry_count, u_int32_t timeout,
2320 		    struct ata_security_password *pwd, int quiet)
2321 {
2322 
2323 	if (quiet == 0)
2324 		atasecurity_notify(ATA_SECURITY_DISABLE_PASSWORD, pwd);
2325 	return ata_do_28bit_cmd(device,
2326 				ccb,
2327 				retry_count,
2328 				/*flags*/CAM_DIR_OUT,
2329 				/*protocol*/AP_PROTO_PIO_OUT,
2330 				/*tag_action*/MSG_SIMPLE_Q_TAG,
2331 				/*command*/ATA_SECURITY_DISABLE_PASSWORD,
2332 				/*features*/0,
2333 				/*lba*/0,
2334 				/*sector_count*/0,
2335 				/*data_ptr*/(u_int8_t *)pwd,
2336 				/*dxfer_len*/sizeof(*pwd),
2337 				/*timeout*/timeout,
2338 				/*quiet*/0);
2339 }
2340 
2341 
2342 static int
2343 atasecurity_erase_confirm(struct cam_device *device,
2344 			  struct ata_params* ident_buf)
2345 {
2346 
2347 	printf("\nYou are about to ERASE ALL DATA from the following"
2348 	       " device:\n%s%d,%s%d: ", device->device_name,
2349 	       device->dev_unit_num, device->given_dev_name,
2350 	       device->given_unit_number);
2351 	ata_print_ident(ident_buf);
2352 
2353 	for(;;) {
2354 		char str[50];
2355 		printf("\nAre you SURE you want to ERASE ALL DATA? (yes/no) ");
2356 
2357 		if (fgets(str, sizeof(str), stdin) != NULL) {
2358 			if (strncasecmp(str, "yes", 3) == 0) {
2359 				return (1);
2360 			} else if (strncasecmp(str, "no", 2) == 0) {
2361 				return (0);
2362 			} else {
2363 				printf("Please answer \"yes\" or "
2364 				       "\"no\"\n");
2365 			}
2366 		}
2367 	}
2368 
2369 	/* NOTREACHED */
2370 	return (0);
2371 }
2372 
2373 static int
2374 atasecurity_erase(struct cam_device *device, union ccb *ccb,
2375 		  int retry_count, u_int32_t timeout,
2376 		  u_int32_t erase_timeout,
2377 		  struct ata_security_password *pwd, int quiet)
2378 {
2379 	int error;
2380 
2381 	if (quiet == 0)
2382 		atasecurity_notify(ATA_SECURITY_ERASE_PREPARE, NULL);
2383 
2384 	error = ata_do_28bit_cmd(device,
2385 				 ccb,
2386 				 retry_count,
2387 				 /*flags*/CAM_DIR_NONE,
2388 				 /*protocol*/AP_PROTO_NON_DATA,
2389 				 /*tag_action*/MSG_SIMPLE_Q_TAG,
2390 				 /*command*/ATA_SECURITY_ERASE_PREPARE,
2391 				 /*features*/0,
2392 				 /*lba*/0,
2393 				 /*sector_count*/0,
2394 				 /*data_ptr*/NULL,
2395 				 /*dxfer_len*/0,
2396 				 /*timeout*/timeout,
2397 				 /*quiet*/0);
2398 
2399 	if (error != 0)
2400 		return error;
2401 
2402 	if (quiet == 0)
2403 		atasecurity_notify(ATA_SECURITY_ERASE_UNIT, pwd);
2404 
2405 	error = ata_do_28bit_cmd(device,
2406 				 ccb,
2407 				 retry_count,
2408 				 /*flags*/CAM_DIR_OUT,
2409 				 /*protocol*/AP_PROTO_PIO_OUT,
2410 				 /*tag_action*/MSG_SIMPLE_Q_TAG,
2411 				 /*command*/ATA_SECURITY_ERASE_UNIT,
2412 				 /*features*/0,
2413 				 /*lba*/0,
2414 				 /*sector_count*/0,
2415 				 /*data_ptr*/(u_int8_t *)pwd,
2416 				 /*dxfer_len*/sizeof(*pwd),
2417 				 /*timeout*/erase_timeout,
2418 				 /*quiet*/0);
2419 
2420 	if (error == 0 && quiet == 0)
2421 		printf("\nErase Complete\n");
2422 
2423 	return error;
2424 }
2425 
2426 static int
2427 atasecurity_set_password(struct cam_device *device, union ccb *ccb,
2428 			 int retry_count, u_int32_t timeout,
2429 			 struct ata_security_password *pwd, int quiet)
2430 {
2431 
2432 	if (quiet == 0)
2433 		atasecurity_notify(ATA_SECURITY_SET_PASSWORD, pwd);
2434 
2435 	return ata_do_28bit_cmd(device,
2436 				 ccb,
2437 				 retry_count,
2438 				 /*flags*/CAM_DIR_OUT,
2439 				 /*protocol*/AP_PROTO_PIO_OUT,
2440 				 /*tag_action*/MSG_SIMPLE_Q_TAG,
2441 				 /*command*/ATA_SECURITY_SET_PASSWORD,
2442 				 /*features*/0,
2443 				 /*lba*/0,
2444 				 /*sector_count*/0,
2445 				 /*data_ptr*/(u_int8_t *)pwd,
2446 				 /*dxfer_len*/sizeof(*pwd),
2447 				 /*timeout*/timeout,
2448 				 /*quiet*/0);
2449 }
2450 
2451 static void
2452 atasecurity_print(struct ata_params *parm)
2453 {
2454 
2455 	printf("\nSecurity Option           Value\n");
2456 	if (arglist & CAM_ARG_VERBOSE) {
2457 		printf("status                    %04x\n",
2458 		       parm->security_status);
2459 	}
2460 	printf("supported                 %s\n",
2461 		parm->security_status & ATA_SECURITY_SUPPORTED ? "yes" : "no");
2462 	if (!(parm->security_status & ATA_SECURITY_SUPPORTED))
2463 		return;
2464 	printf("enabled                   %s\n",
2465 		parm->security_status & ATA_SECURITY_ENABLED ? "yes" : "no");
2466 	printf("drive locked              %s\n",
2467 		parm->security_status & ATA_SECURITY_LOCKED ? "yes" : "no");
2468 	printf("security config frozen    %s\n",
2469 		parm->security_status & ATA_SECURITY_FROZEN ? "yes" : "no");
2470 	printf("count expired             %s\n",
2471 		parm->security_status & ATA_SECURITY_COUNT_EXP ? "yes" : "no");
2472 	printf("security level            %s\n",
2473 		parm->security_status & ATA_SECURITY_LEVEL ? "maximum" : "high");
2474 	printf("enhanced erase supported  %s\n",
2475 		parm->security_status & ATA_SECURITY_ENH_SUPP ? "yes" : "no");
2476 	printf("erase time                ");
2477 	atasecurity_print_time(parm->erase_time);
2478 	printf("\n");
2479 	printf("enhanced erase time       ");
2480 	atasecurity_print_time(parm->enhanced_erase_time);
2481 	printf("\n");
2482 	printf("master password rev       %04x%s\n",
2483 		parm->master_passwd_revision,
2484 		parm->master_passwd_revision == 0x0000 ||
2485 		parm->master_passwd_revision == 0xFFFF ?  " (unsupported)" : "");
2486 }
2487 
2488 /*
2489  * Validates and copies the password in optarg to the passed buffer.
2490  * If the password in optarg is the same length as the buffer then
2491  * the data will still be copied but no null termination will occur.
2492  */
2493 static int
2494 ata_getpwd(u_int8_t *passwd, int max, char opt)
2495 {
2496 	int len;
2497 
2498 	len = strlen(optarg);
2499 	if (len > max) {
2500 		warnx("-%c password is too long", opt);
2501 		return (1);
2502 	} else if (len == 0) {
2503 		warnx("-%c password is missing", opt);
2504 		return (1);
2505 	} else if (optarg[0] == '-'){
2506 		warnx("-%c password starts with '-' (generic arg?)", opt);
2507 		return (1);
2508 	} else if (strlen(passwd) != 0 && strcmp(passwd, optarg) != 0) {
2509 		warnx("-%c password conflicts with existing password from -%c",
2510 		      opt, pwd_opt);
2511 		return (1);
2512 	}
2513 
2514 	/* Callers pass in a buffer which does NOT need to be terminated */
2515 	strncpy(passwd, optarg, max);
2516 	pwd_opt = opt;
2517 
2518 	return (0);
2519 }
2520 
2521 enum {
2522 	ATA_HPA_ACTION_PRINT,
2523 	ATA_HPA_ACTION_SET_MAX,
2524 	ATA_HPA_ACTION_SET_PWD,
2525 	ATA_HPA_ACTION_LOCK,
2526 	ATA_HPA_ACTION_UNLOCK,
2527 	ATA_HPA_ACTION_FREEZE_LOCK
2528 };
2529 
2530 static int
2531 atahpa_set_confirm(struct cam_device *device, struct ata_params* ident_buf,
2532 		   u_int64_t maxsize, int persist)
2533 {
2534 	printf("\nYou are about to configure HPA to limit the user accessible\n"
2535 	       "sectors to %ju %s on the device:\n%s%d,%s%d: ", maxsize,
2536 	       persist ? "persistently" : "temporarily",
2537 	       device->device_name, device->dev_unit_num,
2538 	       device->given_dev_name, device->given_unit_number);
2539 	ata_print_ident(ident_buf);
2540 
2541 	for(;;) {
2542 		char str[50];
2543 		printf("\nAre you SURE you want to configure HPA? (yes/no) ");
2544 
2545 		if (NULL != fgets(str, sizeof(str), stdin)) {
2546 			if (0 == strncasecmp(str, "yes", 3)) {
2547 				return (1);
2548 			} else if (0 == strncasecmp(str, "no", 2)) {
2549 				return (0);
2550 			} else {
2551 				printf("Please answer \"yes\" or "
2552 				       "\"no\"\n");
2553 			}
2554 		}
2555 	}
2556 
2557 	/* NOTREACHED */
2558 	return (0);
2559 }
2560 
2561 static int
2562 atahpa(struct cam_device *device, int retry_count, int timeout,
2563        int argc, char **argv, char *combinedopt)
2564 {
2565 	union ccb *ccb;
2566 	struct ata_params *ident_buf;
2567 	struct ccb_getdev cgd;
2568 	struct ata_set_max_pwd pwd;
2569 	int error, confirm, quiet, c, action, actions, setpwd, persist;
2570 	int security, is48bit, pwdsize;
2571 	u_int64_t hpasize, maxsize;
2572 
2573 	actions = 0;
2574 	setpwd = 0;
2575 	confirm = 0;
2576 	quiet = 0;
2577 	maxsize = 0;
2578 	persist = 0;
2579 	security = 0;
2580 
2581 	memset(&pwd, 0, sizeof(pwd));
2582 
2583 	/* default action is to print hpa information */
2584 	action = ATA_HPA_ACTION_PRINT;
2585 	pwdsize = sizeof(pwd.password);
2586 
2587 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2588 		switch(c){
2589 		case 's':
2590 			action = ATA_HPA_ACTION_SET_MAX;
2591 			maxsize = strtoumax(optarg, NULL, 0);
2592 			actions++;
2593 			break;
2594 
2595 		case 'p':
2596 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2597 				return (1);
2598 			action = ATA_HPA_ACTION_SET_PWD;
2599 			security = 1;
2600 			actions++;
2601 			break;
2602 
2603 		case 'l':
2604 			action = ATA_HPA_ACTION_LOCK;
2605 			security = 1;
2606 			actions++;
2607 			break;
2608 
2609 		case 'U':
2610 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2611 				return (1);
2612 			action = ATA_HPA_ACTION_UNLOCK;
2613 			security = 1;
2614 			actions++;
2615 			break;
2616 
2617 		case 'f':
2618 			action = ATA_HPA_ACTION_FREEZE_LOCK;
2619 			security = 1;
2620 			actions++;
2621 			break;
2622 
2623 		case 'P':
2624 			persist = 1;
2625 			break;
2626 
2627 		case 'y':
2628 			confirm++;
2629 			break;
2630 
2631 		case 'q':
2632 			quiet++;
2633 			break;
2634 		}
2635 	}
2636 
2637 	if (actions > 1) {
2638 		warnx("too many hpa actions specified");
2639 		return (1);
2640 	}
2641 
2642 	if (get_cgd(device, &cgd) != 0) {
2643 		warnx("couldn't get CGD");
2644 		return (1);
2645 	}
2646 
2647 	ccb = cam_getccb(device);
2648 	if (ccb == NULL) {
2649 		warnx("couldn't allocate CCB");
2650 		return (1);
2651 	}
2652 
2653 	error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2654 	if (error != 0) {
2655 		cam_freeccb(ccb);
2656 		return (1);
2657 	}
2658 
2659 	if (quiet == 0) {
2660 		printf("%s%d: ", device->device_name, device->dev_unit_num);
2661 		ata_print_ident(ident_buf);
2662 		camxferrate(device);
2663 	}
2664 
2665 	if (action == ATA_HPA_ACTION_PRINT) {
2666 		error = ata_read_native_max(device, retry_count, timeout, ccb,
2667 					    ident_buf, &hpasize);
2668 		if (error == 0)
2669 			atahpa_print(ident_buf, hpasize, 1);
2670 
2671 		cam_freeccb(ccb);
2672 		free(ident_buf);
2673 		return (error);
2674 	}
2675 
2676 	if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) {
2677 		warnx("HPA is not supported by this device");
2678 		cam_freeccb(ccb);
2679 		free(ident_buf);
2680 		return (1);
2681 	}
2682 
2683 	if (security && !(ident_buf->support.command1 & ATA_SUPPORT_MAXSECURITY)) {
2684 		warnx("HPA Security is not supported by this device");
2685 		cam_freeccb(ccb);
2686 		free(ident_buf);
2687 		return (1);
2688 	}
2689 
2690 	is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48;
2691 
2692 	/*
2693 	 * The ATA spec requires:
2694 	 * 1. Read native max addr is called directly before set max addr
2695 	 * 2. Read native max addr is NOT called before any other set max call
2696 	 */
2697 	switch(action) {
2698 	case ATA_HPA_ACTION_SET_MAX:
2699 		if (confirm == 0 &&
2700 		    atahpa_set_confirm(device, ident_buf, maxsize,
2701 		    persist) == 0) {
2702 			cam_freeccb(ccb);
2703 			free(ident_buf);
2704 			return (1);
2705 		}
2706 
2707 		error = ata_read_native_max(device, retry_count, timeout,
2708 					    ccb, ident_buf, &hpasize);
2709 		if (error == 0) {
2710 			error = atahpa_set_max(device, retry_count, timeout,
2711 					       ccb, is48bit, maxsize, persist);
2712 			if (error == 0) {
2713 				/* redo identify to get new lba values */
2714 				error = ata_do_identify(device, retry_count,
2715 							timeout, ccb,
2716 							&ident_buf);
2717 				atahpa_print(ident_buf, hpasize, 1);
2718 			}
2719 		}
2720 		break;
2721 
2722 	case ATA_HPA_ACTION_SET_PWD:
2723 		error = atahpa_password(device, retry_count, timeout,
2724 					ccb, is48bit, &pwd);
2725 		if (error == 0)
2726 			printf("HPA password has been set\n");
2727 		break;
2728 
2729 	case ATA_HPA_ACTION_LOCK:
2730 		error = atahpa_lock(device, retry_count, timeout,
2731 				    ccb, is48bit);
2732 		if (error == 0)
2733 			printf("HPA has been locked\n");
2734 		break;
2735 
2736 	case ATA_HPA_ACTION_UNLOCK:
2737 		error = atahpa_unlock(device, retry_count, timeout,
2738 				      ccb, is48bit, &pwd);
2739 		if (error == 0)
2740 			printf("HPA has been unlocked\n");
2741 		break;
2742 
2743 	case ATA_HPA_ACTION_FREEZE_LOCK:
2744 		error = atahpa_freeze_lock(device, retry_count, timeout,
2745 					   ccb, is48bit);
2746 		if (error == 0)
2747 			printf("HPA has been frozen\n");
2748 		break;
2749 
2750 	default:
2751 		errx(1, "Option currently not supported");
2752 	}
2753 
2754 	cam_freeccb(ccb);
2755 	free(ident_buf);
2756 
2757 	return (error);
2758 }
2759 
2760 static int
2761 atasecurity(struct cam_device *device, int retry_count, int timeout,
2762 	    int argc, char **argv, char *combinedopt)
2763 {
2764 	union ccb *ccb;
2765 	struct ata_params *ident_buf;
2766 	int error, confirm, quiet, c, action, actions, setpwd;
2767 	int security_enabled, erase_timeout, pwdsize;
2768 	struct ata_security_password pwd;
2769 
2770 	actions = 0;
2771 	setpwd = 0;
2772 	erase_timeout = 0;
2773 	confirm = 0;
2774 	quiet = 0;
2775 
2776 	memset(&pwd, 0, sizeof(pwd));
2777 
2778 	/* default action is to print security information */
2779 	action = ATA_SECURITY_ACTION_PRINT;
2780 
2781 	/* user is master by default as its safer that way */
2782 	pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2783 	pwdsize = sizeof(pwd.password);
2784 
2785 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2786 		switch(c){
2787 		case 'f':
2788 			action = ATA_SECURITY_ACTION_FREEZE;
2789 			actions++;
2790 			break;
2791 
2792 		case 'U':
2793 			if (strcasecmp(optarg, "user") == 0) {
2794 				pwd.ctrl |= ATA_SECURITY_PASSWORD_USER;
2795 				pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER;
2796 			} else if (strcasecmp(optarg, "master") == 0) {
2797 				pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2798 				pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER;
2799 			} else {
2800 				warnx("-U argument '%s' is invalid (must be "
2801 				      "'user' or 'master')", optarg);
2802 				return (1);
2803 			}
2804 			break;
2805 
2806 		case 'l':
2807 			if (strcasecmp(optarg, "high") == 0) {
2808 				pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH;
2809 				pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM;
2810 			} else if (strcasecmp(optarg, "maximum") == 0) {
2811 				pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM;
2812 				pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH;
2813 			} else {
2814 				warnx("-l argument '%s' is unknown (must be "
2815 				      "'high' or 'maximum')", optarg);
2816 				return (1);
2817 			}
2818 			break;
2819 
2820 		case 'k':
2821 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2822 				return (1);
2823 			action = ATA_SECURITY_ACTION_UNLOCK;
2824 			actions++;
2825 			break;
2826 
2827 		case 'd':
2828 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2829 				return (1);
2830 			action = ATA_SECURITY_ACTION_DISABLE;
2831 			actions++;
2832 			break;
2833 
2834 		case 'e':
2835 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2836 				return (1);
2837 			action = ATA_SECURITY_ACTION_ERASE;
2838 			actions++;
2839 			break;
2840 
2841 		case 'h':
2842 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2843 				return (1);
2844 			pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED;
2845 			action = ATA_SECURITY_ACTION_ERASE_ENHANCED;
2846 			actions++;
2847 			break;
2848 
2849 		case 's':
2850 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2851 				return (1);
2852 			setpwd = 1;
2853 			if (action == ATA_SECURITY_ACTION_PRINT)
2854 				action = ATA_SECURITY_ACTION_SET_PASSWORD;
2855 			/*
2856 			 * Don't increment action as this can be combined
2857 			 * with other actions.
2858 			 */
2859 			break;
2860 
2861 		case 'y':
2862 			confirm++;
2863 			break;
2864 
2865 		case 'q':
2866 			quiet++;
2867 			break;
2868 
2869 		case 'T':
2870 			erase_timeout = atoi(optarg) * 1000;
2871 			break;
2872 		}
2873 	}
2874 
2875 	if (actions > 1) {
2876 		warnx("too many security actions specified");
2877 		return (1);
2878 	}
2879 
2880 	if ((ccb = cam_getccb(device)) == NULL) {
2881 		warnx("couldn't allocate CCB");
2882 		return (1);
2883 	}
2884 
2885 	error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2886 	if (error != 0) {
2887 		cam_freeccb(ccb);
2888 		return (1);
2889 	}
2890 
2891 	if (quiet == 0) {
2892 		printf("%s%d: ", device->device_name, device->dev_unit_num);
2893 		ata_print_ident(ident_buf);
2894 		camxferrate(device);
2895 	}
2896 
2897 	if (action == ATA_SECURITY_ACTION_PRINT) {
2898 		atasecurity_print(ident_buf);
2899 		free(ident_buf);
2900 		cam_freeccb(ccb);
2901 		return (0);
2902 	}
2903 
2904 	if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) {
2905 		warnx("Security not supported");
2906 		free(ident_buf);
2907 		cam_freeccb(ccb);
2908 		return (1);
2909 	}
2910 
2911 	/* default timeout 15 seconds the same as linux hdparm */
2912 	timeout = timeout ? timeout : 15 * 1000;
2913 
2914 	security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED;
2915 
2916 	/* first set the password if requested */
2917 	if (setpwd == 1) {
2918 		/* confirm we can erase before setting the password if erasing */
2919 		if (confirm == 0 &&
2920 		    (action == ATA_SECURITY_ACTION_ERASE_ENHANCED ||
2921 		    action == ATA_SECURITY_ACTION_ERASE) &&
2922 		    atasecurity_erase_confirm(device, ident_buf) == 0) {
2923 			cam_freeccb(ccb);
2924 			free(ident_buf);
2925 			return (error);
2926 		}
2927 
2928 		if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) {
2929 			pwd.revision = ident_buf->master_passwd_revision;
2930 			if (pwd.revision != 0 && pwd.revision != 0xfff &&
2931 			    --pwd.revision == 0) {
2932 				pwd.revision = 0xfffe;
2933 			}
2934 		}
2935 		error = atasecurity_set_password(device, ccb, retry_count,
2936 						 timeout, &pwd, quiet);
2937 		if (error != 0) {
2938 			cam_freeccb(ccb);
2939 			free(ident_buf);
2940 			return (error);
2941 		}
2942 		security_enabled = 1;
2943 	}
2944 
2945 	switch(action) {
2946 	case ATA_SECURITY_ACTION_FREEZE:
2947 		error = atasecurity_freeze(device, ccb, retry_count,
2948 					   timeout, quiet);
2949 		break;
2950 
2951 	case ATA_SECURITY_ACTION_UNLOCK:
2952 		if (security_enabled) {
2953 			if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2954 				error = atasecurity_unlock(device, ccb,
2955 					retry_count, timeout, &pwd, quiet);
2956 			} else {
2957 				warnx("Can't unlock, drive is not locked");
2958 				error = 1;
2959 			}
2960 		} else {
2961 			warnx("Can't unlock, security is disabled");
2962 			error = 1;
2963 		}
2964 		break;
2965 
2966 	case ATA_SECURITY_ACTION_DISABLE:
2967 		if (security_enabled) {
2968 			/* First unlock the drive if its locked */
2969 			if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2970 				error = atasecurity_unlock(device, ccb,
2971 							   retry_count,
2972 							   timeout,
2973 							   &pwd,
2974 							   quiet);
2975 			}
2976 
2977 			if (error == 0) {
2978 				error = atasecurity_disable(device,
2979 							    ccb,
2980 							    retry_count,
2981 							    timeout,
2982 							    &pwd,
2983 							    quiet);
2984 			}
2985 		} else {
2986 			warnx("Can't disable security (already disabled)");
2987 			error = 1;
2988 		}
2989 		break;
2990 
2991 	case ATA_SECURITY_ACTION_ERASE:
2992 		if (security_enabled) {
2993 			if (erase_timeout == 0) {
2994 				erase_timeout = atasecurity_erase_timeout_msecs(
2995 				    ident_buf->erase_time);
2996 			}
2997 
2998 			error = atasecurity_erase(device, ccb, retry_count,
2999 					          timeout, erase_timeout, &pwd,
3000 						  quiet);
3001 		} else {
3002 			warnx("Can't secure erase (security is disabled)");
3003 			error = 1;
3004 		}
3005 		break;
3006 
3007 	case ATA_SECURITY_ACTION_ERASE_ENHANCED:
3008 		if (security_enabled) {
3009 			if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) {
3010 				if (erase_timeout == 0) {
3011 					erase_timeout =
3012 					    atasecurity_erase_timeout_msecs(
3013 						ident_buf->enhanced_erase_time);
3014 				}
3015 
3016 				error = atasecurity_erase(device, ccb,
3017 							  retry_count, timeout,
3018 							  erase_timeout, &pwd,
3019 							  quiet);
3020 			} else {
3021 				warnx("Enhanced erase is not supported");
3022 				error = 1;
3023 			}
3024 		} else {
3025 			warnx("Can't secure erase (enhanced), "
3026 			      "(security is disabled)");
3027 			error = 1;
3028 		}
3029 		break;
3030 	}
3031 
3032 	cam_freeccb(ccb);
3033 	free(ident_buf);
3034 
3035 	return (error);
3036 }
3037 #endif /* MINIMALISTIC */
3038 
3039 /*
3040  * Parse out a bus, or a bus, target and lun in the following
3041  * format:
3042  * bus
3043  * bus:target
3044  * bus:target:lun
3045  *
3046  * Returns the number of parsed components, or 0.
3047  */
3048 static int
3049 parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun,
3050     cam_argmask *arglst)
3051 {
3052 	char *tmpstr;
3053 	int convs = 0;
3054 
3055 	while (isspace(*tstr) && (*tstr != '\0'))
3056 		tstr++;
3057 
3058 	tmpstr = (char *)strtok(tstr, ":");
3059 	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3060 		*bus = strtol(tmpstr, NULL, 0);
3061 		*arglst |= CAM_ARG_BUS;
3062 		convs++;
3063 		tmpstr = (char *)strtok(NULL, ":");
3064 		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3065 			*target = strtol(tmpstr, NULL, 0);
3066 			*arglst |= CAM_ARG_TARGET;
3067 			convs++;
3068 			tmpstr = (char *)strtok(NULL, ":");
3069 			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3070 				*lun = strtol(tmpstr, NULL, 0);
3071 				*arglst |= CAM_ARG_LUN;
3072 				convs++;
3073 			}
3074 		}
3075 	}
3076 
3077 	return convs;
3078 }
3079 
3080 static int
3081 dorescan_or_reset(int argc, char **argv, int rescan)
3082 {
3083 	static const char must[] =
3084 		"you must specify \"all\", a bus, or a bus:target:lun to %s";
3085 	int rv, error = 0;
3086 	path_id_t bus = CAM_BUS_WILDCARD;
3087 	target_id_t target = CAM_TARGET_WILDCARD;
3088 	lun_id_t lun = CAM_LUN_WILDCARD;
3089 	char *tstr;
3090 
3091 	if (argc < 3) {
3092 		warnx(must, rescan? "rescan" : "reset");
3093 		return(1);
3094 	}
3095 
3096 	tstr = argv[optind];
3097 	while (isspace(*tstr) && (*tstr != '\0'))
3098 		tstr++;
3099 	if (strncasecmp(tstr, "all", strlen("all")) == 0)
3100 		arglist |= CAM_ARG_BUS;
3101 	else {
3102 		rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
3103 		if (rv != 1 && rv != 3) {
3104 			warnx(must, rescan? "rescan" : "reset");
3105 			return(1);
3106 		}
3107 	}
3108 
3109 	if ((arglist & CAM_ARG_BUS)
3110 	    && (arglist & CAM_ARG_TARGET)
3111 	    && (arglist & CAM_ARG_LUN))
3112 		error = scanlun_or_reset_dev(bus, target, lun, rescan);
3113 	else
3114 		error = rescan_or_reset_bus(bus, rescan);
3115 
3116 	return(error);
3117 }
3118 
3119 static int
3120 rescan_or_reset_bus(path_id_t bus, int rescan)
3121 {
3122 	union ccb ccb, matchccb;
3123 	int fd, retval;
3124 	int bufsize;
3125 
3126 	retval = 0;
3127 
3128 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3129 		warnx("error opening transport layer device %s", XPT_DEVICE);
3130 		warn("%s", XPT_DEVICE);
3131 		return(1);
3132 	}
3133 
3134 	if (bus != CAM_BUS_WILDCARD) {
3135 		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3136 		ccb.ccb_h.path_id = bus;
3137 		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3138 		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3139 		ccb.crcn.flags = CAM_FLAG_NONE;
3140 
3141 		/* run this at a low priority */
3142 		ccb.ccb_h.pinfo.priority = 5;
3143 
3144 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3145 			warn("CAMIOCOMMAND ioctl failed");
3146 			close(fd);
3147 			return(1);
3148 		}
3149 
3150 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3151 			fprintf(stdout, "%s of bus %d was successful\n",
3152 			    rescan ? "Re-scan" : "Reset", bus);
3153 		} else {
3154 			fprintf(stdout, "%s of bus %d returned error %#x\n",
3155 				rescan ? "Re-scan" : "Reset", bus,
3156 				ccb.ccb_h.status & CAM_STATUS_MASK);
3157 			retval = 1;
3158 		}
3159 
3160 		close(fd);
3161 		return(retval);
3162 
3163 	}
3164 
3165 
3166 	/*
3167 	 * The right way to handle this is to modify the xpt so that it can
3168 	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
3169 	 * that isn't implemented, so instead we enumerate the busses and
3170 	 * send the rescan or reset to those busses in the case where the
3171 	 * given bus is -1 (wildcard).  We don't send a rescan or reset
3172 	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
3173 	 * no-op, sending a rescan to the xpt bus would result in a status of
3174 	 * CAM_REQ_INVALID.
3175 	 */
3176 	bzero(&(&matchccb.ccb_h)[1],
3177 	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
3178 	matchccb.ccb_h.func_code = XPT_DEV_MATCH;
3179 	matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
3180 	bufsize = sizeof(struct dev_match_result) * 20;
3181 	matchccb.cdm.match_buf_len = bufsize;
3182 	matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
3183 	if (matchccb.cdm.matches == NULL) {
3184 		warnx("can't malloc memory for matches");
3185 		retval = 1;
3186 		goto bailout;
3187 	}
3188 	matchccb.cdm.num_matches = 0;
3189 
3190 	matchccb.cdm.num_patterns = 1;
3191 	matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3192 
3193 	matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
3194 		matchccb.cdm.pattern_buf_len);
3195 	if (matchccb.cdm.patterns == NULL) {
3196 		warnx("can't malloc memory for patterns");
3197 		retval = 1;
3198 		goto bailout;
3199 	}
3200 	matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
3201 	matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3202 
3203 	do {
3204 		unsigned int i;
3205 
3206 		if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
3207 			warn("CAMIOCOMMAND ioctl failed");
3208 			retval = 1;
3209 			goto bailout;
3210 		}
3211 
3212 		if ((matchccb.ccb_h.status != CAM_REQ_CMP)
3213 		 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
3214 		   && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
3215 			warnx("got CAM error %#x, CDM error %d\n",
3216 			      matchccb.ccb_h.status, matchccb.cdm.status);
3217 			retval = 1;
3218 			goto bailout;
3219 		}
3220 
3221 		for (i = 0; i < matchccb.cdm.num_matches; i++) {
3222 			struct bus_match_result *bus_result;
3223 
3224 			/* This shouldn't happen. */
3225 			if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
3226 				continue;
3227 
3228 			bus_result = &matchccb.cdm.matches[i].result.bus_result;
3229 
3230 			/*
3231 			 * We don't want to rescan or reset the xpt bus.
3232 			 * See above.
3233 			 */
3234 			if (bus_result->path_id == CAM_XPT_PATH_ID)
3235 				continue;
3236 
3237 			ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3238 						       XPT_RESET_BUS;
3239 			ccb.ccb_h.path_id = bus_result->path_id;
3240 			ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3241 			ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3242 			ccb.crcn.flags = CAM_FLAG_NONE;
3243 
3244 			/* run this at a low priority */
3245 			ccb.ccb_h.pinfo.priority = 5;
3246 
3247 			if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3248 				warn("CAMIOCOMMAND ioctl failed");
3249 				retval = 1;
3250 				goto bailout;
3251 			}
3252 
3253 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
3254 				fprintf(stdout, "%s of bus %d was successful\n",
3255 					rescan? "Re-scan" : "Reset",
3256 					bus_result->path_id);
3257 			} else {
3258 				/*
3259 				 * Don't bail out just yet, maybe the other
3260 				 * rescan or reset commands will complete
3261 				 * successfully.
3262 				 */
3263 				fprintf(stderr, "%s of bus %d returned error "
3264 					"%#x\n", rescan? "Re-scan" : "Reset",
3265 					bus_result->path_id,
3266 					ccb.ccb_h.status & CAM_STATUS_MASK);
3267 				retval = 1;
3268 			}
3269 		}
3270 	} while ((matchccb.ccb_h.status == CAM_REQ_CMP)
3271 		 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
3272 
3273 bailout:
3274 
3275 	if (fd != -1)
3276 		close(fd);
3277 
3278 	if (matchccb.cdm.patterns != NULL)
3279 		free(matchccb.cdm.patterns);
3280 	if (matchccb.cdm.matches != NULL)
3281 		free(matchccb.cdm.matches);
3282 
3283 	return(retval);
3284 }
3285 
3286 static int
3287 scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3288 {
3289 	union ccb ccb;
3290 	struct cam_device *device;
3291 	int fd;
3292 
3293 	device = NULL;
3294 
3295 	if (bus == CAM_BUS_WILDCARD) {
3296 		warnx("invalid bus number %d", bus);
3297 		return(1);
3298 	}
3299 
3300 	if (target == CAM_TARGET_WILDCARD) {
3301 		warnx("invalid target number %d", target);
3302 		return(1);
3303 	}
3304 
3305 	if (lun == CAM_LUN_WILDCARD) {
3306 		warnx("invalid lun number %jx", (uintmax_t)lun);
3307 		return(1);
3308 	}
3309 
3310 	fd = -1;
3311 
3312 	bzero(&ccb, sizeof(union ccb));
3313 
3314 	if (scan) {
3315 		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3316 			warnx("error opening transport layer device %s\n",
3317 			    XPT_DEVICE);
3318 			warn("%s", XPT_DEVICE);
3319 			return(1);
3320 		}
3321 	} else {
3322 		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3323 		if (device == NULL) {
3324 			warnx("%s", cam_errbuf);
3325 			return(1);
3326 		}
3327 	}
3328 
3329 	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3330 	ccb.ccb_h.path_id = bus;
3331 	ccb.ccb_h.target_id = target;
3332 	ccb.ccb_h.target_lun = lun;
3333 	ccb.ccb_h.timeout = 5000;
3334 	ccb.crcn.flags = CAM_FLAG_NONE;
3335 
3336 	/* run this at a low priority */
3337 	ccb.ccb_h.pinfo.priority = 5;
3338 
3339 	if (scan) {
3340 		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3341 			warn("CAMIOCOMMAND ioctl failed");
3342 			close(fd);
3343 			return(1);
3344 		}
3345 	} else {
3346 		if (cam_send_ccb(device, &ccb) < 0) {
3347 			warn("error sending XPT_RESET_DEV CCB");
3348 			cam_close_device(device);
3349 			return(1);
3350 		}
3351 	}
3352 
3353 	if (scan)
3354 		close(fd);
3355 	else
3356 		cam_close_device(device);
3357 
3358 	/*
3359 	 * An error code of CAM_BDR_SENT is normal for a BDR request.
3360 	 */
3361 	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3362 	 || ((!scan)
3363 	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3364 		fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3365 		    scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3366 		return(0);
3367 	} else {
3368 		fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3369 		    scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3370 		    ccb.ccb_h.status & CAM_STATUS_MASK);
3371 		return(1);
3372 	}
3373 }
3374 
3375 #ifndef MINIMALISTIC
3376 
3377 static struct scsi_nv defect_list_type_map[] = {
3378 	{ "block", SRDD10_BLOCK_FORMAT },
3379 	{ "extbfi", SRDD10_EXT_BFI_FORMAT },
3380 	{ "extphys", SRDD10_EXT_PHYS_FORMAT },
3381 	{ "longblock", SRDD10_LONG_BLOCK_FORMAT },
3382 	{ "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3383 	{ "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3384 };
3385 
3386 static int
3387 readdefects(struct cam_device *device, int argc, char **argv,
3388 	    char *combinedopt, int retry_count, int timeout)
3389 {
3390 	union ccb *ccb = NULL;
3391 	struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3392 	struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3393 	size_t hdr_size = 0, entry_size = 0;
3394 	int use_12byte = 0;
3395 	int hex_format = 0;
3396 	u_int8_t *defect_list = NULL;
3397 	u_int8_t list_format = 0;
3398 	int list_type_set = 0;
3399 	u_int32_t dlist_length = 0;
3400 	u_int32_t returned_length = 0, valid_len = 0;
3401 	u_int32_t num_returned = 0, num_valid = 0;
3402 	u_int32_t max_possible_size = 0, hdr_max = 0;
3403 	u_int32_t starting_offset = 0;
3404 	u_int8_t returned_format, returned_type;
3405 	unsigned int i;
3406 	int summary = 0, quiet = 0;
3407 	int c, error = 0;
3408 	int lists_specified = 0;
3409 	int get_length = 1, first_pass = 1;
3410 	int mads = 0;
3411 
3412 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3413 		switch(c){
3414 		case 'f':
3415 		{
3416 			scsi_nv_status status;
3417 			int entry_num = 0;
3418 
3419 			status = scsi_get_nv(defect_list_type_map,
3420 			    sizeof(defect_list_type_map) /
3421 			    sizeof(defect_list_type_map[0]), optarg,
3422 			    &entry_num, SCSI_NV_FLAG_IG_CASE);
3423 
3424 			if (status == SCSI_NV_FOUND) {
3425 				list_format = defect_list_type_map[
3426 				    entry_num].value;
3427 				list_type_set = 1;
3428 			} else {
3429 				warnx("%s: %s %s option %s", __func__,
3430 				    (status == SCSI_NV_AMBIGUOUS) ?
3431 				    "ambiguous" : "invalid", "defect list type",
3432 				    optarg);
3433 				error = 1;
3434 				goto defect_bailout;
3435 			}
3436 			break;
3437 		}
3438 		case 'G':
3439 			arglist |= CAM_ARG_GLIST;
3440 			break;
3441 		case 'P':
3442 			arglist |= CAM_ARG_PLIST;
3443 			break;
3444 		case 'q':
3445 			quiet = 1;
3446 			break;
3447 		case 's':
3448 			summary = 1;
3449 			break;
3450 		case 'S': {
3451 			char *endptr;
3452 
3453 			starting_offset = strtoul(optarg, &endptr, 0);
3454 			if (*endptr != '\0') {
3455 				error = 1;
3456 				warnx("invalid starting offset %s", optarg);
3457 				goto defect_bailout;
3458 			}
3459 			break;
3460 		}
3461 		case 'X':
3462 			hex_format = 1;
3463 			break;
3464 		default:
3465 			break;
3466 		}
3467 	}
3468 
3469 	if (list_type_set == 0) {
3470 		error = 1;
3471 		warnx("no defect list format specified");
3472 		goto defect_bailout;
3473 	}
3474 
3475 	if (arglist & CAM_ARG_PLIST) {
3476 		list_format |= SRDD10_PLIST;
3477 		lists_specified++;
3478 	}
3479 
3480 	if (arglist & CAM_ARG_GLIST) {
3481 		list_format |= SRDD10_GLIST;
3482 		lists_specified++;
3483 	}
3484 
3485 	/*
3486 	 * This implies a summary, and was the previous behavior.
3487 	 */
3488 	if (lists_specified == 0)
3489 		summary = 1;
3490 
3491 	ccb = cam_getccb(device);
3492 
3493 retry_12byte:
3494 
3495 	/*
3496 	 * We start off asking for just the header to determine how much
3497 	 * defect data is available.  Some Hitachi drives return an error
3498 	 * if you ask for more data than the drive has.  Once we know the
3499 	 * length, we retry the command with the returned length.
3500 	 */
3501 	if (use_12byte == 0)
3502 		dlist_length = sizeof(*hdr10);
3503 	else
3504 		dlist_length = sizeof(*hdr12);
3505 
3506 retry:
3507 	if (defect_list != NULL) {
3508 		free(defect_list);
3509 		defect_list = NULL;
3510 	}
3511 	defect_list = malloc(dlist_length);
3512 	if (defect_list == NULL) {
3513 		warnx("can't malloc memory for defect list");
3514 		error = 1;
3515 		goto defect_bailout;
3516 	}
3517 
3518 next_batch:
3519 	bzero(defect_list, dlist_length);
3520 
3521 	/*
3522 	 * cam_getccb() zeros the CCB header only.  So we need to zero the
3523 	 * payload portion of the ccb.
3524 	 */
3525 	bzero(&(&ccb->ccb_h)[1],
3526 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3527 
3528 	scsi_read_defects(&ccb->csio,
3529 			  /*retries*/ retry_count,
3530 			  /*cbfcnp*/ NULL,
3531 			  /*tag_action*/ MSG_SIMPLE_Q_TAG,
3532 			  /*list_format*/ list_format,
3533 			  /*addr_desc_index*/ starting_offset,
3534 			  /*data_ptr*/ defect_list,
3535 			  /*dxfer_len*/ dlist_length,
3536 			  /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3537 			  /*sense_len*/ SSD_FULL_SIZE,
3538 			  /*timeout*/ timeout ? timeout : 5000);
3539 
3540 	/* Disable freezing the device queue */
3541 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3542 
3543 	if (cam_send_ccb(device, ccb) < 0) {
3544 		perror("error reading defect list");
3545 
3546 		if (arglist & CAM_ARG_VERBOSE) {
3547 			cam_error_print(device, ccb, CAM_ESF_ALL,
3548 					CAM_EPF_ALL, stderr);
3549 		}
3550 
3551 		error = 1;
3552 		goto defect_bailout;
3553 	}
3554 
3555 	valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3556 
3557 	if (use_12byte == 0) {
3558 		hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3559 		hdr_size = sizeof(*hdr10);
3560 		hdr_max = SRDDH10_MAX_LENGTH;
3561 
3562 		if (valid_len >= hdr_size) {
3563 			returned_length = scsi_2btoul(hdr10->length);
3564 			returned_format = hdr10->format;
3565 		} else {
3566 			returned_length = 0;
3567 			returned_format = 0;
3568 		}
3569 	} else {
3570 		hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3571 		hdr_size = sizeof(*hdr12);
3572 		hdr_max = SRDDH12_MAX_LENGTH;
3573 
3574 		if (valid_len >= hdr_size) {
3575 			returned_length = scsi_4btoul(hdr12->length);
3576 			returned_format = hdr12->format;
3577 		} else {
3578 			returned_length = 0;
3579 			returned_format = 0;
3580 		}
3581 	}
3582 
3583 	returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3584 	switch (returned_type) {
3585 	case SRDD10_BLOCK_FORMAT:
3586 		entry_size = sizeof(struct scsi_defect_desc_block);
3587 		break;
3588 	case SRDD10_LONG_BLOCK_FORMAT:
3589 		entry_size = sizeof(struct scsi_defect_desc_long_block);
3590 		break;
3591 	case SRDD10_EXT_PHYS_FORMAT:
3592 	case SRDD10_PHYSICAL_SECTOR_FORMAT:
3593 		entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3594 		break;
3595 	case SRDD10_EXT_BFI_FORMAT:
3596 	case SRDD10_BYTES_FROM_INDEX_FORMAT:
3597 		entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3598 		break;
3599 	default:
3600 		warnx("Unknown defect format 0x%x\n", returned_type);
3601 		error = 1;
3602 		goto defect_bailout;
3603 		break;
3604 	}
3605 
3606 	max_possible_size = (hdr_max / entry_size) * entry_size;
3607 	num_returned = returned_length / entry_size;
3608 	num_valid = min(returned_length, valid_len - hdr_size);
3609 	num_valid /= entry_size;
3610 
3611 	if (get_length != 0) {
3612 		get_length = 0;
3613 
3614 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3615 		     CAM_SCSI_STATUS_ERROR) {
3616 			struct scsi_sense_data *sense;
3617 			int error_code, sense_key, asc, ascq;
3618 
3619 			sense = &ccb->csio.sense_data;
3620 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
3621 			    ccb->csio.sense_resid, &error_code, &sense_key,
3622 			    &asc, &ascq, /*show_errors*/ 1);
3623 
3624 			/*
3625 			 * If the drive is reporting that it just doesn't
3626 			 * support the defect list format, go ahead and use
3627 			 * the length it reported.  Otherwise, the length
3628 			 * may not be valid, so use the maximum.
3629 			 */
3630 			if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3631 			 && (asc == 0x1c) && (ascq == 0x00)
3632 			 && (returned_length > 0)) {
3633 				if ((use_12byte == 0)
3634 				 && (returned_length >= max_possible_size)) {
3635 					get_length = 1;
3636 					use_12byte = 1;
3637 					goto retry_12byte;
3638 				}
3639 				dlist_length = returned_length + hdr_size;
3640 			} else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3641 				&& (asc == 0x1f) && (ascq == 0x00)
3642 				&& (returned_length > 0)) {
3643 				/* Partial defect list transfer */
3644 				/*
3645 				 * Hitachi drives return this error
3646 				 * along with a partial defect list if they
3647 				 * have more defects than the 10 byte
3648 				 * command can support.  Retry with the 12
3649 				 * byte command.
3650 				 */
3651 				if (use_12byte == 0) {
3652 					get_length = 1;
3653 					use_12byte = 1;
3654 					goto retry_12byte;
3655 				}
3656 				dlist_length = returned_length + hdr_size;
3657 			} else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3658 				&& (asc == 0x24) && (ascq == 0x00)) {
3659 				/* Invalid field in CDB */
3660 				/*
3661 				 * SBC-3 says that if the drive has more
3662 				 * defects than can be reported with the
3663 				 * 10 byte command, it should return this
3664 	 			 * error and no data.  Retry with the 12
3665 				 * byte command.
3666 				 */
3667 				if (use_12byte == 0) {
3668 					get_length = 1;
3669 					use_12byte = 1;
3670 					goto retry_12byte;
3671 				}
3672 				dlist_length = returned_length + hdr_size;
3673 			} else {
3674 				/*
3675 				 * If we got a SCSI error and no valid length,
3676 				 * just use the 10 byte maximum.  The 12
3677 				 * byte maximum is too large.
3678 				 */
3679 				if (returned_length == 0)
3680 					dlist_length = SRDD10_MAX_LENGTH;
3681 				else {
3682 					if ((use_12byte == 0)
3683 					 && (returned_length >=
3684 					     max_possible_size)) {
3685 						get_length = 1;
3686 						use_12byte = 1;
3687 						goto retry_12byte;
3688 					}
3689 					dlist_length = returned_length +
3690 					    hdr_size;
3691 				}
3692 			}
3693 		} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3694 			    CAM_REQ_CMP){
3695 			error = 1;
3696 			warnx("Error reading defect header");
3697 			if (arglist & CAM_ARG_VERBOSE)
3698 				cam_error_print(device, ccb, CAM_ESF_ALL,
3699 						CAM_EPF_ALL, stderr);
3700 			goto defect_bailout;
3701 		} else {
3702 			if ((use_12byte == 0)
3703 			 && (returned_length >= max_possible_size)) {
3704 				get_length = 1;
3705 				use_12byte = 1;
3706 				goto retry_12byte;
3707 			}
3708 			dlist_length = returned_length + hdr_size;
3709 		}
3710 		if (summary != 0) {
3711 			fprintf(stdout, "%u", num_returned);
3712 			if (quiet == 0) {
3713 				fprintf(stdout, " defect%s",
3714 					(num_returned != 1) ? "s" : "");
3715 			}
3716 			fprintf(stdout, "\n");
3717 
3718 			goto defect_bailout;
3719 		}
3720 
3721 		/*
3722 		 * We always limit the list length to the 10-byte maximum
3723 		 * length (0xffff).  The reason is that some controllers
3724 		 * can't handle larger I/Os, and we can transfer the entire
3725 		 * 10 byte list in one shot.  For drives that support the 12
3726 		 * byte read defects command, we'll step through the list
3727 		 * by specifying a starting offset.  For drives that don't
3728 		 * support the 12 byte command's starting offset, we'll
3729 		 * just display the first 64K.
3730 		 */
3731 		dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3732 
3733 		goto retry;
3734 	}
3735 
3736 
3737 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3738 	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3739 	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3740 		struct scsi_sense_data *sense;
3741 		int error_code, sense_key, asc, ascq;
3742 
3743 		sense = &ccb->csio.sense_data;
3744 		scsi_extract_sense_len(sense, ccb->csio.sense_len -
3745 		    ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3746 		    &ascq, /*show_errors*/ 1);
3747 
3748 		/*
3749 		 * According to the SCSI spec, if the disk doesn't support
3750 		 * the requested format, it will generally return a sense
3751 		 * key of RECOVERED ERROR, and an additional sense code
3752 		 * of "DEFECT LIST NOT FOUND".  HGST drives also return
3753 		 * Primary/Grown defect list not found errors.  So just
3754 		 * check for an ASC of 0x1c.
3755 		 */
3756 		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3757 		 && (asc == 0x1c)) {
3758 			const char *format_str;
3759 
3760 			format_str = scsi_nv_to_str(defect_list_type_map,
3761 			    sizeof(defect_list_type_map) /
3762 			    sizeof(defect_list_type_map[0]),
3763 			    list_format & SRDD10_DLIST_FORMAT_MASK);
3764 			warnx("requested defect format %s not available",
3765 			    format_str ? format_str : "unknown");
3766 
3767 			format_str = scsi_nv_to_str(defect_list_type_map,
3768 			    sizeof(defect_list_type_map) /
3769 			    sizeof(defect_list_type_map[0]), returned_type);
3770 			if (format_str != NULL) {
3771 				warnx("Device returned %s format",
3772 				    format_str);
3773 			} else {
3774 				error = 1;
3775 				warnx("Device returned unknown defect"
3776 				     " data format %#x", returned_type);
3777 				goto defect_bailout;
3778 			}
3779 		} else {
3780 			error = 1;
3781 			warnx("Error returned from read defect data command");
3782 			if (arglist & CAM_ARG_VERBOSE)
3783 				cam_error_print(device, ccb, CAM_ESF_ALL,
3784 						CAM_EPF_ALL, stderr);
3785 			goto defect_bailout;
3786 		}
3787 	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3788 		error = 1;
3789 		warnx("Error returned from read defect data command");
3790 		if (arglist & CAM_ARG_VERBOSE)
3791 			cam_error_print(device, ccb, CAM_ESF_ALL,
3792 					CAM_EPF_ALL, stderr);
3793 		goto defect_bailout;
3794 	}
3795 
3796 	if (first_pass != 0) {
3797 		fprintf(stderr, "Got %d defect", num_returned);
3798 
3799 		if ((lists_specified == 0) || (num_returned == 0)) {
3800 			fprintf(stderr, "s.\n");
3801 			goto defect_bailout;
3802 		} else if (num_returned == 1)
3803 			fprintf(stderr, ":\n");
3804 		else
3805 			fprintf(stderr, "s:\n");
3806 
3807 		first_pass = 0;
3808 	}
3809 
3810 	/*
3811 	 * XXX KDM  I should probably clean up the printout format for the
3812 	 * disk defects.
3813 	 */
3814 	switch (returned_type) {
3815 	case SRDD10_PHYSICAL_SECTOR_FORMAT:
3816 	case SRDD10_EXT_PHYS_FORMAT:
3817 	{
3818 		struct scsi_defect_desc_phys_sector *dlist;
3819 
3820 		dlist = (struct scsi_defect_desc_phys_sector *)
3821 			(defect_list + hdr_size);
3822 
3823 		for (i = 0; i < num_valid; i++) {
3824 			uint32_t sector;
3825 
3826 			sector = scsi_4btoul(dlist[i].sector);
3827 			if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
3828 				mads = (sector & SDD_EXT_PHYS_MADS) ?
3829 				       0 : 1;
3830 				sector &= ~SDD_EXT_PHYS_FLAG_MASK;
3831 			}
3832 			if (hex_format == 0)
3833 				fprintf(stdout, "%d:%d:%d%s",
3834 					scsi_3btoul(dlist[i].cylinder),
3835 					dlist[i].head,
3836 					scsi_4btoul(dlist[i].sector),
3837 					mads ? " - " : "\n");
3838 			else
3839 				fprintf(stdout, "0x%x:0x%x:0x%x%s",
3840 					scsi_3btoul(dlist[i].cylinder),
3841 					dlist[i].head,
3842 					scsi_4btoul(dlist[i].sector),
3843 					mads ? " - " : "\n");
3844 			mads = 0;
3845 		}
3846 		if (num_valid < num_returned) {
3847 			starting_offset += num_valid;
3848 			goto next_batch;
3849 		}
3850 		break;
3851 	}
3852 	case SRDD10_BYTES_FROM_INDEX_FORMAT:
3853 	case SRDD10_EXT_BFI_FORMAT:
3854 	{
3855 		struct scsi_defect_desc_bytes_from_index *dlist;
3856 
3857 		dlist = (struct scsi_defect_desc_bytes_from_index *)
3858 			(defect_list + hdr_size);
3859 
3860 		for (i = 0; i < num_valid; i++) {
3861 			uint32_t bfi;
3862 
3863 			bfi = scsi_4btoul(dlist[i].bytes_from_index);
3864 			if (returned_type == SRDD10_EXT_BFI_FORMAT) {
3865 				mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
3866 				bfi &= ~SDD_EXT_BFI_FLAG_MASK;
3867 			}
3868 			if (hex_format == 0)
3869 				fprintf(stdout, "%d:%d:%d%s",
3870 					scsi_3btoul(dlist[i].cylinder),
3871 					dlist[i].head,
3872 					scsi_4btoul(dlist[i].bytes_from_index),
3873 					mads ? " - " : "\n");
3874 			else
3875 				fprintf(stdout, "0x%x:0x%x:0x%x%s",
3876 					scsi_3btoul(dlist[i].cylinder),
3877 					dlist[i].head,
3878 					scsi_4btoul(dlist[i].bytes_from_index),
3879 					mads ? " - " : "\n");
3880 
3881 			mads = 0;
3882 		}
3883 		if (num_valid < num_returned) {
3884 			starting_offset += num_valid;
3885 			goto next_batch;
3886 		}
3887 		break;
3888 	}
3889 	case SRDDH10_BLOCK_FORMAT:
3890 	{
3891 		struct scsi_defect_desc_block *dlist;
3892 
3893 		dlist = (struct scsi_defect_desc_block *)
3894 			(defect_list + hdr_size);
3895 
3896 		for (i = 0; i < num_valid; i++) {
3897 			if (hex_format == 0)
3898 				fprintf(stdout, "%u\n",
3899 					scsi_4btoul(dlist[i].address));
3900 			else
3901 				fprintf(stdout, "0x%x\n",
3902 					scsi_4btoul(dlist[i].address));
3903 		}
3904 
3905 		if (num_valid < num_returned) {
3906 			starting_offset += num_valid;
3907 			goto next_batch;
3908 		}
3909 
3910 		break;
3911 	}
3912 	case SRDD10_LONG_BLOCK_FORMAT:
3913 	{
3914 		struct scsi_defect_desc_long_block *dlist;
3915 
3916 		dlist = (struct scsi_defect_desc_long_block *)
3917 			(defect_list + hdr_size);
3918 
3919 		for (i = 0; i < num_valid; i++) {
3920 			if (hex_format == 0)
3921 				fprintf(stdout, "%ju\n",
3922 					(uintmax_t)scsi_8btou64(
3923 					dlist[i].address));
3924 			else
3925 				fprintf(stdout, "0x%jx\n",
3926 					(uintmax_t)scsi_8btou64(
3927 					dlist[i].address));
3928 		}
3929 
3930 		if (num_valid < num_returned) {
3931 			starting_offset += num_valid;
3932 			goto next_batch;
3933 		}
3934 		break;
3935 	}
3936 	default:
3937 		fprintf(stderr, "Unknown defect format 0x%x\n",
3938 			returned_type);
3939 		error = 1;
3940 		break;
3941 	}
3942 defect_bailout:
3943 
3944 	if (defect_list != NULL)
3945 		free(defect_list);
3946 
3947 	if (ccb != NULL)
3948 		cam_freeccb(ccb);
3949 
3950 	return(error);
3951 }
3952 #endif /* MINIMALISTIC */
3953 
3954 #if 0
3955 void
3956 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3957 {
3958 	union ccb *ccb;
3959 
3960 	ccb = cam_getccb(device);
3961 
3962 	cam_freeccb(ccb);
3963 }
3964 #endif
3965 
3966 #ifndef MINIMALISTIC
3967 void
3968 mode_sense(struct cam_device *device, int mode_page, int page_control,
3969 	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3970 {
3971 	union ccb *ccb;
3972 	int retval;
3973 
3974 	ccb = cam_getccb(device);
3975 
3976 	if (ccb == NULL)
3977 		errx(1, "mode_sense: couldn't allocate CCB");
3978 
3979 	bzero(&(&ccb->ccb_h)[1],
3980 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3981 
3982 	scsi_mode_sense(&ccb->csio,
3983 			/* retries */ retry_count,
3984 			/* cbfcnp */ NULL,
3985 			/* tag_action */ MSG_SIMPLE_Q_TAG,
3986 			/* dbd */ dbd,
3987 			/* page_code */ page_control << 6,
3988 			/* page */ mode_page,
3989 			/* param_buf */ data,
3990 			/* param_len */ datalen,
3991 			/* sense_len */ SSD_FULL_SIZE,
3992 			/* timeout */ timeout ? timeout : 5000);
3993 
3994 	if (arglist & CAM_ARG_ERR_RECOVER)
3995 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3996 
3997 	/* Disable freezing the device queue */
3998 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3999 
4000 	if (((retval = cam_send_ccb(device, ccb)) < 0)
4001 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4002 		if (arglist & CAM_ARG_VERBOSE) {
4003 			cam_error_print(device, ccb, CAM_ESF_ALL,
4004 					CAM_EPF_ALL, stderr);
4005 		}
4006 		cam_freeccb(ccb);
4007 		cam_close_device(device);
4008 		if (retval < 0)
4009 			err(1, "error sending mode sense command");
4010 		else
4011 			errx(1, "error sending mode sense command");
4012 	}
4013 
4014 	cam_freeccb(ccb);
4015 }
4016 
4017 void
4018 mode_select(struct cam_device *device, int save_pages, int retry_count,
4019 	   int timeout, u_int8_t *data, int datalen)
4020 {
4021 	union ccb *ccb;
4022 	int retval;
4023 
4024 	ccb = cam_getccb(device);
4025 
4026 	if (ccb == NULL)
4027 		errx(1, "mode_select: couldn't allocate CCB");
4028 
4029 	bzero(&(&ccb->ccb_h)[1],
4030 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4031 
4032 	scsi_mode_select(&ccb->csio,
4033 			 /* retries */ retry_count,
4034 			 /* cbfcnp */ NULL,
4035 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
4036 			 /* scsi_page_fmt */ 1,
4037 			 /* save_pages */ save_pages,
4038 			 /* param_buf */ data,
4039 			 /* param_len */ datalen,
4040 			 /* sense_len */ SSD_FULL_SIZE,
4041 			 /* timeout */ timeout ? timeout : 5000);
4042 
4043 	if (arglist & CAM_ARG_ERR_RECOVER)
4044 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4045 
4046 	/* Disable freezing the device queue */
4047 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4048 
4049 	if (((retval = cam_send_ccb(device, ccb)) < 0)
4050 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4051 		if (arglist & CAM_ARG_VERBOSE) {
4052 			cam_error_print(device, ccb, CAM_ESF_ALL,
4053 					CAM_EPF_ALL, stderr);
4054 		}
4055 		cam_freeccb(ccb);
4056 		cam_close_device(device);
4057 
4058 		if (retval < 0)
4059 			err(1, "error sending mode select command");
4060 		else
4061 			errx(1, "error sending mode select command");
4062 
4063 	}
4064 
4065 	cam_freeccb(ccb);
4066 }
4067 
4068 void
4069 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4070 	 int retry_count, int timeout)
4071 {
4072 	int c, mode_page = -1, page_control = 0;
4073 	int binary = 0, list = 0;
4074 
4075 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4076 		switch(c) {
4077 		case 'b':
4078 			binary = 1;
4079 			break;
4080 		case 'd':
4081 			arglist |= CAM_ARG_DBD;
4082 			break;
4083 		case 'e':
4084 			arglist |= CAM_ARG_MODE_EDIT;
4085 			break;
4086 		case 'l':
4087 			list = 1;
4088 			break;
4089 		case 'm':
4090 			mode_page = strtol(optarg, NULL, 0);
4091 			if (mode_page < 0)
4092 				errx(1, "invalid mode page %d", mode_page);
4093 			break;
4094 		case 'P':
4095 			page_control = strtol(optarg, NULL, 0);
4096 			if ((page_control < 0) || (page_control > 3))
4097 				errx(1, "invalid page control field %d",
4098 				     page_control);
4099 			arglist |= CAM_ARG_PAGE_CNTL;
4100 			break;
4101 		default:
4102 			break;
4103 		}
4104 	}
4105 
4106 	if (mode_page == -1 && list == 0)
4107 		errx(1, "you must specify a mode page!");
4108 
4109 	if (list) {
4110 		mode_list(device, page_control, arglist & CAM_ARG_DBD,
4111 		    retry_count, timeout);
4112 	} else {
4113 		mode_edit(device, mode_page, page_control,
4114 		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
4115 		    retry_count, timeout);
4116 	}
4117 }
4118 
4119 static int
4120 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4121 	int retry_count, int timeout)
4122 {
4123 	union ccb *ccb;
4124 	u_int32_t flags = CAM_DIR_NONE;
4125 	u_int8_t *data_ptr = NULL;
4126 	u_int8_t cdb[20];
4127 	u_int8_t atacmd[12];
4128 	struct get_hook hook;
4129 	int c, data_bytes = 0;
4130 	int cdb_len = 0;
4131 	int atacmd_len = 0;
4132 	int dmacmd = 0;
4133 	int fpdmacmd = 0;
4134 	int need_res = 0;
4135 	char *datastr = NULL, *tstr, *resstr = NULL;
4136 	int error = 0;
4137 	int fd_data = 0, fd_res = 0;
4138 	int retval;
4139 
4140 	ccb = cam_getccb(device);
4141 
4142 	if (ccb == NULL) {
4143 		warnx("scsicmd: error allocating ccb");
4144 		return(1);
4145 	}
4146 
4147 	bzero(&(&ccb->ccb_h)[1],
4148 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4149 
4150 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4151 		switch(c) {
4152 		case 'a':
4153 			tstr = optarg;
4154 			while (isspace(*tstr) && (*tstr != '\0'))
4155 				tstr++;
4156 			hook.argc = argc - optind;
4157 			hook.argv = argv + optind;
4158 			hook.got = 0;
4159 			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4160 						    iget, &hook);
4161 			/*
4162 			 * Increment optind by the number of arguments the
4163 			 * encoding routine processed.  After each call to
4164 			 * getopt(3), optind points to the argument that
4165 			 * getopt should process _next_.  In this case,
4166 			 * that means it points to the first command string
4167 			 * argument, if there is one.  Once we increment
4168 			 * this, it should point to either the next command
4169 			 * line argument, or it should be past the end of
4170 			 * the list.
4171 			 */
4172 			optind += hook.got;
4173 			break;
4174 		case 'c':
4175 			tstr = optarg;
4176 			while (isspace(*tstr) && (*tstr != '\0'))
4177 				tstr++;
4178 			hook.argc = argc - optind;
4179 			hook.argv = argv + optind;
4180 			hook.got = 0;
4181 			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4182 						    iget, &hook);
4183 			/*
4184 			 * Increment optind by the number of arguments the
4185 			 * encoding routine processed.  After each call to
4186 			 * getopt(3), optind points to the argument that
4187 			 * getopt should process _next_.  In this case,
4188 			 * that means it points to the first command string
4189 			 * argument, if there is one.  Once we increment
4190 			 * this, it should point to either the next command
4191 			 * line argument, or it should be past the end of
4192 			 * the list.
4193 			 */
4194 			optind += hook.got;
4195 			break;
4196 		case 'd':
4197 			dmacmd = 1;
4198 			break;
4199 		case 'f':
4200 			fpdmacmd = 1;
4201 			break;
4202 		case 'i':
4203 			if (arglist & CAM_ARG_CMD_OUT) {
4204 				warnx("command must either be "
4205 				      "read or write, not both");
4206 				error = 1;
4207 				goto scsicmd_bailout;
4208 			}
4209 			arglist |= CAM_ARG_CMD_IN;
4210 			flags = CAM_DIR_IN;
4211 			data_bytes = strtol(optarg, NULL, 0);
4212 			if (data_bytes <= 0) {
4213 				warnx("invalid number of input bytes %d",
4214 				      data_bytes);
4215 				error = 1;
4216 				goto scsicmd_bailout;
4217 			}
4218 			hook.argc = argc - optind;
4219 			hook.argv = argv + optind;
4220 			hook.got = 0;
4221 			optind++;
4222 			datastr = cget(&hook, NULL);
4223 			/*
4224 			 * If the user supplied "-" instead of a format, he
4225 			 * wants the data to be written to stdout.
4226 			 */
4227 			if ((datastr != NULL)
4228 			 && (datastr[0] == '-'))
4229 				fd_data = 1;
4230 
4231 			data_ptr = (u_int8_t *)malloc(data_bytes);
4232 			if (data_ptr == NULL) {
4233 				warnx("can't malloc memory for data_ptr");
4234 				error = 1;
4235 				goto scsicmd_bailout;
4236 			}
4237 			break;
4238 		case 'o':
4239 			if (arglist & CAM_ARG_CMD_IN) {
4240 				warnx("command must either be "
4241 				      "read or write, not both");
4242 				error = 1;
4243 				goto scsicmd_bailout;
4244 			}
4245 			arglist |= CAM_ARG_CMD_OUT;
4246 			flags = CAM_DIR_OUT;
4247 			data_bytes = strtol(optarg, NULL, 0);
4248 			if (data_bytes <= 0) {
4249 				warnx("invalid number of output bytes %d",
4250 				      data_bytes);
4251 				error = 1;
4252 				goto scsicmd_bailout;
4253 			}
4254 			hook.argc = argc - optind;
4255 			hook.argv = argv + optind;
4256 			hook.got = 0;
4257 			datastr = cget(&hook, NULL);
4258 			data_ptr = (u_int8_t *)malloc(data_bytes);
4259 			if (data_ptr == NULL) {
4260 				warnx("can't malloc memory for data_ptr");
4261 				error = 1;
4262 				goto scsicmd_bailout;
4263 			}
4264 			bzero(data_ptr, data_bytes);
4265 			/*
4266 			 * If the user supplied "-" instead of a format, he
4267 			 * wants the data to be read from stdin.
4268 			 */
4269 			if ((datastr != NULL)
4270 			 && (datastr[0] == '-'))
4271 				fd_data = 1;
4272 			else
4273 				buff_encode_visit(data_ptr, data_bytes, datastr,
4274 						  iget, &hook);
4275 			optind += hook.got;
4276 			break;
4277 		case 'r':
4278 			need_res = 1;
4279 			hook.argc = argc - optind;
4280 			hook.argv = argv + optind;
4281 			hook.got = 0;
4282 			resstr = cget(&hook, NULL);
4283 			if ((resstr != NULL) && (resstr[0] == '-'))
4284 				fd_res = 1;
4285 			optind += hook.got;
4286 			break;
4287 		default:
4288 			break;
4289 		}
4290 	}
4291 
4292 	/*
4293 	 * If fd_data is set, and we're writing to the device, we need to
4294 	 * read the data the user wants written from stdin.
4295 	 */
4296 	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4297 		ssize_t amt_read;
4298 		int amt_to_read = data_bytes;
4299 		u_int8_t *buf_ptr = data_ptr;
4300 
4301 		for (amt_read = 0; amt_to_read > 0;
4302 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4303 			if (amt_read == -1) {
4304 				warn("error reading data from stdin");
4305 				error = 1;
4306 				goto scsicmd_bailout;
4307 			}
4308 			amt_to_read -= amt_read;
4309 			buf_ptr += amt_read;
4310 		}
4311 	}
4312 
4313 	if (arglist & CAM_ARG_ERR_RECOVER)
4314 		flags |= CAM_PASS_ERR_RECOVER;
4315 
4316 	/* Disable freezing the device queue */
4317 	flags |= CAM_DEV_QFRZDIS;
4318 
4319 	if (cdb_len) {
4320 		/*
4321 		 * This is taken from the SCSI-3 draft spec.
4322 		 * (T10/1157D revision 0.3)
4323 		 * The top 3 bits of an opcode are the group code.
4324 		 * The next 5 bits are the command code.
4325 		 * Group 0:  six byte commands
4326 		 * Group 1:  ten byte commands
4327 		 * Group 2:  ten byte commands
4328 		 * Group 3:  reserved
4329 		 * Group 4:  sixteen byte commands
4330 		 * Group 5:  twelve byte commands
4331 		 * Group 6:  vendor specific
4332 		 * Group 7:  vendor specific
4333 		 */
4334 		switch((cdb[0] >> 5) & 0x7) {
4335 			case 0:
4336 				cdb_len = 6;
4337 				break;
4338 			case 1:
4339 			case 2:
4340 				cdb_len = 10;
4341 				break;
4342 			case 3:
4343 			case 6:
4344 			case 7:
4345 			        /* computed by buff_encode_visit */
4346 				break;
4347 			case 4:
4348 				cdb_len = 16;
4349 				break;
4350 			case 5:
4351 				cdb_len = 12;
4352 				break;
4353 		}
4354 
4355 		/*
4356 		 * We should probably use csio_build_visit or something like that
4357 		 * here, but it's easier to encode arguments as you go.  The
4358 		 * alternative would be skipping the CDB argument and then encoding
4359 		 * it here, since we've got the data buffer argument by now.
4360 		 */
4361 		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4362 
4363 		cam_fill_csio(&ccb->csio,
4364 		      /*retries*/ retry_count,
4365 		      /*cbfcnp*/ NULL,
4366 		      /*flags*/ flags,
4367 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
4368 		      /*data_ptr*/ data_ptr,
4369 		      /*dxfer_len*/ data_bytes,
4370 		      /*sense_len*/ SSD_FULL_SIZE,
4371 		      /*cdb_len*/ cdb_len,
4372 		      /*timeout*/ timeout ? timeout : 5000);
4373 	} else {
4374 		atacmd_len = 12;
4375 		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4376 		if (need_res)
4377 			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4378 		if (dmacmd)
4379 			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4380 		if (fpdmacmd)
4381 			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4382 
4383 		cam_fill_ataio(&ccb->ataio,
4384 		      /*retries*/ retry_count,
4385 		      /*cbfcnp*/ NULL,
4386 		      /*flags*/ flags,
4387 		      /*tag_action*/ 0,
4388 		      /*data_ptr*/ data_ptr,
4389 		      /*dxfer_len*/ data_bytes,
4390 		      /*timeout*/ timeout ? timeout : 5000);
4391 	}
4392 
4393 	if (((retval = cam_send_ccb(device, ccb)) < 0)
4394 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4395 		const char warnstr[] = "error sending command";
4396 
4397 		if (retval < 0)
4398 			warn(warnstr);
4399 		else
4400 			warnx(warnstr);
4401 
4402 		if (arglist & CAM_ARG_VERBOSE) {
4403 			cam_error_print(device, ccb, CAM_ESF_ALL,
4404 					CAM_EPF_ALL, stderr);
4405 		}
4406 
4407 		error = 1;
4408 		goto scsicmd_bailout;
4409 	}
4410 
4411 	if (atacmd_len && need_res) {
4412 		if (fd_res == 0) {
4413 			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4414 					  arg_put, NULL);
4415 			fprintf(stdout, "\n");
4416 		} else {
4417 			fprintf(stdout,
4418 			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4419 			    ccb->ataio.res.status,
4420 			    ccb->ataio.res.error,
4421 			    ccb->ataio.res.lba_low,
4422 			    ccb->ataio.res.lba_mid,
4423 			    ccb->ataio.res.lba_high,
4424 			    ccb->ataio.res.device,
4425 			    ccb->ataio.res.lba_low_exp,
4426 			    ccb->ataio.res.lba_mid_exp,
4427 			    ccb->ataio.res.lba_high_exp,
4428 			    ccb->ataio.res.sector_count,
4429 			    ccb->ataio.res.sector_count_exp);
4430 			fflush(stdout);
4431 		}
4432 	}
4433 
4434 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4435 	 && (arglist & CAM_ARG_CMD_IN)
4436 	 && (data_bytes > 0)) {
4437 		if (fd_data == 0) {
4438 			buff_decode_visit(data_ptr, data_bytes, datastr,
4439 					  arg_put, NULL);
4440 			fprintf(stdout, "\n");
4441 		} else {
4442 			ssize_t amt_written;
4443 			int amt_to_write = data_bytes;
4444 			u_int8_t *buf_ptr = data_ptr;
4445 
4446 			for (amt_written = 0; (amt_to_write > 0) &&
4447 			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4448 				amt_to_write -= amt_written;
4449 				buf_ptr += amt_written;
4450 			}
4451 			if (amt_written == -1) {
4452 				warn("error writing data to stdout");
4453 				error = 1;
4454 				goto scsicmd_bailout;
4455 			} else if ((amt_written == 0)
4456 				&& (amt_to_write > 0)) {
4457 				warnx("only wrote %u bytes out of %u",
4458 				      data_bytes - amt_to_write, data_bytes);
4459 			}
4460 		}
4461 	}
4462 
4463 scsicmd_bailout:
4464 
4465 	if ((data_bytes > 0) && (data_ptr != NULL))
4466 		free(data_ptr);
4467 
4468 	cam_freeccb(ccb);
4469 
4470 	return(error);
4471 }
4472 
4473 static int
4474 camdebug(int argc, char **argv, char *combinedopt)
4475 {
4476 	int c, fd;
4477 	path_id_t bus = CAM_BUS_WILDCARD;
4478 	target_id_t target = CAM_TARGET_WILDCARD;
4479 	lun_id_t lun = CAM_LUN_WILDCARD;
4480 	char *tstr, *tmpstr = NULL;
4481 	union ccb ccb;
4482 	int error = 0;
4483 
4484 	bzero(&ccb, sizeof(union ccb));
4485 
4486 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4487 		switch(c) {
4488 		case 'I':
4489 			arglist |= CAM_ARG_DEBUG_INFO;
4490 			ccb.cdbg.flags |= CAM_DEBUG_INFO;
4491 			break;
4492 		case 'P':
4493 			arglist |= CAM_ARG_DEBUG_PERIPH;
4494 			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4495 			break;
4496 		case 'S':
4497 			arglist |= CAM_ARG_DEBUG_SUBTRACE;
4498 			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4499 			break;
4500 		case 'T':
4501 			arglist |= CAM_ARG_DEBUG_TRACE;
4502 			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4503 			break;
4504 		case 'X':
4505 			arglist |= CAM_ARG_DEBUG_XPT;
4506 			ccb.cdbg.flags |= CAM_DEBUG_XPT;
4507 			break;
4508 		case 'c':
4509 			arglist |= CAM_ARG_DEBUG_CDB;
4510 			ccb.cdbg.flags |= CAM_DEBUG_CDB;
4511 			break;
4512 		case 'p':
4513 			arglist |= CAM_ARG_DEBUG_PROBE;
4514 			ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4515 			break;
4516 		default:
4517 			break;
4518 		}
4519 	}
4520 
4521 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4522 		warnx("error opening transport layer device %s", XPT_DEVICE);
4523 		warn("%s", XPT_DEVICE);
4524 		return(1);
4525 	}
4526 	argc -= optind;
4527 	argv += optind;
4528 
4529 	if (argc <= 0) {
4530 		warnx("you must specify \"off\", \"all\" or a bus,");
4531 		warnx("bus:target, or bus:target:lun");
4532 		close(fd);
4533 		return(1);
4534 	}
4535 
4536 	tstr = *argv;
4537 
4538 	while (isspace(*tstr) && (*tstr != '\0'))
4539 		tstr++;
4540 
4541 	if (strncmp(tstr, "off", 3) == 0) {
4542 		ccb.cdbg.flags = CAM_DEBUG_NONE;
4543 		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4544 			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4545 			     CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4546 	} else if (strncmp(tstr, "all", 3) != 0) {
4547 		tmpstr = (char *)strtok(tstr, ":");
4548 		if ((tmpstr != NULL) && (*tmpstr != '\0')){
4549 			bus = strtol(tmpstr, NULL, 0);
4550 			arglist |= CAM_ARG_BUS;
4551 			tmpstr = (char *)strtok(NULL, ":");
4552 			if ((tmpstr != NULL) && (*tmpstr != '\0')){
4553 				target = strtol(tmpstr, NULL, 0);
4554 				arglist |= CAM_ARG_TARGET;
4555 				tmpstr = (char *)strtok(NULL, ":");
4556 				if ((tmpstr != NULL) && (*tmpstr != '\0')){
4557 					lun = strtol(tmpstr, NULL, 0);
4558 					arglist |= CAM_ARG_LUN;
4559 				}
4560 			}
4561 		} else {
4562 			error = 1;
4563 			warnx("you must specify \"all\", \"off\", or a bus,");
4564 			warnx("bus:target, or bus:target:lun to debug");
4565 		}
4566 	}
4567 
4568 	if (error == 0) {
4569 
4570 		ccb.ccb_h.func_code = XPT_DEBUG;
4571 		ccb.ccb_h.path_id = bus;
4572 		ccb.ccb_h.target_id = target;
4573 		ccb.ccb_h.target_lun = lun;
4574 
4575 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4576 			warn("CAMIOCOMMAND ioctl failed");
4577 			error = 1;
4578 		}
4579 
4580 		if (error == 0) {
4581 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4582 			     CAM_FUNC_NOTAVAIL) {
4583 				warnx("CAM debugging not available");
4584 				warnx("you need to put options CAMDEBUG in"
4585 				      " your kernel config file!");
4586 				error = 1;
4587 			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4588 				    CAM_REQ_CMP) {
4589 				warnx("XPT_DEBUG CCB failed with status %#x",
4590 				      ccb.ccb_h.status);
4591 				error = 1;
4592 			} else {
4593 				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4594 					fprintf(stderr,
4595 						"Debugging turned off\n");
4596 				} else {
4597 					fprintf(stderr,
4598 						"Debugging enabled for "
4599 						"%d:%d:%jx\n",
4600 						bus, target, (uintmax_t)lun);
4601 				}
4602 			}
4603 		}
4604 		close(fd);
4605 	}
4606 
4607 	return(error);
4608 }
4609 
4610 static int
4611 tagcontrol(struct cam_device *device, int argc, char **argv,
4612 	   char *combinedopt)
4613 {
4614 	int c;
4615 	union ccb *ccb;
4616 	int numtags = -1;
4617 	int retval = 0;
4618 	int quiet = 0;
4619 	char pathstr[1024];
4620 
4621 	ccb = cam_getccb(device);
4622 
4623 	if (ccb == NULL) {
4624 		warnx("tagcontrol: error allocating ccb");
4625 		return(1);
4626 	}
4627 
4628 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4629 		switch(c) {
4630 		case 'N':
4631 			numtags = strtol(optarg, NULL, 0);
4632 			if (numtags < 0) {
4633 				warnx("tag count %d is < 0", numtags);
4634 				retval = 1;
4635 				goto tagcontrol_bailout;
4636 			}
4637 			break;
4638 		case 'q':
4639 			quiet++;
4640 			break;
4641 		default:
4642 			break;
4643 		}
4644 	}
4645 
4646 	cam_path_string(device, pathstr, sizeof(pathstr));
4647 
4648 	if (numtags >= 0) {
4649 		bzero(&(&ccb->ccb_h)[1],
4650 		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4651 		ccb->ccb_h.func_code = XPT_REL_SIMQ;
4652 		ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4653 		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4654 		ccb->crs.openings = numtags;
4655 
4656 
4657 		if (cam_send_ccb(device, ccb) < 0) {
4658 			perror("error sending XPT_REL_SIMQ CCB");
4659 			retval = 1;
4660 			goto tagcontrol_bailout;
4661 		}
4662 
4663 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4664 			warnx("XPT_REL_SIMQ CCB failed");
4665 			cam_error_print(device, ccb, CAM_ESF_ALL,
4666 					CAM_EPF_ALL, stderr);
4667 			retval = 1;
4668 			goto tagcontrol_bailout;
4669 		}
4670 
4671 
4672 		if (quiet == 0)
4673 			fprintf(stdout, "%stagged openings now %d\n",
4674 				pathstr, ccb->crs.openings);
4675 	}
4676 
4677 	bzero(&(&ccb->ccb_h)[1],
4678 	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4679 
4680 	ccb->ccb_h.func_code = XPT_GDEV_STATS;
4681 
4682 	if (cam_send_ccb(device, ccb) < 0) {
4683 		perror("error sending XPT_GDEV_STATS CCB");
4684 		retval = 1;
4685 		goto tagcontrol_bailout;
4686 	}
4687 
4688 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4689 		warnx("XPT_GDEV_STATS CCB failed");
4690 		cam_error_print(device, ccb, CAM_ESF_ALL,
4691 				CAM_EPF_ALL, stderr);
4692 		retval = 1;
4693 		goto tagcontrol_bailout;
4694 	}
4695 
4696 	if (arglist & CAM_ARG_VERBOSE) {
4697 		fprintf(stdout, "%s", pathstr);
4698 		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4699 		fprintf(stdout, "%s", pathstr);
4700 		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4701 		fprintf(stdout, "%s", pathstr);
4702 		fprintf(stdout, "allocated     %d\n", ccb->cgds.allocated);
4703 		fprintf(stdout, "%s", pathstr);
4704 		fprintf(stdout, "queued        %d\n", ccb->cgds.queued);
4705 		fprintf(stdout, "%s", pathstr);
4706 		fprintf(stdout, "held          %d\n", ccb->cgds.held);
4707 		fprintf(stdout, "%s", pathstr);
4708 		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4709 		fprintf(stdout, "%s", pathstr);
4710 		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4711 	} else {
4712 		if (quiet == 0) {
4713 			fprintf(stdout, "%s", pathstr);
4714 			fprintf(stdout, "device openings: ");
4715 		}
4716 		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4717 			ccb->cgds.dev_active);
4718 	}
4719 
4720 tagcontrol_bailout:
4721 
4722 	cam_freeccb(ccb);
4723 	return(retval);
4724 }
4725 
4726 static void
4727 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4728 {
4729 	char pathstr[1024];
4730 
4731 	cam_path_string(device, pathstr, sizeof(pathstr));
4732 
4733 	if (cts->transport == XPORT_SPI) {
4734 		struct ccb_trans_settings_spi *spi =
4735 		    &cts->xport_specific.spi;
4736 
4737 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4738 
4739 			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4740 				spi->sync_period);
4741 
4742 			if (spi->sync_offset != 0) {
4743 				u_int freq;
4744 
4745 				freq = scsi_calc_syncsrate(spi->sync_period);
4746 				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4747 					pathstr, freq / 1000, freq % 1000);
4748 			}
4749 		}
4750 
4751 		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4752 			fprintf(stdout, "%soffset: %d\n", pathstr,
4753 			    spi->sync_offset);
4754 		}
4755 
4756 		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4757 			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4758 				(0x01 << spi->bus_width) * 8);
4759 		}
4760 
4761 		if (spi->valid & CTS_SPI_VALID_DISC) {
4762 			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4763 				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4764 				"enabled" : "disabled");
4765 		}
4766 	}
4767 	if (cts->transport == XPORT_FC) {
4768 		struct ccb_trans_settings_fc *fc =
4769 		    &cts->xport_specific.fc;
4770 
4771 		if (fc->valid & CTS_FC_VALID_WWNN)
4772 			fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4773 			    (long long) fc->wwnn);
4774 		if (fc->valid & CTS_FC_VALID_WWPN)
4775 			fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4776 			    (long long) fc->wwpn);
4777 		if (fc->valid & CTS_FC_VALID_PORT)
4778 			fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4779 		if (fc->valid & CTS_FC_VALID_SPEED)
4780 			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4781 			    pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4782 	}
4783 	if (cts->transport == XPORT_SAS) {
4784 		struct ccb_trans_settings_sas *sas =
4785 		    &cts->xport_specific.sas;
4786 
4787 		if (sas->valid & CTS_SAS_VALID_SPEED)
4788 			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4789 			    pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4790 	}
4791 	if (cts->transport == XPORT_ATA) {
4792 		struct ccb_trans_settings_pata *pata =
4793 		    &cts->xport_specific.ata;
4794 
4795 		if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4796 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4797 				ata_mode2string(pata->mode));
4798 		}
4799 		if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4800 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4801 				pata->atapi);
4802 		}
4803 		if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4804 			fprintf(stdout, "%sPIO transaction length: %d\n",
4805 				pathstr, pata->bytecount);
4806 		}
4807 	}
4808 	if (cts->transport == XPORT_SATA) {
4809 		struct ccb_trans_settings_sata *sata =
4810 		    &cts->xport_specific.sata;
4811 
4812 		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4813 			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4814 				sata->revision);
4815 		}
4816 		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4817 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4818 				ata_mode2string(sata->mode));
4819 		}
4820 		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4821 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4822 				sata->atapi);
4823 		}
4824 		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4825 			fprintf(stdout, "%sPIO transaction length: %d\n",
4826 				pathstr, sata->bytecount);
4827 		}
4828 		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4829 			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4830 				sata->pm_present);
4831 		}
4832 		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4833 			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4834 				sata->tags);
4835 		}
4836 		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4837 			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4838 				sata->caps);
4839 		}
4840 	}
4841 	if (cts->protocol == PROTO_ATA) {
4842 		struct ccb_trans_settings_ata *ata=
4843 		    &cts->proto_specific.ata;
4844 
4845 		if (ata->valid & CTS_ATA_VALID_TQ) {
4846 			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4847 				(ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4848 				"enabled" : "disabled");
4849 		}
4850 	}
4851 	if (cts->protocol == PROTO_SCSI) {
4852 		struct ccb_trans_settings_scsi *scsi=
4853 		    &cts->proto_specific.scsi;
4854 
4855 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
4856 			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4857 				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4858 				"enabled" : "disabled");
4859 		}
4860 	}
4861 
4862 }
4863 
4864 /*
4865  * Get a path inquiry CCB for the specified device.
4866  */
4867 static int
4868 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4869 {
4870 	union ccb *ccb;
4871 	int retval = 0;
4872 
4873 	ccb = cam_getccb(device);
4874 	if (ccb == NULL) {
4875 		warnx("get_cpi: couldn't allocate CCB");
4876 		return(1);
4877 	}
4878 	bzero(&(&ccb->ccb_h)[1],
4879 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4880 	ccb->ccb_h.func_code = XPT_PATH_INQ;
4881 	if (cam_send_ccb(device, ccb) < 0) {
4882 		warn("get_cpi: error sending Path Inquiry CCB");
4883 		if (arglist & CAM_ARG_VERBOSE)
4884 			cam_error_print(device, ccb, CAM_ESF_ALL,
4885 					CAM_EPF_ALL, stderr);
4886 		retval = 1;
4887 		goto get_cpi_bailout;
4888 	}
4889 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4890 		if (arglist & CAM_ARG_VERBOSE)
4891 			cam_error_print(device, ccb, CAM_ESF_ALL,
4892 					CAM_EPF_ALL, stderr);
4893 		retval = 1;
4894 		goto get_cpi_bailout;
4895 	}
4896 	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4897 
4898 get_cpi_bailout:
4899 	cam_freeccb(ccb);
4900 	return(retval);
4901 }
4902 
4903 /*
4904  * Get a get device CCB for the specified device.
4905  */
4906 static int
4907 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4908 {
4909 	union ccb *ccb;
4910 	int retval = 0;
4911 
4912 	ccb = cam_getccb(device);
4913 	if (ccb == NULL) {
4914 		warnx("get_cgd: couldn't allocate CCB");
4915 		return(1);
4916 	}
4917 	bzero(&(&ccb->ccb_h)[1],
4918 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4919 	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4920 	if (cam_send_ccb(device, ccb) < 0) {
4921 		warn("get_cgd: error sending Path Inquiry CCB");
4922 		if (arglist & CAM_ARG_VERBOSE)
4923 			cam_error_print(device, ccb, CAM_ESF_ALL,
4924 					CAM_EPF_ALL, stderr);
4925 		retval = 1;
4926 		goto get_cgd_bailout;
4927 	}
4928 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4929 		if (arglist & CAM_ARG_VERBOSE)
4930 			cam_error_print(device, ccb, CAM_ESF_ALL,
4931 					CAM_EPF_ALL, stderr);
4932 		retval = 1;
4933 		goto get_cgd_bailout;
4934 	}
4935 	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4936 
4937 get_cgd_bailout:
4938 	cam_freeccb(ccb);
4939 	return(retval);
4940 }
4941 
4942 /* return the type of disk (really the command type) */
4943 static const char *
4944 get_disk_type(struct cam_device *device)
4945 {
4946 	struct ccb_getdev	cgd;
4947 
4948 	(void) memset(&cgd, 0x0, sizeof(cgd));
4949 	get_cgd(device, &cgd);
4950 	switch(cgd.protocol) {
4951 	case PROTO_SCSI:
4952 		return "scsi";
4953 	case PROTO_ATA:
4954 	case PROTO_ATAPI:
4955 	case PROTO_SATAPM:
4956 		return "ata";
4957 	default:
4958 		return "unknown";
4959 	}
4960 }
4961 
4962 static void
4963 cpi_print(struct ccb_pathinq *cpi)
4964 {
4965 	char adapter_str[1024];
4966 	int i;
4967 
4968 	snprintf(adapter_str, sizeof(adapter_str),
4969 		 "%s%d:", cpi->dev_name, cpi->unit_number);
4970 
4971 	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
4972 		cpi->version_num);
4973 
4974 	for (i = 1; i < 0xff; i = i << 1) {
4975 		const char *str;
4976 
4977 		if ((i & cpi->hba_inquiry) == 0)
4978 			continue;
4979 
4980 		fprintf(stdout, "%s supports ", adapter_str);
4981 
4982 		switch(i) {
4983 		case PI_MDP_ABLE:
4984 			str = "MDP message";
4985 			break;
4986 		case PI_WIDE_32:
4987 			str = "32 bit wide SCSI";
4988 			break;
4989 		case PI_WIDE_16:
4990 			str = "16 bit wide SCSI";
4991 			break;
4992 		case PI_SDTR_ABLE:
4993 			str = "SDTR message";
4994 			break;
4995 		case PI_LINKED_CDB:
4996 			str = "linked CDBs";
4997 			break;
4998 		case PI_TAG_ABLE:
4999 			str = "tag queue messages";
5000 			break;
5001 		case PI_SOFT_RST:
5002 			str = "soft reset alternative";
5003 			break;
5004 		case PI_SATAPM:
5005 			str = "SATA Port Multiplier";
5006 			break;
5007 		default:
5008 			str = "unknown PI bit set";
5009 			break;
5010 		}
5011 		fprintf(stdout, "%s\n", str);
5012 	}
5013 
5014 	for (i = 1; i < 0xff; i = i << 1) {
5015 		const char *str;
5016 
5017 		if ((i & cpi->hba_misc) == 0)
5018 			continue;
5019 
5020 		fprintf(stdout, "%s ", adapter_str);
5021 
5022 		switch(i) {
5023 		case PIM_SCANHILO:
5024 			str = "bus scans from high ID to low ID";
5025 			break;
5026 		case PIM_NOREMOVE:
5027 			str = "removable devices not included in scan";
5028 			break;
5029 		case PIM_NOINITIATOR:
5030 			str = "initiator role not supported";
5031 			break;
5032 		case PIM_NOBUSRESET:
5033 			str = "user has disabled initial BUS RESET or"
5034 			      " controller is in target/mixed mode";
5035 			break;
5036 		case PIM_NO_6_BYTE:
5037 			str = "do not send 6-byte commands";
5038 			break;
5039 		case PIM_SEQSCAN:
5040 			str = "scan bus sequentially";
5041 			break;
5042 		default:
5043 			str = "unknown PIM bit set";
5044 			break;
5045 		}
5046 		fprintf(stdout, "%s\n", str);
5047 	}
5048 
5049 	for (i = 1; i < 0xff; i = i << 1) {
5050 		const char *str;
5051 
5052 		if ((i & cpi->target_sprt) == 0)
5053 			continue;
5054 
5055 		fprintf(stdout, "%s supports ", adapter_str);
5056 		switch(i) {
5057 		case PIT_PROCESSOR:
5058 			str = "target mode processor mode";
5059 			break;
5060 		case PIT_PHASE:
5061 			str = "target mode phase cog. mode";
5062 			break;
5063 		case PIT_DISCONNECT:
5064 			str = "disconnects in target mode";
5065 			break;
5066 		case PIT_TERM_IO:
5067 			str = "terminate I/O message in target mode";
5068 			break;
5069 		case PIT_GRP_6:
5070 			str = "group 6 commands in target mode";
5071 			break;
5072 		case PIT_GRP_7:
5073 			str = "group 7 commands in target mode";
5074 			break;
5075 		default:
5076 			str = "unknown PIT bit set";
5077 			break;
5078 		}
5079 
5080 		fprintf(stdout, "%s\n", str);
5081 	}
5082 	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5083 		cpi->hba_eng_cnt);
5084 	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5085 		cpi->max_target);
5086 	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5087 		cpi->max_lun);
5088 	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5089 		adapter_str, cpi->hpath_id);
5090 	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5091 		cpi->initiator_id);
5092 	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5093 	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5094 	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5095 	    adapter_str, cpi->hba_vendor);
5096 	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5097 	    adapter_str, cpi->hba_device);
5098 	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5099 	    adapter_str, cpi->hba_subvendor);
5100 	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5101 	    adapter_str, cpi->hba_subdevice);
5102 	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5103 	fprintf(stdout, "%s base transfer speed: ", adapter_str);
5104 	if (cpi->base_transfer_speed > 1000)
5105 		fprintf(stdout, "%d.%03dMB/sec\n",
5106 			cpi->base_transfer_speed / 1000,
5107 			cpi->base_transfer_speed % 1000);
5108 	else
5109 		fprintf(stdout, "%dKB/sec\n",
5110 			(cpi->base_transfer_speed % 1000) * 1000);
5111 	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5112 	    adapter_str, cpi->maxio);
5113 }
5114 
5115 static int
5116 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5117 	      struct ccb_trans_settings *cts)
5118 {
5119 	int retval;
5120 	union ccb *ccb;
5121 
5122 	retval = 0;
5123 	ccb = cam_getccb(device);
5124 
5125 	if (ccb == NULL) {
5126 		warnx("get_print_cts: error allocating ccb");
5127 		return(1);
5128 	}
5129 
5130 	bzero(&(&ccb->ccb_h)[1],
5131 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5132 
5133 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5134 
5135 	if (user_settings == 0)
5136 		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5137 	else
5138 		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5139 
5140 	if (cam_send_ccb(device, ccb) < 0) {
5141 		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5142 		if (arglist & CAM_ARG_VERBOSE)
5143 			cam_error_print(device, ccb, CAM_ESF_ALL,
5144 					CAM_EPF_ALL, stderr);
5145 		retval = 1;
5146 		goto get_print_cts_bailout;
5147 	}
5148 
5149 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5150 		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5151 		if (arglist & CAM_ARG_VERBOSE)
5152 			cam_error_print(device, ccb, CAM_ESF_ALL,
5153 					CAM_EPF_ALL, stderr);
5154 		retval = 1;
5155 		goto get_print_cts_bailout;
5156 	}
5157 
5158 	if (quiet == 0)
5159 		cts_print(device, &ccb->cts);
5160 
5161 	if (cts != NULL)
5162 		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5163 
5164 get_print_cts_bailout:
5165 
5166 	cam_freeccb(ccb);
5167 
5168 	return(retval);
5169 }
5170 
5171 static int
5172 ratecontrol(struct cam_device *device, int retry_count, int timeout,
5173 	    int argc, char **argv, char *combinedopt)
5174 {
5175 	int c;
5176 	union ccb *ccb;
5177 	int user_settings = 0;
5178 	int retval = 0;
5179 	int disc_enable = -1, tag_enable = -1;
5180 	int mode = -1;
5181 	int offset = -1;
5182 	double syncrate = -1;
5183 	int bus_width = -1;
5184 	int quiet = 0;
5185 	int change_settings = 0, send_tur = 0;
5186 	struct ccb_pathinq cpi;
5187 
5188 	ccb = cam_getccb(device);
5189 	if (ccb == NULL) {
5190 		warnx("ratecontrol: error allocating ccb");
5191 		return(1);
5192 	}
5193 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5194 		switch(c){
5195 		case 'a':
5196 			send_tur = 1;
5197 			break;
5198 		case 'c':
5199 			user_settings = 0;
5200 			break;
5201 		case 'D':
5202 			if (strncasecmp(optarg, "enable", 6) == 0)
5203 				disc_enable = 1;
5204 			else if (strncasecmp(optarg, "disable", 7) == 0)
5205 				disc_enable = 0;
5206 			else {
5207 				warnx("-D argument \"%s\" is unknown", optarg);
5208 				retval = 1;
5209 				goto ratecontrol_bailout;
5210 			}
5211 			change_settings = 1;
5212 			break;
5213 		case 'M':
5214 			mode = ata_string2mode(optarg);
5215 			if (mode < 0) {
5216 				warnx("unknown mode '%s'", optarg);
5217 				retval = 1;
5218 				goto ratecontrol_bailout;
5219 			}
5220 			change_settings = 1;
5221 			break;
5222 		case 'O':
5223 			offset = strtol(optarg, NULL, 0);
5224 			if (offset < 0) {
5225 				warnx("offset value %d is < 0", offset);
5226 				retval = 1;
5227 				goto ratecontrol_bailout;
5228 			}
5229 			change_settings = 1;
5230 			break;
5231 		case 'q':
5232 			quiet++;
5233 			break;
5234 		case 'R':
5235 			syncrate = atof(optarg);
5236 			if (syncrate < 0) {
5237 				warnx("sync rate %f is < 0", syncrate);
5238 				retval = 1;
5239 				goto ratecontrol_bailout;
5240 			}
5241 			change_settings = 1;
5242 			break;
5243 		case 'T':
5244 			if (strncasecmp(optarg, "enable", 6) == 0)
5245 				tag_enable = 1;
5246 			else if (strncasecmp(optarg, "disable", 7) == 0)
5247 				tag_enable = 0;
5248 			else {
5249 				warnx("-T argument \"%s\" is unknown", optarg);
5250 				retval = 1;
5251 				goto ratecontrol_bailout;
5252 			}
5253 			change_settings = 1;
5254 			break;
5255 		case 'U':
5256 			user_settings = 1;
5257 			break;
5258 		case 'W':
5259 			bus_width = strtol(optarg, NULL, 0);
5260 			if (bus_width < 0) {
5261 				warnx("bus width %d is < 0", bus_width);
5262 				retval = 1;
5263 				goto ratecontrol_bailout;
5264 			}
5265 			change_settings = 1;
5266 			break;
5267 		default:
5268 			break;
5269 		}
5270 	}
5271 	bzero(&(&ccb->ccb_h)[1],
5272 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5273 	/*
5274 	 * Grab path inquiry information, so we can determine whether
5275 	 * or not the initiator is capable of the things that the user
5276 	 * requests.
5277 	 */
5278 	ccb->ccb_h.func_code = XPT_PATH_INQ;
5279 	if (cam_send_ccb(device, ccb) < 0) {
5280 		perror("error sending XPT_PATH_INQ CCB");
5281 		if (arglist & CAM_ARG_VERBOSE) {
5282 			cam_error_print(device, ccb, CAM_ESF_ALL,
5283 					CAM_EPF_ALL, stderr);
5284 		}
5285 		retval = 1;
5286 		goto ratecontrol_bailout;
5287 	}
5288 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5289 		warnx("XPT_PATH_INQ CCB failed");
5290 		if (arglist & CAM_ARG_VERBOSE) {
5291 			cam_error_print(device, ccb, CAM_ESF_ALL,
5292 					CAM_EPF_ALL, stderr);
5293 		}
5294 		retval = 1;
5295 		goto ratecontrol_bailout;
5296 	}
5297 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5298 	bzero(&(&ccb->ccb_h)[1],
5299 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5300 	if (quiet == 0) {
5301 		fprintf(stdout, "%s parameters:\n",
5302 		    user_settings ? "User" : "Current");
5303 	}
5304 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5305 	if (retval != 0)
5306 		goto ratecontrol_bailout;
5307 
5308 	if (arglist & CAM_ARG_VERBOSE)
5309 		cpi_print(&cpi);
5310 
5311 	if (change_settings) {
5312 		int didsettings = 0;
5313 		struct ccb_trans_settings_spi *spi = NULL;
5314 		struct ccb_trans_settings_pata *pata = NULL;
5315 		struct ccb_trans_settings_sata *sata = NULL;
5316 		struct ccb_trans_settings_ata *ata = NULL;
5317 		struct ccb_trans_settings_scsi *scsi = NULL;
5318 
5319 		if (ccb->cts.transport == XPORT_SPI)
5320 			spi = &ccb->cts.xport_specific.spi;
5321 		if (ccb->cts.transport == XPORT_ATA)
5322 			pata = &ccb->cts.xport_specific.ata;
5323 		if (ccb->cts.transport == XPORT_SATA)
5324 			sata = &ccb->cts.xport_specific.sata;
5325 		if (ccb->cts.protocol == PROTO_ATA)
5326 			ata = &ccb->cts.proto_specific.ata;
5327 		if (ccb->cts.protocol == PROTO_SCSI)
5328 			scsi = &ccb->cts.proto_specific.scsi;
5329 		ccb->cts.xport_specific.valid = 0;
5330 		ccb->cts.proto_specific.valid = 0;
5331 		if (spi && disc_enable != -1) {
5332 			spi->valid |= CTS_SPI_VALID_DISC;
5333 			if (disc_enable == 0)
5334 				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5335 			else
5336 				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5337 			didsettings++;
5338 		}
5339 		if (tag_enable != -1) {
5340 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5341 				warnx("HBA does not support tagged queueing, "
5342 				      "so you cannot modify tag settings");
5343 				retval = 1;
5344 				goto ratecontrol_bailout;
5345 			}
5346 			if (ata) {
5347 				ata->valid |= CTS_SCSI_VALID_TQ;
5348 				if (tag_enable == 0)
5349 					ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5350 				else
5351 					ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5352 				didsettings++;
5353 			} else if (scsi) {
5354 				scsi->valid |= CTS_SCSI_VALID_TQ;
5355 				if (tag_enable == 0)
5356 					scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5357 				else
5358 					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5359 				didsettings++;
5360 			}
5361 		}
5362 		if (spi && offset != -1) {
5363 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5364 				warnx("HBA is not capable of changing offset");
5365 				retval = 1;
5366 				goto ratecontrol_bailout;
5367 			}
5368 			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5369 			spi->sync_offset = offset;
5370 			didsettings++;
5371 		}
5372 		if (spi && syncrate != -1) {
5373 			int prelim_sync_period;
5374 
5375 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5376 				warnx("HBA is not capable of changing "
5377 				      "transfer rates");
5378 				retval = 1;
5379 				goto ratecontrol_bailout;
5380 			}
5381 			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5382 			/*
5383 			 * The sync rate the user gives us is in MHz.
5384 			 * We need to translate it into KHz for this
5385 			 * calculation.
5386 			 */
5387 			syncrate *= 1000;
5388 			/*
5389 			 * Next, we calculate a "preliminary" sync period
5390 			 * in tenths of a nanosecond.
5391 			 */
5392 			if (syncrate == 0)
5393 				prelim_sync_period = 0;
5394 			else
5395 				prelim_sync_period = 10000000 / syncrate;
5396 			spi->sync_period =
5397 				scsi_calc_syncparam(prelim_sync_period);
5398 			didsettings++;
5399 		}
5400 		if (sata && syncrate != -1) {
5401 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5402 				warnx("HBA is not capable of changing "
5403 				      "transfer rates");
5404 				retval = 1;
5405 				goto ratecontrol_bailout;
5406 			}
5407 			if  (!user_settings) {
5408 				warnx("You can modify only user rate "
5409 				    "settings for SATA");
5410 				retval = 1;
5411 				goto ratecontrol_bailout;
5412 			}
5413 			sata->revision = ata_speed2revision(syncrate * 100);
5414 			if (sata->revision < 0) {
5415 				warnx("Invalid rate %f", syncrate);
5416 				retval = 1;
5417 				goto ratecontrol_bailout;
5418 			}
5419 			sata->valid |= CTS_SATA_VALID_REVISION;
5420 			didsettings++;
5421 		}
5422 		if ((pata || sata) && mode != -1) {
5423 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5424 				warnx("HBA is not capable of changing "
5425 				      "transfer rates");
5426 				retval = 1;
5427 				goto ratecontrol_bailout;
5428 			}
5429 			if  (!user_settings) {
5430 				warnx("You can modify only user mode "
5431 				    "settings for ATA/SATA");
5432 				retval = 1;
5433 				goto ratecontrol_bailout;
5434 			}
5435 			if (pata) {
5436 				pata->mode = mode;
5437 				pata->valid |= CTS_ATA_VALID_MODE;
5438 			} else {
5439 				sata->mode = mode;
5440 				sata->valid |= CTS_SATA_VALID_MODE;
5441 			}
5442 			didsettings++;
5443 		}
5444 		/*
5445 		 * The bus_width argument goes like this:
5446 		 * 0 == 8 bit
5447 		 * 1 == 16 bit
5448 		 * 2 == 32 bit
5449 		 * Therefore, if you shift the number of bits given on the
5450 		 * command line right by 4, you should get the correct
5451 		 * number.
5452 		 */
5453 		if (spi && bus_width != -1) {
5454 			/*
5455 			 * We might as well validate things here with a
5456 			 * decipherable error message, rather than what
5457 			 * will probably be an indecipherable error message
5458 			 * by the time it gets back to us.
5459 			 */
5460 			if ((bus_width == 16)
5461 			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5462 				warnx("HBA does not support 16 bit bus width");
5463 				retval = 1;
5464 				goto ratecontrol_bailout;
5465 			} else if ((bus_width == 32)
5466 				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5467 				warnx("HBA does not support 32 bit bus width");
5468 				retval = 1;
5469 				goto ratecontrol_bailout;
5470 			} else if ((bus_width != 8)
5471 				&& (bus_width != 16)
5472 				&& (bus_width != 32)) {
5473 				warnx("Invalid bus width %d", bus_width);
5474 				retval = 1;
5475 				goto ratecontrol_bailout;
5476 			}
5477 			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5478 			spi->bus_width = bus_width >> 4;
5479 			didsettings++;
5480 		}
5481 		if  (didsettings == 0) {
5482 			goto ratecontrol_bailout;
5483 		}
5484 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5485 		if (cam_send_ccb(device, ccb) < 0) {
5486 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5487 			if (arglist & CAM_ARG_VERBOSE) {
5488 				cam_error_print(device, ccb, CAM_ESF_ALL,
5489 						CAM_EPF_ALL, stderr);
5490 			}
5491 			retval = 1;
5492 			goto ratecontrol_bailout;
5493 		}
5494 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5495 			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5496 			if (arglist & CAM_ARG_VERBOSE) {
5497 				cam_error_print(device, ccb, CAM_ESF_ALL,
5498 						CAM_EPF_ALL, stderr);
5499 			}
5500 			retval = 1;
5501 			goto ratecontrol_bailout;
5502 		}
5503 	}
5504 	if (send_tur) {
5505 		retval = testunitready(device, retry_count, timeout,
5506 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5507 		/*
5508 		 * If the TUR didn't succeed, just bail.
5509 		 */
5510 		if (retval != 0) {
5511 			if (quiet == 0)
5512 				fprintf(stderr, "Test Unit Ready failed\n");
5513 			goto ratecontrol_bailout;
5514 		}
5515 	}
5516 	if ((change_settings || send_tur) && !quiet &&
5517 	    (ccb->cts.transport == XPORT_ATA ||
5518 	     ccb->cts.transport == XPORT_SATA || send_tur)) {
5519 		fprintf(stdout, "New parameters:\n");
5520 		retval = get_print_cts(device, user_settings, 0, NULL);
5521 	}
5522 
5523 ratecontrol_bailout:
5524 	cam_freeccb(ccb);
5525 	return(retval);
5526 }
5527 
5528 static int
5529 scsiformat(struct cam_device *device, int argc, char **argv,
5530 	   char *combinedopt, int retry_count, int timeout)
5531 {
5532 	union ccb *ccb;
5533 	int c;
5534 	int ycount = 0, quiet = 0;
5535 	int error = 0, retval = 0;
5536 	int use_timeout = 10800 * 1000;
5537 	int immediate = 1;
5538 	struct format_defect_list_header fh;
5539 	u_int8_t *data_ptr = NULL;
5540 	u_int32_t dxfer_len = 0;
5541 	u_int8_t byte2 = 0;
5542 	int num_warnings = 0;
5543 	int reportonly = 0;
5544 
5545 	ccb = cam_getccb(device);
5546 
5547 	if (ccb == NULL) {
5548 		warnx("scsiformat: error allocating ccb");
5549 		return(1);
5550 	}
5551 
5552 	bzero(&(&ccb->ccb_h)[1],
5553 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5554 
5555 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5556 		switch(c) {
5557 		case 'q':
5558 			quiet++;
5559 			break;
5560 		case 'r':
5561 			reportonly = 1;
5562 			break;
5563 		case 'w':
5564 			immediate = 0;
5565 			break;
5566 		case 'y':
5567 			ycount++;
5568 			break;
5569 		}
5570 	}
5571 
5572 	if (reportonly)
5573 		goto doreport;
5574 
5575 	if (quiet == 0) {
5576 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5577 			"following device:\n");
5578 
5579 		error = scsidoinquiry(device, argc, argv, combinedopt,
5580 				      retry_count, timeout);
5581 
5582 		if (error != 0) {
5583 			warnx("scsiformat: error sending inquiry");
5584 			goto scsiformat_bailout;
5585 		}
5586 	}
5587 
5588 	if (ycount == 0) {
5589 		if (!get_confirmation()) {
5590 			error = 1;
5591 			goto scsiformat_bailout;
5592 		}
5593 	}
5594 
5595 	if (timeout != 0)
5596 		use_timeout = timeout;
5597 
5598 	if (quiet == 0) {
5599 		fprintf(stdout, "Current format timeout is %d seconds\n",
5600 			use_timeout / 1000);
5601 	}
5602 
5603 	/*
5604 	 * If the user hasn't disabled questions and didn't specify a
5605 	 * timeout on the command line, ask them if they want the current
5606 	 * timeout.
5607 	 */
5608 	if ((ycount == 0)
5609 	 && (timeout == 0)) {
5610 		char str[1024];
5611 		int new_timeout = 0;
5612 
5613 		fprintf(stdout, "Enter new timeout in seconds or press\n"
5614 			"return to keep the current timeout [%d] ",
5615 			use_timeout / 1000);
5616 
5617 		if (fgets(str, sizeof(str), stdin) != NULL) {
5618 			if (str[0] != '\0')
5619 				new_timeout = atoi(str);
5620 		}
5621 
5622 		if (new_timeout != 0) {
5623 			use_timeout = new_timeout * 1000;
5624 			fprintf(stdout, "Using new timeout value %d\n",
5625 				use_timeout / 1000);
5626 		}
5627 	}
5628 
5629 	/*
5630 	 * Keep this outside the if block below to silence any unused
5631 	 * variable warnings.
5632 	 */
5633 	bzero(&fh, sizeof(fh));
5634 
5635 	/*
5636 	 * If we're in immediate mode, we've got to include the format
5637 	 * header
5638 	 */
5639 	if (immediate != 0) {
5640 		fh.byte2 = FU_DLH_IMMED;
5641 		data_ptr = (u_int8_t *)&fh;
5642 		dxfer_len = sizeof(fh);
5643 		byte2 = FU_FMT_DATA;
5644 	} else if (quiet == 0) {
5645 		fprintf(stdout, "Formatting...");
5646 		fflush(stdout);
5647 	}
5648 
5649 	scsi_format_unit(&ccb->csio,
5650 			 /* retries */ retry_count,
5651 			 /* cbfcnp */ NULL,
5652 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
5653 			 /* byte2 */ byte2,
5654 			 /* ileave */ 0,
5655 			 /* data_ptr */ data_ptr,
5656 			 /* dxfer_len */ dxfer_len,
5657 			 /* sense_len */ SSD_FULL_SIZE,
5658 			 /* timeout */ use_timeout);
5659 
5660 	/* Disable freezing the device queue */
5661 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5662 
5663 	if (arglist & CAM_ARG_ERR_RECOVER)
5664 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5665 
5666 	if (((retval = cam_send_ccb(device, ccb)) < 0)
5667 	 || ((immediate == 0)
5668 	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5669 		const char errstr[] = "error sending format command";
5670 
5671 		if (retval < 0)
5672 			warn(errstr);
5673 		else
5674 			warnx(errstr);
5675 
5676 		if (arglist & CAM_ARG_VERBOSE) {
5677 			cam_error_print(device, ccb, CAM_ESF_ALL,
5678 					CAM_EPF_ALL, stderr);
5679 		}
5680 		error = 1;
5681 		goto scsiformat_bailout;
5682 	}
5683 
5684 	/*
5685 	 * If we ran in non-immediate mode, we already checked for errors
5686 	 * above and printed out any necessary information.  If we're in
5687 	 * immediate mode, we need to loop through and get status
5688 	 * information periodically.
5689 	 */
5690 	if (immediate == 0) {
5691 		if (quiet == 0) {
5692 			fprintf(stdout, "Format Complete\n");
5693 		}
5694 		goto scsiformat_bailout;
5695 	}
5696 
5697 doreport:
5698 	do {
5699 		cam_status status;
5700 
5701 		bzero(&(&ccb->ccb_h)[1],
5702 		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5703 
5704 		/*
5705 		 * There's really no need to do error recovery or
5706 		 * retries here, since we're just going to sit in a
5707 		 * loop and wait for the device to finish formatting.
5708 		 */
5709 		scsi_test_unit_ready(&ccb->csio,
5710 				     /* retries */ 0,
5711 				     /* cbfcnp */ NULL,
5712 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
5713 				     /* sense_len */ SSD_FULL_SIZE,
5714 				     /* timeout */ 5000);
5715 
5716 		/* Disable freezing the device queue */
5717 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5718 
5719 		retval = cam_send_ccb(device, ccb);
5720 
5721 		/*
5722 		 * If we get an error from the ioctl, bail out.  SCSI
5723 		 * errors are expected.
5724 		 */
5725 		if (retval < 0) {
5726 			warn("error sending CAMIOCOMMAND ioctl");
5727 			if (arglist & CAM_ARG_VERBOSE) {
5728 				cam_error_print(device, ccb, CAM_ESF_ALL,
5729 						CAM_EPF_ALL, stderr);
5730 			}
5731 			error = 1;
5732 			goto scsiformat_bailout;
5733 		}
5734 
5735 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
5736 
5737 		if ((status != CAM_REQ_CMP)
5738 		 && (status == CAM_SCSI_STATUS_ERROR)
5739 		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5740 			struct scsi_sense_data *sense;
5741 			int error_code, sense_key, asc, ascq;
5742 
5743 			sense = &ccb->csio.sense_data;
5744 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
5745 			    ccb->csio.sense_resid, &error_code, &sense_key,
5746 			    &asc, &ascq, /*show_errors*/ 1);
5747 
5748 			/*
5749 			 * According to the SCSI-2 and SCSI-3 specs, a
5750 			 * drive that is in the middle of a format should
5751 			 * return NOT READY with an ASC of "logical unit
5752 			 * not ready, format in progress".  The sense key
5753 			 * specific bytes will then be a progress indicator.
5754 			 */
5755 			if ((sense_key == SSD_KEY_NOT_READY)
5756 			 && (asc == 0x04) && (ascq == 0x04)) {
5757 				uint8_t sks[3];
5758 
5759 				if ((scsi_get_sks(sense, ccb->csio.sense_len -
5760 				     ccb->csio.sense_resid, sks) == 0)
5761 				 && (quiet == 0)) {
5762 					int val;
5763 					u_int64_t percentage;
5764 
5765 					val = scsi_2btoul(&sks[1]);
5766 					percentage = 10000 * val;
5767 
5768 					fprintf(stdout,
5769 						"\rFormatting:  %ju.%02u %% "
5770 						"(%d/%d) done",
5771 						(uintmax_t)(percentage /
5772 						(0x10000 * 100)),
5773 						(unsigned)((percentage /
5774 						0x10000) % 100),
5775 						val, 0x10000);
5776 					fflush(stdout);
5777 				} else if ((quiet == 0)
5778 					&& (++num_warnings <= 1)) {
5779 					warnx("Unexpected SCSI Sense Key "
5780 					      "Specific value returned "
5781 					      "during format:");
5782 					scsi_sense_print(device, &ccb->csio,
5783 							 stderr);
5784 					warnx("Unable to print status "
5785 					      "information, but format will "
5786 					      "proceed.");
5787 					warnx("will exit when format is "
5788 					      "complete");
5789 				}
5790 				sleep(1);
5791 			} else {
5792 				warnx("Unexpected SCSI error during format");
5793 				cam_error_print(device, ccb, CAM_ESF_ALL,
5794 						CAM_EPF_ALL, stderr);
5795 				error = 1;
5796 				goto scsiformat_bailout;
5797 			}
5798 
5799 		} else if (status != CAM_REQ_CMP) {
5800 			warnx("Unexpected CAM status %#x", status);
5801 			if (arglist & CAM_ARG_VERBOSE)
5802 				cam_error_print(device, ccb, CAM_ESF_ALL,
5803 						CAM_EPF_ALL, stderr);
5804 			error = 1;
5805 			goto scsiformat_bailout;
5806 		}
5807 
5808 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5809 
5810 	if (quiet == 0)
5811 		fprintf(stdout, "\nFormat Complete\n");
5812 
5813 scsiformat_bailout:
5814 
5815 	cam_freeccb(ccb);
5816 
5817 	return(error);
5818 }
5819 
5820 static int
5821 scsisanitize(struct cam_device *device, int argc, char **argv,
5822 	     char *combinedopt, int retry_count, int timeout)
5823 {
5824 	union ccb *ccb;
5825 	u_int8_t action = 0;
5826 	int c;
5827 	int ycount = 0, quiet = 0;
5828 	int error = 0, retval = 0;
5829 	int use_timeout = 10800 * 1000;
5830 	int immediate = 1;
5831 	int invert = 0;
5832 	int passes = 0;
5833 	int ause = 0;
5834 	int fd = -1;
5835 	const char *pattern = NULL;
5836 	u_int8_t *data_ptr = NULL;
5837 	u_int32_t dxfer_len = 0;
5838 	u_int8_t byte2 = 0;
5839 	int num_warnings = 0;
5840 	int reportonly = 0;
5841 
5842 	ccb = cam_getccb(device);
5843 
5844 	if (ccb == NULL) {
5845 		warnx("scsisanitize: error allocating ccb");
5846 		return(1);
5847 	}
5848 
5849 	bzero(&(&ccb->ccb_h)[1],
5850 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5851 
5852 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5853 		switch(c) {
5854 		case 'a':
5855 			if (strcasecmp(optarg, "overwrite") == 0)
5856 				action = SSZ_SERVICE_ACTION_OVERWRITE;
5857 			else if (strcasecmp(optarg, "block") == 0)
5858 				action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
5859 			else if (strcasecmp(optarg, "crypto") == 0)
5860 				action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
5861 			else if (strcasecmp(optarg, "exitfailure") == 0)
5862 				action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
5863 			else {
5864 				warnx("invalid service operation \"%s\"",
5865 				      optarg);
5866 				error = 1;
5867 				goto scsisanitize_bailout;
5868 			}
5869 			break;
5870 		case 'c':
5871 			passes = strtol(optarg, NULL, 0);
5872 			if (passes < 1 || passes > 31) {
5873 				warnx("invalid passes value %d", passes);
5874 				error = 1;
5875 				goto scsisanitize_bailout;
5876 			}
5877 			break;
5878 		case 'I':
5879 			invert = 1;
5880 			break;
5881 		case 'P':
5882 			pattern = optarg;
5883 			break;
5884 		case 'q':
5885 			quiet++;
5886 			break;
5887 		case 'U':
5888 			ause = 1;
5889 			break;
5890 		case 'r':
5891 			reportonly = 1;
5892 			break;
5893 		case 'w':
5894 			immediate = 0;
5895 			break;
5896 		case 'y':
5897 			ycount++;
5898 			break;
5899 		}
5900 	}
5901 
5902 	if (reportonly)
5903 		goto doreport;
5904 
5905 	if (action == 0) {
5906 		warnx("an action is required");
5907 		error = 1;
5908 		goto scsisanitize_bailout;
5909 	} else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
5910 		struct scsi_sanitize_parameter_list *pl;
5911 		struct stat sb;
5912 		ssize_t sz, amt;
5913 
5914 		if (pattern == NULL) {
5915 			warnx("overwrite action requires -P argument");
5916 			error = 1;
5917 			goto scsisanitize_bailout;
5918 		}
5919 		fd = open(pattern, O_RDONLY);
5920 		if (fd < 0) {
5921 			warn("cannot open pattern file %s", pattern);
5922 			error = 1;
5923 			goto scsisanitize_bailout;
5924 		}
5925 		if (fstat(fd, &sb) < 0) {
5926 			warn("cannot stat pattern file %s", pattern);
5927 			error = 1;
5928 			goto scsisanitize_bailout;
5929 		}
5930 		sz = sb.st_size;
5931 		if (sz > SSZPL_MAX_PATTERN_LENGTH) {
5932 			warnx("pattern file size exceeds maximum value %d",
5933 			      SSZPL_MAX_PATTERN_LENGTH);
5934 			error = 1;
5935 			goto scsisanitize_bailout;
5936 		}
5937 		dxfer_len = sizeof(*pl) + sz;
5938 		data_ptr = calloc(1, dxfer_len);
5939 		if (data_ptr == NULL) {
5940 			warnx("cannot allocate parameter list buffer");
5941 			error = 1;
5942 			goto scsisanitize_bailout;
5943 		}
5944 
5945 		amt = read(fd, data_ptr + sizeof(*pl), sz);
5946 		if (amt < 0) {
5947 			warn("cannot read pattern file");
5948 			error = 1;
5949 			goto scsisanitize_bailout;
5950 		} else if (amt != sz) {
5951 			warnx("short pattern file read");
5952 			error = 1;
5953 			goto scsisanitize_bailout;
5954 		}
5955 
5956 		pl = (struct scsi_sanitize_parameter_list *)data_ptr;
5957 		if (passes == 0)
5958 			pl->byte1 = 1;
5959 		else
5960 			pl->byte1 = passes;
5961 		if (invert != 0)
5962 			pl->byte1 |= SSZPL_INVERT;
5963 		scsi_ulto2b(sz, pl->length);
5964 	} else {
5965 		const char *arg;
5966 
5967 		if (passes != 0)
5968 			arg = "-c";
5969 		else if (invert != 0)
5970 			arg = "-I";
5971 		else if (pattern != NULL)
5972 			arg = "-P";
5973 		else
5974 			arg = NULL;
5975 		if (arg != NULL) {
5976 			warnx("%s argument only valid with overwrite "
5977 			      "operation", arg);
5978 			error = 1;
5979 			goto scsisanitize_bailout;
5980 		}
5981 	}
5982 
5983 	if (quiet == 0) {
5984 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5985 			"following device:\n");
5986 
5987 		error = scsidoinquiry(device, argc, argv, combinedopt,
5988 				      retry_count, timeout);
5989 
5990 		if (error != 0) {
5991 			warnx("scsisanitize: error sending inquiry");
5992 			goto scsisanitize_bailout;
5993 		}
5994 	}
5995 
5996 	if (ycount == 0) {
5997 		if (!get_confirmation()) {
5998 			error = 1;
5999 			goto scsisanitize_bailout;
6000 		}
6001 	}
6002 
6003 	if (timeout != 0)
6004 		use_timeout = timeout;
6005 
6006 	if (quiet == 0) {
6007 		fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6008 			use_timeout / 1000);
6009 	}
6010 
6011 	/*
6012 	 * If the user hasn't disabled questions and didn't specify a
6013 	 * timeout on the command line, ask them if they want the current
6014 	 * timeout.
6015 	 */
6016 	if ((ycount == 0)
6017 	 && (timeout == 0)) {
6018 		char str[1024];
6019 		int new_timeout = 0;
6020 
6021 		fprintf(stdout, "Enter new timeout in seconds or press\n"
6022 			"return to keep the current timeout [%d] ",
6023 			use_timeout / 1000);
6024 
6025 		if (fgets(str, sizeof(str), stdin) != NULL) {
6026 			if (str[0] != '\0')
6027 				new_timeout = atoi(str);
6028 		}
6029 
6030 		if (new_timeout != 0) {
6031 			use_timeout = new_timeout * 1000;
6032 			fprintf(stdout, "Using new timeout value %d\n",
6033 				use_timeout / 1000);
6034 		}
6035 	}
6036 
6037 	byte2 = action;
6038 	if (ause != 0)
6039 		byte2 |= SSZ_UNRESTRICTED_EXIT;
6040 	if (immediate != 0)
6041 		byte2 |= SSZ_IMMED;
6042 
6043 	scsi_sanitize(&ccb->csio,
6044 		      /* retries */ retry_count,
6045 		      /* cbfcnp */ NULL,
6046 		      /* tag_action */ MSG_SIMPLE_Q_TAG,
6047 		      /* byte2 */ byte2,
6048 		      /* control */ 0,
6049 		      /* data_ptr */ data_ptr,
6050 		      /* dxfer_len */ dxfer_len,
6051 		      /* sense_len */ SSD_FULL_SIZE,
6052 		      /* timeout */ use_timeout);
6053 
6054 	/* Disable freezing the device queue */
6055 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6056 
6057 	if (arglist & CAM_ARG_ERR_RECOVER)
6058 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6059 
6060 	if (cam_send_ccb(device, ccb) < 0) {
6061 		warn("error sending sanitize command");
6062 		error = 1;
6063 		goto scsisanitize_bailout;
6064 	}
6065 
6066 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6067 		struct scsi_sense_data *sense;
6068 		int error_code, sense_key, asc, ascq;
6069 
6070 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6071 		    CAM_SCSI_STATUS_ERROR) {
6072 			sense = &ccb->csio.sense_data;
6073 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6074 			    ccb->csio.sense_resid, &error_code, &sense_key,
6075 			    &asc, &ascq, /*show_errors*/ 1);
6076 
6077 			if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6078 			    asc == 0x20 && ascq == 0x00)
6079 				warnx("sanitize is not supported by "
6080 				      "this device");
6081 			else
6082 				warnx("error sanitizing this device");
6083 		} else
6084 			warnx("error sanitizing this device");
6085 
6086 		if (arglist & CAM_ARG_VERBOSE) {
6087 			cam_error_print(device, ccb, CAM_ESF_ALL,
6088 					CAM_EPF_ALL, stderr);
6089 		}
6090 		error = 1;
6091 		goto scsisanitize_bailout;
6092 	}
6093 
6094 	/*
6095 	 * If we ran in non-immediate mode, we already checked for errors
6096 	 * above and printed out any necessary information.  If we're in
6097 	 * immediate mode, we need to loop through and get status
6098 	 * information periodically.
6099 	 */
6100 	if (immediate == 0) {
6101 		if (quiet == 0) {
6102 			fprintf(stdout, "Sanitize Complete\n");
6103 		}
6104 		goto scsisanitize_bailout;
6105 	}
6106 
6107 doreport:
6108 	do {
6109 		cam_status status;
6110 
6111 		bzero(&(&ccb->ccb_h)[1],
6112 		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6113 
6114 		/*
6115 		 * There's really no need to do error recovery or
6116 		 * retries here, since we're just going to sit in a
6117 		 * loop and wait for the device to finish sanitizing.
6118 		 */
6119 		scsi_test_unit_ready(&ccb->csio,
6120 				     /* retries */ 0,
6121 				     /* cbfcnp */ NULL,
6122 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
6123 				     /* sense_len */ SSD_FULL_SIZE,
6124 				     /* timeout */ 5000);
6125 
6126 		/* Disable freezing the device queue */
6127 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6128 
6129 		retval = cam_send_ccb(device, ccb);
6130 
6131 		/*
6132 		 * If we get an error from the ioctl, bail out.  SCSI
6133 		 * errors are expected.
6134 		 */
6135 		if (retval < 0) {
6136 			warn("error sending CAMIOCOMMAND ioctl");
6137 			if (arglist & CAM_ARG_VERBOSE) {
6138 				cam_error_print(device, ccb, CAM_ESF_ALL,
6139 						CAM_EPF_ALL, stderr);
6140 			}
6141 			error = 1;
6142 			goto scsisanitize_bailout;
6143 		}
6144 
6145 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
6146 
6147 		if ((status != CAM_REQ_CMP)
6148 		 && (status == CAM_SCSI_STATUS_ERROR)
6149 		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6150 			struct scsi_sense_data *sense;
6151 			int error_code, sense_key, asc, ascq;
6152 
6153 			sense = &ccb->csio.sense_data;
6154 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6155 			    ccb->csio.sense_resid, &error_code, &sense_key,
6156 			    &asc, &ascq, /*show_errors*/ 1);
6157 
6158 			/*
6159 			 * According to the SCSI-3 spec, a drive that is in the
6160 			 * middle of a sanitize should return NOT READY with an
6161 			 * ASC of "logical unit not ready, sanitize in
6162 			 * progress". The sense key specific bytes will then
6163 			 * be a progress indicator.
6164 			 */
6165 			if ((sense_key == SSD_KEY_NOT_READY)
6166 			 && (asc == 0x04) && (ascq == 0x1b)) {
6167 				uint8_t sks[3];
6168 
6169 				if ((scsi_get_sks(sense, ccb->csio.sense_len -
6170 				     ccb->csio.sense_resid, sks) == 0)
6171 				 && (quiet == 0)) {
6172 					int val;
6173 					u_int64_t percentage;
6174 
6175 					val = scsi_2btoul(&sks[1]);
6176 					percentage = 10000 * val;
6177 
6178 					fprintf(stdout,
6179 						"\rSanitizing:  %ju.%02u %% "
6180 						"(%d/%d) done",
6181 						(uintmax_t)(percentage /
6182 						(0x10000 * 100)),
6183 						(unsigned)((percentage /
6184 						0x10000) % 100),
6185 						val, 0x10000);
6186 					fflush(stdout);
6187 				} else if ((quiet == 0)
6188 					&& (++num_warnings <= 1)) {
6189 					warnx("Unexpected SCSI Sense Key "
6190 					      "Specific value returned "
6191 					      "during sanitize:");
6192 					scsi_sense_print(device, &ccb->csio,
6193 							 stderr);
6194 					warnx("Unable to print status "
6195 					      "information, but sanitze will "
6196 					      "proceed.");
6197 					warnx("will exit when sanitize is "
6198 					      "complete");
6199 				}
6200 				sleep(1);
6201 			} else {
6202 				warnx("Unexpected SCSI error during sanitize");
6203 				cam_error_print(device, ccb, CAM_ESF_ALL,
6204 						CAM_EPF_ALL, stderr);
6205 				error = 1;
6206 				goto scsisanitize_bailout;
6207 			}
6208 
6209 		} else if (status != CAM_REQ_CMP) {
6210 			warnx("Unexpected CAM status %#x", status);
6211 			if (arglist & CAM_ARG_VERBOSE)
6212 				cam_error_print(device, ccb, CAM_ESF_ALL,
6213 						CAM_EPF_ALL, stderr);
6214 			error = 1;
6215 			goto scsisanitize_bailout;
6216 		}
6217 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6218 
6219 	if (quiet == 0)
6220 		fprintf(stdout, "\nSanitize Complete\n");
6221 
6222 scsisanitize_bailout:
6223 	if (fd >= 0)
6224 		close(fd);
6225 	if (data_ptr != NULL)
6226 		free(data_ptr);
6227 	cam_freeccb(ccb);
6228 
6229 	return(error);
6230 }
6231 
6232 static int
6233 scsireportluns(struct cam_device *device, int argc, char **argv,
6234 	       char *combinedopt, int retry_count, int timeout)
6235 {
6236 	union ccb *ccb;
6237 	int c, countonly, lunsonly;
6238 	struct scsi_report_luns_data *lundata;
6239 	int alloc_len;
6240 	uint8_t report_type;
6241 	uint32_t list_len, i, j;
6242 	int retval;
6243 
6244 	retval = 0;
6245 	lundata = NULL;
6246 	report_type = RPL_REPORT_DEFAULT;
6247 	ccb = cam_getccb(device);
6248 
6249 	if (ccb == NULL) {
6250 		warnx("%s: error allocating ccb", __func__);
6251 		return (1);
6252 	}
6253 
6254 	bzero(&(&ccb->ccb_h)[1],
6255 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6256 
6257 	countonly = 0;
6258 	lunsonly = 0;
6259 
6260 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6261 		switch (c) {
6262 		case 'c':
6263 			countonly++;
6264 			break;
6265 		case 'l':
6266 			lunsonly++;
6267 			break;
6268 		case 'r':
6269 			if (strcasecmp(optarg, "default") == 0)
6270 				report_type = RPL_REPORT_DEFAULT;
6271 			else if (strcasecmp(optarg, "wellknown") == 0)
6272 				report_type = RPL_REPORT_WELLKNOWN;
6273 			else if (strcasecmp(optarg, "all") == 0)
6274 				report_type = RPL_REPORT_ALL;
6275 			else {
6276 				warnx("%s: invalid report type \"%s\"",
6277 				      __func__, optarg);
6278 				retval = 1;
6279 				goto bailout;
6280 			}
6281 			break;
6282 		default:
6283 			break;
6284 		}
6285 	}
6286 
6287 	if ((countonly != 0)
6288 	 && (lunsonly != 0)) {
6289 		warnx("%s: you can only specify one of -c or -l", __func__);
6290 		retval = 1;
6291 		goto bailout;
6292 	}
6293 	/*
6294 	 * According to SPC-4, the allocation length must be at least 16
6295 	 * bytes -- enough for the header and one LUN.
6296 	 */
6297 	alloc_len = sizeof(*lundata) + 8;
6298 
6299 retry:
6300 
6301 	lundata = malloc(alloc_len);
6302 
6303 	if (lundata == NULL) {
6304 		warn("%s: error mallocing %d bytes", __func__, alloc_len);
6305 		retval = 1;
6306 		goto bailout;
6307 	}
6308 
6309 	scsi_report_luns(&ccb->csio,
6310 			 /*retries*/ retry_count,
6311 			 /*cbfcnp*/ NULL,
6312 			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6313 			 /*select_report*/ report_type,
6314 			 /*rpl_buf*/ lundata,
6315 			 /*alloc_len*/ alloc_len,
6316 			 /*sense_len*/ SSD_FULL_SIZE,
6317 			 /*timeout*/ timeout ? timeout : 5000);
6318 
6319 	/* Disable freezing the device queue */
6320 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6321 
6322 	if (arglist & CAM_ARG_ERR_RECOVER)
6323 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6324 
6325 	if (cam_send_ccb(device, ccb) < 0) {
6326 		warn("error sending REPORT LUNS command");
6327 
6328 		if (arglist & CAM_ARG_VERBOSE)
6329 			cam_error_print(device, ccb, CAM_ESF_ALL,
6330 					CAM_EPF_ALL, stderr);
6331 
6332 		retval = 1;
6333 		goto bailout;
6334 	}
6335 
6336 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6337 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6338 		retval = 1;
6339 		goto bailout;
6340 	}
6341 
6342 
6343 	list_len = scsi_4btoul(lundata->length);
6344 
6345 	/*
6346 	 * If we need to list the LUNs, and our allocation
6347 	 * length was too short, reallocate and retry.
6348 	 */
6349 	if ((countonly == 0)
6350 	 && (list_len > (alloc_len - sizeof(*lundata)))) {
6351 		alloc_len = list_len + sizeof(*lundata);
6352 		free(lundata);
6353 		goto retry;
6354 	}
6355 
6356 	if (lunsonly == 0)
6357 		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6358 			((list_len / 8) > 1) ? "s" : "");
6359 
6360 	if (countonly != 0)
6361 		goto bailout;
6362 
6363 	for (i = 0; i < (list_len / 8); i++) {
6364 		int no_more;
6365 
6366 		no_more = 0;
6367 		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6368 			if (j != 0)
6369 				fprintf(stdout, ",");
6370 			switch (lundata->luns[i].lundata[j] &
6371 				RPL_LUNDATA_ATYP_MASK) {
6372 			case RPL_LUNDATA_ATYP_PERIPH:
6373 				if ((lundata->luns[i].lundata[j] &
6374 				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6375 					fprintf(stdout, "%d:",
6376 						lundata->luns[i].lundata[j] &
6377 						RPL_LUNDATA_PERIPH_BUS_MASK);
6378 				else if ((j == 0)
6379 				      && ((lundata->luns[i].lundata[j+2] &
6380 					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6381 					no_more = 1;
6382 
6383 				fprintf(stdout, "%d",
6384 					lundata->luns[i].lundata[j+1]);
6385 				break;
6386 			case RPL_LUNDATA_ATYP_FLAT: {
6387 				uint8_t tmplun[2];
6388 				tmplun[0] = lundata->luns[i].lundata[j] &
6389 					RPL_LUNDATA_FLAT_LUN_MASK;
6390 				tmplun[1] = lundata->luns[i].lundata[j+1];
6391 
6392 				fprintf(stdout, "%d", scsi_2btoul(tmplun));
6393 				no_more = 1;
6394 				break;
6395 			}
6396 			case RPL_LUNDATA_ATYP_LUN:
6397 				fprintf(stdout, "%d:%d:%d",
6398 					(lundata->luns[i].lundata[j+1] &
6399 					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6400 					lundata->luns[i].lundata[j] &
6401 					RPL_LUNDATA_LUN_TARG_MASK,
6402 					lundata->luns[i].lundata[j+1] &
6403 					RPL_LUNDATA_LUN_LUN_MASK);
6404 				break;
6405 			case RPL_LUNDATA_ATYP_EXTLUN: {
6406 				int field_len_code, eam_code;
6407 
6408 				eam_code = lundata->luns[i].lundata[j] &
6409 					RPL_LUNDATA_EXT_EAM_MASK;
6410 				field_len_code = (lundata->luns[i].lundata[j] &
6411 					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6412 
6413 				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6414 				 && (field_len_code == 0x00)) {
6415 					fprintf(stdout, "%d",
6416 						lundata->luns[i].lundata[j+1]);
6417 				} else if ((eam_code ==
6418 					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6419 					&& (field_len_code == 0x03)) {
6420 					uint8_t tmp_lun[8];
6421 
6422 					/*
6423 					 * This format takes up all 8 bytes.
6424 					 * If we aren't starting at offset 0,
6425 					 * that's a bug.
6426 					 */
6427 					if (j != 0) {
6428 						fprintf(stdout, "Invalid "
6429 							"offset %d for "
6430 							"Extended LUN not "
6431 							"specified format", j);
6432 						no_more = 1;
6433 						break;
6434 					}
6435 					bzero(tmp_lun, sizeof(tmp_lun));
6436 					bcopy(&lundata->luns[i].lundata[j+1],
6437 					      &tmp_lun[1], sizeof(tmp_lun) - 1);
6438 					fprintf(stdout, "%#jx",
6439 					       (intmax_t)scsi_8btou64(tmp_lun));
6440 					no_more = 1;
6441 				} else {
6442 					fprintf(stderr, "Unknown Extended LUN"
6443 						"Address method %#x, length "
6444 						"code %#x", eam_code,
6445 						field_len_code);
6446 					no_more = 1;
6447 				}
6448 				break;
6449 			}
6450 			default:
6451 				fprintf(stderr, "Unknown LUN address method "
6452 					"%#x\n", lundata->luns[i].lundata[0] &
6453 					RPL_LUNDATA_ATYP_MASK);
6454 				break;
6455 			}
6456 			/*
6457 			 * For the flat addressing method, there are no
6458 			 * other levels after it.
6459 			 */
6460 			if (no_more != 0)
6461 				break;
6462 		}
6463 		fprintf(stdout, "\n");
6464 	}
6465 
6466 bailout:
6467 
6468 	cam_freeccb(ccb);
6469 
6470 	free(lundata);
6471 
6472 	return (retval);
6473 }
6474 
6475 static int
6476 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6477 		 char *combinedopt, int retry_count, int timeout)
6478 {
6479 	union ccb *ccb;
6480 	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6481 	struct scsi_read_capacity_data rcap;
6482 	struct scsi_read_capacity_data_long rcaplong;
6483 	uint64_t maxsector;
6484 	uint32_t block_len;
6485 	int retval;
6486 	int c;
6487 
6488 	blocksizeonly = 0;
6489 	humanize = 0;
6490 	numblocks = 0;
6491 	quiet = 0;
6492 	sizeonly = 0;
6493 	baseten = 0;
6494 	retval = 0;
6495 
6496 	ccb = cam_getccb(device);
6497 
6498 	if (ccb == NULL) {
6499 		warnx("%s: error allocating ccb", __func__);
6500 		return (1);
6501 	}
6502 
6503 	bzero(&(&ccb->ccb_h)[1],
6504 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6505 
6506 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6507 		switch (c) {
6508 		case 'b':
6509 			blocksizeonly++;
6510 			break;
6511 		case 'h':
6512 			humanize++;
6513 			baseten = 0;
6514 			break;
6515 		case 'H':
6516 			humanize++;
6517 			baseten++;
6518 			break;
6519 		case 'N':
6520 			numblocks++;
6521 			break;
6522 		case 'q':
6523 			quiet++;
6524 			break;
6525 		case 's':
6526 			sizeonly++;
6527 			break;
6528 		default:
6529 			break;
6530 		}
6531 	}
6532 
6533 	if ((blocksizeonly != 0)
6534 	 && (numblocks != 0)) {
6535 		warnx("%s: you can only specify one of -b or -N", __func__);
6536 		retval = 1;
6537 		goto bailout;
6538 	}
6539 
6540 	if ((blocksizeonly != 0)
6541 	 && (sizeonly != 0)) {
6542 		warnx("%s: you can only specify one of -b or -s", __func__);
6543 		retval = 1;
6544 		goto bailout;
6545 	}
6546 
6547 	if ((humanize != 0)
6548 	 && (quiet != 0)) {
6549 		warnx("%s: you can only specify one of -h/-H or -q", __func__);
6550 		retval = 1;
6551 		goto bailout;
6552 	}
6553 
6554 	if ((humanize != 0)
6555 	 && (blocksizeonly != 0)) {
6556 		warnx("%s: you can only specify one of -h/-H or -b", __func__);
6557 		retval = 1;
6558 		goto bailout;
6559 	}
6560 
6561 	scsi_read_capacity(&ccb->csio,
6562 			   /*retries*/ retry_count,
6563 			   /*cbfcnp*/ NULL,
6564 			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
6565 			   &rcap,
6566 			   SSD_FULL_SIZE,
6567 			   /*timeout*/ timeout ? timeout : 5000);
6568 
6569 	/* Disable freezing the device queue */
6570 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6571 
6572 	if (arglist & CAM_ARG_ERR_RECOVER)
6573 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6574 
6575 	if (cam_send_ccb(device, ccb) < 0) {
6576 		warn("error sending READ CAPACITY command");
6577 
6578 		if (arglist & CAM_ARG_VERBOSE)
6579 			cam_error_print(device, ccb, CAM_ESF_ALL,
6580 					CAM_EPF_ALL, stderr);
6581 
6582 		retval = 1;
6583 		goto bailout;
6584 	}
6585 
6586 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6587 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6588 		retval = 1;
6589 		goto bailout;
6590 	}
6591 
6592 	maxsector = scsi_4btoul(rcap.addr);
6593 	block_len = scsi_4btoul(rcap.length);
6594 
6595 	/*
6596 	 * A last block of 2^32-1 means that the true capacity is over 2TB,
6597 	 * and we need to issue the long READ CAPACITY to get the real
6598 	 * capacity.  Otherwise, we're all set.
6599 	 */
6600 	if (maxsector != 0xffffffff)
6601 		goto do_print;
6602 
6603 	scsi_read_capacity_16(&ccb->csio,
6604 			      /*retries*/ retry_count,
6605 			      /*cbfcnp*/ NULL,
6606 			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
6607 			      /*lba*/ 0,
6608 			      /*reladdr*/ 0,
6609 			      /*pmi*/ 0,
6610 			      /*rcap_buf*/ (uint8_t *)&rcaplong,
6611 			      /*rcap_buf_len*/ sizeof(rcaplong),
6612 			      /*sense_len*/ SSD_FULL_SIZE,
6613 			      /*timeout*/ timeout ? timeout : 5000);
6614 
6615 	/* Disable freezing the device queue */
6616 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6617 
6618 	if (arglist & CAM_ARG_ERR_RECOVER)
6619 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6620 
6621 	if (cam_send_ccb(device, ccb) < 0) {
6622 		warn("error sending READ CAPACITY (16) command");
6623 
6624 		if (arglist & CAM_ARG_VERBOSE)
6625 			cam_error_print(device, ccb, CAM_ESF_ALL,
6626 					CAM_EPF_ALL, stderr);
6627 
6628 		retval = 1;
6629 		goto bailout;
6630 	}
6631 
6632 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6633 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6634 		retval = 1;
6635 		goto bailout;
6636 	}
6637 
6638 	maxsector = scsi_8btou64(rcaplong.addr);
6639 	block_len = scsi_4btoul(rcaplong.length);
6640 
6641 do_print:
6642 	if (blocksizeonly == 0) {
6643 		/*
6644 		 * Humanize implies !quiet, and also implies numblocks.
6645 		 */
6646 		if (humanize != 0) {
6647 			char tmpstr[6];
6648 			int64_t tmpbytes;
6649 			int ret;
6650 
6651 			tmpbytes = (maxsector + 1) * block_len;
6652 			ret = humanize_number(tmpstr, sizeof(tmpstr),
6653 					      tmpbytes, "", HN_AUTOSCALE,
6654 					      HN_B | HN_DECIMAL |
6655 					      ((baseten != 0) ?
6656 					      HN_DIVISOR_1000 : 0));
6657 			if (ret == -1) {
6658 				warnx("%s: humanize_number failed!", __func__);
6659 				retval = 1;
6660 				goto bailout;
6661 			}
6662 			fprintf(stdout, "Device Size: %s%s", tmpstr,
6663 				(sizeonly == 0) ?  ", " : "\n");
6664 		} else if (numblocks != 0) {
6665 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6666 				"Blocks: " : "", (uintmax_t)maxsector + 1,
6667 				(sizeonly == 0) ? ", " : "\n");
6668 		} else {
6669 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6670 				"Last Block: " : "", (uintmax_t)maxsector,
6671 				(sizeonly == 0) ? ", " : "\n");
6672 		}
6673 	}
6674 	if (sizeonly == 0)
6675 		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6676 			"Block Length: " : "", block_len, (quiet == 0) ?
6677 			" bytes" : "");
6678 bailout:
6679 	cam_freeccb(ccb);
6680 
6681 	return (retval);
6682 }
6683 
6684 static int
6685 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6686        int retry_count, int timeout)
6687 {
6688 	int c, error = 0;
6689 	union ccb *ccb;
6690 	uint8_t *smp_request = NULL, *smp_response = NULL;
6691 	int request_size = 0, response_size = 0;
6692 	int fd_request = 0, fd_response = 0;
6693 	char *datastr = NULL;
6694 	struct get_hook hook;
6695 	int retval;
6696 	int flags = 0;
6697 
6698 	/*
6699 	 * Note that at the moment we don't support sending SMP CCBs to
6700 	 * devices that aren't probed by CAM.
6701 	 */
6702 	ccb = cam_getccb(device);
6703 	if (ccb == NULL) {
6704 		warnx("%s: error allocating CCB", __func__);
6705 		return (1);
6706 	}
6707 
6708 	bzero(&(&ccb->ccb_h)[1],
6709 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6710 
6711 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6712 		switch (c) {
6713 		case 'R':
6714 			arglist |= CAM_ARG_CMD_IN;
6715 			response_size = strtol(optarg, NULL, 0);
6716 			if (response_size <= 0) {
6717 				warnx("invalid number of response bytes %d",
6718 				      response_size);
6719 				error = 1;
6720 				goto smpcmd_bailout;
6721 			}
6722 			hook.argc = argc - optind;
6723 			hook.argv = argv + optind;
6724 			hook.got = 0;
6725 			optind++;
6726 			datastr = cget(&hook, NULL);
6727 			/*
6728 			 * If the user supplied "-" instead of a format, he
6729 			 * wants the data to be written to stdout.
6730 			 */
6731 			if ((datastr != NULL)
6732 			 && (datastr[0] == '-'))
6733 				fd_response = 1;
6734 
6735 			smp_response = (u_int8_t *)malloc(response_size);
6736 			if (smp_response == NULL) {
6737 				warn("can't malloc memory for SMP response");
6738 				error = 1;
6739 				goto smpcmd_bailout;
6740 			}
6741 			break;
6742 		case 'r':
6743 			arglist |= CAM_ARG_CMD_OUT;
6744 			request_size = strtol(optarg, NULL, 0);
6745 			if (request_size <= 0) {
6746 				warnx("invalid number of request bytes %d",
6747 				      request_size);
6748 				error = 1;
6749 				goto smpcmd_bailout;
6750 			}
6751 			hook.argc = argc - optind;
6752 			hook.argv = argv + optind;
6753 			hook.got = 0;
6754 			datastr = cget(&hook, NULL);
6755 			smp_request = (u_int8_t *)malloc(request_size);
6756 			if (smp_request == NULL) {
6757 				warn("can't malloc memory for SMP request");
6758 				error = 1;
6759 				goto smpcmd_bailout;
6760 			}
6761 			bzero(smp_request, request_size);
6762 			/*
6763 			 * If the user supplied "-" instead of a format, he
6764 			 * wants the data to be read from stdin.
6765 			 */
6766 			if ((datastr != NULL)
6767 			 && (datastr[0] == '-'))
6768 				fd_request = 1;
6769 			else
6770 				buff_encode_visit(smp_request, request_size,
6771 						  datastr,
6772 						  iget, &hook);
6773 			optind += hook.got;
6774 			break;
6775 		default:
6776 			break;
6777 		}
6778 	}
6779 
6780 	/*
6781 	 * If fd_data is set, and we're writing to the device, we need to
6782 	 * read the data the user wants written from stdin.
6783 	 */
6784 	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6785 		ssize_t amt_read;
6786 		int amt_to_read = request_size;
6787 		u_int8_t *buf_ptr = smp_request;
6788 
6789 		for (amt_read = 0; amt_to_read > 0;
6790 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6791 			if (amt_read == -1) {
6792 				warn("error reading data from stdin");
6793 				error = 1;
6794 				goto smpcmd_bailout;
6795 			}
6796 			amt_to_read -= amt_read;
6797 			buf_ptr += amt_read;
6798 		}
6799 	}
6800 
6801 	if (((arglist & CAM_ARG_CMD_IN) == 0)
6802 	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6803 		warnx("%s: need both the request (-r) and response (-R) "
6804 		      "arguments", __func__);
6805 		error = 1;
6806 		goto smpcmd_bailout;
6807 	}
6808 
6809 	flags |= CAM_DEV_QFRZDIS;
6810 
6811 	cam_fill_smpio(&ccb->smpio,
6812 		       /*retries*/ retry_count,
6813 		       /*cbfcnp*/ NULL,
6814 		       /*flags*/ flags,
6815 		       /*smp_request*/ smp_request,
6816 		       /*smp_request_len*/ request_size,
6817 		       /*smp_response*/ smp_response,
6818 		       /*smp_response_len*/ response_size,
6819 		       /*timeout*/ timeout ? timeout : 5000);
6820 
6821 	ccb->smpio.flags = SMP_FLAG_NONE;
6822 
6823 	if (((retval = cam_send_ccb(device, ccb)) < 0)
6824 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6825 		const char warnstr[] = "error sending command";
6826 
6827 		if (retval < 0)
6828 			warn(warnstr);
6829 		else
6830 			warnx(warnstr);
6831 
6832 		if (arglist & CAM_ARG_VERBOSE) {
6833 			cam_error_print(device, ccb, CAM_ESF_ALL,
6834 					CAM_EPF_ALL, stderr);
6835 		}
6836 	}
6837 
6838 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6839 	 && (response_size > 0)) {
6840 		if (fd_response == 0) {
6841 			buff_decode_visit(smp_response, response_size,
6842 					  datastr, arg_put, NULL);
6843 			fprintf(stdout, "\n");
6844 		} else {
6845 			ssize_t amt_written;
6846 			int amt_to_write = response_size;
6847 			u_int8_t *buf_ptr = smp_response;
6848 
6849 			for (amt_written = 0; (amt_to_write > 0) &&
6850 			     (amt_written = write(STDOUT_FILENO, buf_ptr,
6851 						  amt_to_write)) > 0;){
6852 				amt_to_write -= amt_written;
6853 				buf_ptr += amt_written;
6854 			}
6855 			if (amt_written == -1) {
6856 				warn("error writing data to stdout");
6857 				error = 1;
6858 				goto smpcmd_bailout;
6859 			} else if ((amt_written == 0)
6860 				&& (amt_to_write > 0)) {
6861 				warnx("only wrote %u bytes out of %u",
6862 				      response_size - amt_to_write,
6863 				      response_size);
6864 			}
6865 		}
6866 	}
6867 smpcmd_bailout:
6868 	if (ccb != NULL)
6869 		cam_freeccb(ccb);
6870 
6871 	if (smp_request != NULL)
6872 		free(smp_request);
6873 
6874 	if (smp_response != NULL)
6875 		free(smp_response);
6876 
6877 	return (error);
6878 }
6879 
6880 static int
6881 smpreportgeneral(struct cam_device *device, int argc, char **argv,
6882 		 char *combinedopt, int retry_count, int timeout)
6883 {
6884 	union ccb *ccb;
6885 	struct smp_report_general_request *request = NULL;
6886 	struct smp_report_general_response *response = NULL;
6887 	struct sbuf *sb = NULL;
6888 	int error = 0;
6889 	int c, long_response = 0;
6890 	int retval;
6891 
6892 	/*
6893 	 * Note that at the moment we don't support sending SMP CCBs to
6894 	 * devices that aren't probed by CAM.
6895 	 */
6896 	ccb = cam_getccb(device);
6897 	if (ccb == NULL) {
6898 		warnx("%s: error allocating CCB", __func__);
6899 		return (1);
6900 	}
6901 
6902 	bzero(&(&ccb->ccb_h)[1],
6903 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6904 
6905 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6906 		switch (c) {
6907 		case 'l':
6908 			long_response = 1;
6909 			break;
6910 		default:
6911 			break;
6912 		}
6913 	}
6914 	request = malloc(sizeof(*request));
6915 	if (request == NULL) {
6916 		warn("%s: unable to allocate %zd bytes", __func__,
6917 		     sizeof(*request));
6918 		error = 1;
6919 		goto bailout;
6920 	}
6921 
6922 	response = malloc(sizeof(*response));
6923 	if (response == NULL) {
6924 		warn("%s: unable to allocate %zd bytes", __func__,
6925 		     sizeof(*response));
6926 		error = 1;
6927 		goto bailout;
6928 	}
6929 
6930 try_long:
6931 	smp_report_general(&ccb->smpio,
6932 			   retry_count,
6933 			   /*cbfcnp*/ NULL,
6934 			   request,
6935 			   /*request_len*/ sizeof(*request),
6936 			   (uint8_t *)response,
6937 			   /*response_len*/ sizeof(*response),
6938 			   /*long_response*/ long_response,
6939 			   timeout);
6940 
6941 	if (((retval = cam_send_ccb(device, ccb)) < 0)
6942 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6943 		const char warnstr[] = "error sending command";
6944 
6945 		if (retval < 0)
6946 			warn(warnstr);
6947 		else
6948 			warnx(warnstr);
6949 
6950 		if (arglist & CAM_ARG_VERBOSE) {
6951 			cam_error_print(device, ccb, CAM_ESF_ALL,
6952 					CAM_EPF_ALL, stderr);
6953 		}
6954 		error = 1;
6955 		goto bailout;
6956 	}
6957 
6958 	/*
6959 	 * If the device supports the long response bit, try again and see
6960 	 * if we can get all of the data.
6961 	 */
6962 	if ((response->long_response & SMP_RG_LONG_RESPONSE)
6963 	 && (long_response == 0)) {
6964 		ccb->ccb_h.status = CAM_REQ_INPROG;
6965 		bzero(&(&ccb->ccb_h)[1],
6966 		      sizeof(union ccb) - sizeof(struct ccb_hdr));
6967 		long_response = 1;
6968 		goto try_long;
6969 	}
6970 
6971 	/*
6972 	 * XXX KDM detect and decode SMP errors here.
6973 	 */
6974 	sb = sbuf_new_auto();
6975 	if (sb == NULL) {
6976 		warnx("%s: error allocating sbuf", __func__);
6977 		goto bailout;
6978 	}
6979 
6980 	smp_report_general_sbuf(response, sizeof(*response), sb);
6981 
6982 	if (sbuf_finish(sb) != 0) {
6983 		warnx("%s: sbuf_finish", __func__);
6984 		goto bailout;
6985 	}
6986 
6987 	printf("%s", sbuf_data(sb));
6988 
6989 bailout:
6990 	if (ccb != NULL)
6991 		cam_freeccb(ccb);
6992 
6993 	if (request != NULL)
6994 		free(request);
6995 
6996 	if (response != NULL)
6997 		free(response);
6998 
6999 	if (sb != NULL)
7000 		sbuf_delete(sb);
7001 
7002 	return (error);
7003 }
7004 
7005 static struct camcontrol_opts phy_ops[] = {
7006 	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7007 	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7008 	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7009 	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7010 	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7011 	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7012 	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7013 	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7014 	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7015 	{NULL, 0, 0, NULL}
7016 };
7017 
7018 static int
7019 smpphycontrol(struct cam_device *device, int argc, char **argv,
7020 	      char *combinedopt, int retry_count, int timeout)
7021 {
7022 	union ccb *ccb;
7023 	struct smp_phy_control_request *request = NULL;
7024 	struct smp_phy_control_response *response = NULL;
7025 	int long_response = 0;
7026 	int retval = 0;
7027 	int phy = -1;
7028 	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7029 	int phy_op_set = 0;
7030 	uint64_t attached_dev_name = 0;
7031 	int dev_name_set = 0;
7032 	uint32_t min_plr = 0, max_plr = 0;
7033 	uint32_t pp_timeout_val = 0;
7034 	int slumber_partial = 0;
7035 	int set_pp_timeout_val = 0;
7036 	int c;
7037 
7038 	/*
7039 	 * Note that at the moment we don't support sending SMP CCBs to
7040 	 * devices that aren't probed by CAM.
7041 	 */
7042 	ccb = cam_getccb(device);
7043 	if (ccb == NULL) {
7044 		warnx("%s: error allocating CCB", __func__);
7045 		return (1);
7046 	}
7047 
7048 	bzero(&(&ccb->ccb_h)[1],
7049 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7050 
7051 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7052 		switch (c) {
7053 		case 'a':
7054 		case 'A':
7055 		case 's':
7056 		case 'S': {
7057 			int enable = -1;
7058 
7059 			if (strcasecmp(optarg, "enable") == 0)
7060 				enable = 1;
7061 			else if (strcasecmp(optarg, "disable") == 0)
7062 				enable = 2;
7063 			else {
7064 				warnx("%s: Invalid argument %s", __func__,
7065 				      optarg);
7066 				retval = 1;
7067 				goto bailout;
7068 			}
7069 			switch (c) {
7070 			case 's':
7071 				slumber_partial |= enable <<
7072 						   SMP_PC_SAS_SLUMBER_SHIFT;
7073 				break;
7074 			case 'S':
7075 				slumber_partial |= enable <<
7076 						   SMP_PC_SAS_PARTIAL_SHIFT;
7077 				break;
7078 			case 'a':
7079 				slumber_partial |= enable <<
7080 						   SMP_PC_SATA_SLUMBER_SHIFT;
7081 				break;
7082 			case 'A':
7083 				slumber_partial |= enable <<
7084 						   SMP_PC_SATA_PARTIAL_SHIFT;
7085 				break;
7086 			default:
7087 				warnx("%s: programmer error", __func__);
7088 				retval = 1;
7089 				goto bailout;
7090 				break; /*NOTREACHED*/
7091 			}
7092 			break;
7093 		}
7094 		case 'd':
7095 			attached_dev_name = (uintmax_t)strtoumax(optarg,
7096 								 NULL,0);
7097 			dev_name_set = 1;
7098 			break;
7099 		case 'l':
7100 			long_response = 1;
7101 			break;
7102 		case 'm':
7103 			/*
7104 			 * We don't do extensive checking here, so this
7105 			 * will continue to work when new speeds come out.
7106 			 */
7107 			min_plr = strtoul(optarg, NULL, 0);
7108 			if ((min_plr == 0)
7109 			 || (min_plr > 0xf)) {
7110 				warnx("%s: invalid link rate %x",
7111 				      __func__, min_plr);
7112 				retval = 1;
7113 				goto bailout;
7114 			}
7115 			break;
7116 		case 'M':
7117 			/*
7118 			 * We don't do extensive checking here, so this
7119 			 * will continue to work when new speeds come out.
7120 			 */
7121 			max_plr = strtoul(optarg, NULL, 0);
7122 			if ((max_plr == 0)
7123 			 || (max_plr > 0xf)) {
7124 				warnx("%s: invalid link rate %x",
7125 				      __func__, max_plr);
7126 				retval = 1;
7127 				goto bailout;
7128 			}
7129 			break;
7130 		case 'o': {
7131 			camcontrol_optret optreturn;
7132 			cam_argmask argnums;
7133 			const char *subopt;
7134 
7135 			if (phy_op_set != 0) {
7136 				warnx("%s: only one phy operation argument "
7137 				      "(-o) allowed", __func__);
7138 				retval = 1;
7139 				goto bailout;
7140 			}
7141 
7142 			phy_op_set = 1;
7143 
7144 			/*
7145 			 * Allow the user to specify the phy operation
7146 			 * numerically, as well as with a name.  This will
7147 			 * future-proof it a bit, so options that are added
7148 			 * in future specs can be used.
7149 			 */
7150 			if (isdigit(optarg[0])) {
7151 				phy_operation = strtoul(optarg, NULL, 0);
7152 				if ((phy_operation == 0)
7153 				 || (phy_operation > 0xff)) {
7154 					warnx("%s: invalid phy operation %#x",
7155 					      __func__, phy_operation);
7156 					retval = 1;
7157 					goto bailout;
7158 				}
7159 				break;
7160 			}
7161 			optreturn = getoption(phy_ops, optarg, &phy_operation,
7162 					      &argnums, &subopt);
7163 
7164 			if (optreturn == CC_OR_AMBIGUOUS) {
7165 				warnx("%s: ambiguous option %s", __func__,
7166 				      optarg);
7167 				usage(0);
7168 				retval = 1;
7169 				goto bailout;
7170 			} else if (optreturn == CC_OR_NOT_FOUND) {
7171 				warnx("%s: option %s not found", __func__,
7172 				      optarg);
7173 				usage(0);
7174 				retval = 1;
7175 				goto bailout;
7176 			}
7177 			break;
7178 		}
7179 		case 'p':
7180 			phy = atoi(optarg);
7181 			break;
7182 		case 'T':
7183 			pp_timeout_val = strtoul(optarg, NULL, 0);
7184 			if (pp_timeout_val > 15) {
7185 				warnx("%s: invalid partial pathway timeout "
7186 				      "value %u, need a value less than 16",
7187 				      __func__, pp_timeout_val);
7188 				retval = 1;
7189 				goto bailout;
7190 			}
7191 			set_pp_timeout_val = 1;
7192 			break;
7193 		default:
7194 			break;
7195 		}
7196 	}
7197 
7198 	if (phy == -1) {
7199 		warnx("%s: a PHY (-p phy) argument is required",__func__);
7200 		retval = 1;
7201 		goto bailout;
7202 	}
7203 
7204 	if (((dev_name_set != 0)
7205 	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7206 	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7207 	  && (dev_name_set == 0))) {
7208 		warnx("%s: -d name and -o setdevname arguments both "
7209 		      "required to set device name", __func__);
7210 		retval = 1;
7211 		goto bailout;
7212 	}
7213 
7214 	request = malloc(sizeof(*request));
7215 	if (request == NULL) {
7216 		warn("%s: unable to allocate %zd bytes", __func__,
7217 		     sizeof(*request));
7218 		retval = 1;
7219 		goto bailout;
7220 	}
7221 
7222 	response = malloc(sizeof(*response));
7223 	if (response == NULL) {
7224 		warn("%s: unable to allocate %zd bytes", __func__,
7225 		     sizeof(*request));
7226 		retval = 1;
7227 		goto bailout;
7228 	}
7229 
7230 	smp_phy_control(&ccb->smpio,
7231 			retry_count,
7232 			/*cbfcnp*/ NULL,
7233 			request,
7234 			sizeof(*request),
7235 			(uint8_t *)response,
7236 			sizeof(*response),
7237 			long_response,
7238 			/*expected_exp_change_count*/ 0,
7239 			phy,
7240 			phy_operation,
7241 			(set_pp_timeout_val != 0) ? 1 : 0,
7242 			attached_dev_name,
7243 			min_plr,
7244 			max_plr,
7245 			slumber_partial,
7246 			pp_timeout_val,
7247 			timeout);
7248 
7249 	if (((retval = cam_send_ccb(device, ccb)) < 0)
7250 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7251 		const char warnstr[] = "error sending command";
7252 
7253 		if (retval < 0)
7254 			warn(warnstr);
7255 		else
7256 			warnx(warnstr);
7257 
7258 		if (arglist & CAM_ARG_VERBOSE) {
7259 			/*
7260 			 * Use CAM_EPF_NORMAL so we only get one line of
7261 			 * SMP command decoding.
7262 			 */
7263 			cam_error_print(device, ccb, CAM_ESF_ALL,
7264 					CAM_EPF_NORMAL, stderr);
7265 		}
7266 		retval = 1;
7267 		goto bailout;
7268 	}
7269 
7270 	/* XXX KDM print out something here for success? */
7271 bailout:
7272 	if (ccb != NULL)
7273 		cam_freeccb(ccb);
7274 
7275 	if (request != NULL)
7276 		free(request);
7277 
7278 	if (response != NULL)
7279 		free(response);
7280 
7281 	return (retval);
7282 }
7283 
7284 static int
7285 smpmaninfo(struct cam_device *device, int argc, char **argv,
7286 	   char *combinedopt, int retry_count, int timeout)
7287 {
7288 	union ccb *ccb;
7289 	struct smp_report_manuf_info_request request;
7290 	struct smp_report_manuf_info_response response;
7291 	struct sbuf *sb = NULL;
7292 	int long_response = 0;
7293 	int retval = 0;
7294 	int c;
7295 
7296 	/*
7297 	 * Note that at the moment we don't support sending SMP CCBs to
7298 	 * devices that aren't probed by CAM.
7299 	 */
7300 	ccb = cam_getccb(device);
7301 	if (ccb == NULL) {
7302 		warnx("%s: error allocating CCB", __func__);
7303 		return (1);
7304 	}
7305 
7306 	bzero(&(&ccb->ccb_h)[1],
7307 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7308 
7309 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7310 		switch (c) {
7311 		case 'l':
7312 			long_response = 1;
7313 			break;
7314 		default:
7315 			break;
7316 		}
7317 	}
7318 	bzero(&request, sizeof(request));
7319 	bzero(&response, sizeof(response));
7320 
7321 	smp_report_manuf_info(&ccb->smpio,
7322 			      retry_count,
7323 			      /*cbfcnp*/ NULL,
7324 			      &request,
7325 			      sizeof(request),
7326 			      (uint8_t *)&response,
7327 			      sizeof(response),
7328 			      long_response,
7329 			      timeout);
7330 
7331 	if (((retval = cam_send_ccb(device, ccb)) < 0)
7332 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7333 		const char warnstr[] = "error sending command";
7334 
7335 		if (retval < 0)
7336 			warn(warnstr);
7337 		else
7338 			warnx(warnstr);
7339 
7340 		if (arglist & CAM_ARG_VERBOSE) {
7341 			cam_error_print(device, ccb, CAM_ESF_ALL,
7342 					CAM_EPF_ALL, stderr);
7343 		}
7344 		retval = 1;
7345 		goto bailout;
7346 	}
7347 
7348 	sb = sbuf_new_auto();
7349 	if (sb == NULL) {
7350 		warnx("%s: error allocating sbuf", __func__);
7351 		goto bailout;
7352 	}
7353 
7354 	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7355 
7356 	if (sbuf_finish(sb) != 0) {
7357 		warnx("%s: sbuf_finish", __func__);
7358 		goto bailout;
7359 	}
7360 
7361 	printf("%s", sbuf_data(sb));
7362 
7363 bailout:
7364 
7365 	if (ccb != NULL)
7366 		cam_freeccb(ccb);
7367 
7368 	if (sb != NULL)
7369 		sbuf_delete(sb);
7370 
7371 	return (retval);
7372 }
7373 
7374 static int
7375 getdevid(struct cam_devitem *item)
7376 {
7377 	int retval = 0;
7378 	union ccb *ccb = NULL;
7379 
7380 	struct cam_device *dev;
7381 
7382 	dev = cam_open_btl(item->dev_match.path_id,
7383 			   item->dev_match.target_id,
7384 			   item->dev_match.target_lun, O_RDWR, NULL);
7385 
7386 	if (dev == NULL) {
7387 		warnx("%s", cam_errbuf);
7388 		retval = 1;
7389 		goto bailout;
7390 	}
7391 
7392 	item->device_id_len = 0;
7393 
7394 	ccb = cam_getccb(dev);
7395 	if (ccb == NULL) {
7396 		warnx("%s: error allocating CCB", __func__);
7397 		retval = 1;
7398 		goto bailout;
7399 	}
7400 
7401 	bzero(&(&ccb->ccb_h)[1],
7402 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7403 
7404 	/*
7405 	 * On the first try, we just probe for the size of the data, and
7406 	 * then allocate that much memory and try again.
7407 	 */
7408 retry:
7409 	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7410 	ccb->ccb_h.flags = CAM_DIR_IN;
7411 	ccb->cdai.flags = CDAI_FLAG_NONE;
7412 	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7413 	ccb->cdai.bufsiz = item->device_id_len;
7414 	if (item->device_id_len != 0)
7415 		ccb->cdai.buf = (uint8_t *)item->device_id;
7416 
7417 	if (cam_send_ccb(dev, ccb) < 0) {
7418 		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7419 		retval = 1;
7420 		goto bailout;
7421 	}
7422 
7423 	if (ccb->ccb_h.status != CAM_REQ_CMP) {
7424 		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7425 		retval = 1;
7426 		goto bailout;
7427 	}
7428 
7429 	if (item->device_id_len == 0) {
7430 		/*
7431 		 * This is our first time through.  Allocate the buffer,
7432 		 * and then go back to get the data.
7433 		 */
7434 		if (ccb->cdai.provsiz == 0) {
7435 			warnx("%s: invalid .provsiz field returned with "
7436 			     "XPT_GDEV_ADVINFO CCB", __func__);
7437 			retval = 1;
7438 			goto bailout;
7439 		}
7440 		item->device_id_len = ccb->cdai.provsiz;
7441 		item->device_id = malloc(item->device_id_len);
7442 		if (item->device_id == NULL) {
7443 			warn("%s: unable to allocate %d bytes", __func__,
7444 			     item->device_id_len);
7445 			retval = 1;
7446 			goto bailout;
7447 		}
7448 		ccb->ccb_h.status = CAM_REQ_INPROG;
7449 		goto retry;
7450 	}
7451 
7452 bailout:
7453 	if (dev != NULL)
7454 		cam_close_device(dev);
7455 
7456 	if (ccb != NULL)
7457 		cam_freeccb(ccb);
7458 
7459 	return (retval);
7460 }
7461 
7462 /*
7463  * XXX KDM merge this code with getdevtree()?
7464  */
7465 static int
7466 buildbusdevlist(struct cam_devlist *devlist)
7467 {
7468 	union ccb ccb;
7469 	int bufsize, fd = -1;
7470 	struct dev_match_pattern *patterns;
7471 	struct cam_devitem *item = NULL;
7472 	int skip_device = 0;
7473 	int retval = 0;
7474 
7475 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7476 		warn("couldn't open %s", XPT_DEVICE);
7477 		return(1);
7478 	}
7479 
7480 	bzero(&ccb, sizeof(union ccb));
7481 
7482 	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7483 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7484 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7485 
7486 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
7487 	bufsize = sizeof(struct dev_match_result) * 100;
7488 	ccb.cdm.match_buf_len = bufsize;
7489 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7490 	if (ccb.cdm.matches == NULL) {
7491 		warnx("can't malloc memory for matches");
7492 		close(fd);
7493 		return(1);
7494 	}
7495 	ccb.cdm.num_matches = 0;
7496 	ccb.cdm.num_patterns = 2;
7497 	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7498 		ccb.cdm.num_patterns;
7499 
7500 	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7501 	if (patterns == NULL) {
7502 		warnx("can't malloc memory for patterns");
7503 		retval = 1;
7504 		goto bailout;
7505 	}
7506 
7507 	ccb.cdm.patterns = patterns;
7508 	bzero(patterns, ccb.cdm.pattern_buf_len);
7509 
7510 	patterns[0].type = DEV_MATCH_DEVICE;
7511 	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7512 	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7513 	patterns[1].type = DEV_MATCH_PERIPH;
7514 	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7515 	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7516 
7517 	/*
7518 	 * We do the ioctl multiple times if necessary, in case there are
7519 	 * more than 100 nodes in the EDT.
7520 	 */
7521 	do {
7522 		unsigned int i;
7523 
7524 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7525 			warn("error sending CAMIOCOMMAND ioctl");
7526 			retval = 1;
7527 			goto bailout;
7528 		}
7529 
7530 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
7531 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7532 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7533 			warnx("got CAM error %#x, CDM error %d\n",
7534 			      ccb.ccb_h.status, ccb.cdm.status);
7535 			retval = 1;
7536 			goto bailout;
7537 		}
7538 
7539 		for (i = 0; i < ccb.cdm.num_matches; i++) {
7540 			switch (ccb.cdm.matches[i].type) {
7541 			case DEV_MATCH_DEVICE: {
7542 				struct device_match_result *dev_result;
7543 
7544 				dev_result =
7545 				     &ccb.cdm.matches[i].result.device_result;
7546 
7547 				if (dev_result->flags &
7548 				    DEV_RESULT_UNCONFIGURED) {
7549 					skip_device = 1;
7550 					break;
7551 				} else
7552 					skip_device = 0;
7553 
7554 				item = malloc(sizeof(*item));
7555 				if (item == NULL) {
7556 					warn("%s: unable to allocate %zd bytes",
7557 					     __func__, sizeof(*item));
7558 					retval = 1;
7559 					goto bailout;
7560 				}
7561 				bzero(item, sizeof(*item));
7562 				bcopy(dev_result, &item->dev_match,
7563 				      sizeof(*dev_result));
7564 				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7565 						   links);
7566 
7567 				if (getdevid(item) != 0) {
7568 					retval = 1;
7569 					goto bailout;
7570 				}
7571 				break;
7572 			}
7573 			case DEV_MATCH_PERIPH: {
7574 				struct periph_match_result *periph_result;
7575 
7576 				periph_result =
7577 				      &ccb.cdm.matches[i].result.periph_result;
7578 
7579 				if (skip_device != 0)
7580 					break;
7581 				item->num_periphs++;
7582 				item->periph_matches = realloc(
7583 					item->periph_matches,
7584 					item->num_periphs *
7585 					sizeof(struct periph_match_result));
7586 				if (item->periph_matches == NULL) {
7587 					warn("%s: error allocating periph "
7588 					     "list", __func__);
7589 					retval = 1;
7590 					goto bailout;
7591 				}
7592 				bcopy(periph_result, &item->periph_matches[
7593 				      item->num_periphs - 1],
7594 				      sizeof(*periph_result));
7595 				break;
7596 			}
7597 			default:
7598 				fprintf(stderr, "%s: unexpected match "
7599 					"type %d\n", __func__,
7600 					ccb.cdm.matches[i].type);
7601 				retval = 1;
7602 				goto bailout;
7603 				break; /*NOTREACHED*/
7604 			}
7605 		}
7606 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
7607 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7608 bailout:
7609 
7610 	if (fd != -1)
7611 		close(fd);
7612 
7613 	free(patterns);
7614 
7615 	free(ccb.cdm.matches);
7616 
7617 	if (retval != 0)
7618 		freebusdevlist(devlist);
7619 
7620 	return (retval);
7621 }
7622 
7623 static void
7624 freebusdevlist(struct cam_devlist *devlist)
7625 {
7626 	struct cam_devitem *item, *item2;
7627 
7628 	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7629 		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7630 			      links);
7631 		free(item->device_id);
7632 		free(item->periph_matches);
7633 		free(item);
7634 	}
7635 }
7636 
7637 static struct cam_devitem *
7638 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7639 {
7640 	struct cam_devitem *item;
7641 
7642 	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7643 		struct scsi_vpd_id_descriptor *idd;
7644 
7645 		/*
7646 		 * XXX KDM look for LUN IDs as well?
7647 		 */
7648 		idd = scsi_get_devid(item->device_id,
7649 					   item->device_id_len,
7650 					   scsi_devid_is_sas_target);
7651 		if (idd == NULL)
7652 			continue;
7653 
7654 		if (scsi_8btou64(idd->identifier) == sasaddr)
7655 			return (item);
7656 	}
7657 
7658 	return (NULL);
7659 }
7660 
7661 static int
7662 smpphylist(struct cam_device *device, int argc, char **argv,
7663 	   char *combinedopt, int retry_count, int timeout)
7664 {
7665 	struct smp_report_general_request *rgrequest = NULL;
7666 	struct smp_report_general_response *rgresponse = NULL;
7667 	struct smp_discover_request *disrequest = NULL;
7668 	struct smp_discover_response *disresponse = NULL;
7669 	struct cam_devlist devlist;
7670 	union ccb *ccb;
7671 	int long_response = 0;
7672 	int num_phys = 0;
7673 	int quiet = 0;
7674 	int retval;
7675 	int i, c;
7676 
7677 	/*
7678 	 * Note that at the moment we don't support sending SMP CCBs to
7679 	 * devices that aren't probed by CAM.
7680 	 */
7681 	ccb = cam_getccb(device);
7682 	if (ccb == NULL) {
7683 		warnx("%s: error allocating CCB", __func__);
7684 		return (1);
7685 	}
7686 
7687 	bzero(&(&ccb->ccb_h)[1],
7688 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7689 	STAILQ_INIT(&devlist.dev_queue);
7690 
7691 	rgrequest = malloc(sizeof(*rgrequest));
7692 	if (rgrequest == NULL) {
7693 		warn("%s: unable to allocate %zd bytes", __func__,
7694 		     sizeof(*rgrequest));
7695 		retval = 1;
7696 		goto bailout;
7697 	}
7698 
7699 	rgresponse = malloc(sizeof(*rgresponse));
7700 	if (rgresponse == NULL) {
7701 		warn("%s: unable to allocate %zd bytes", __func__,
7702 		     sizeof(*rgresponse));
7703 		retval = 1;
7704 		goto bailout;
7705 	}
7706 
7707 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7708 		switch (c) {
7709 		case 'l':
7710 			long_response = 1;
7711 			break;
7712 		case 'q':
7713 			quiet = 1;
7714 			break;
7715 		default:
7716 			break;
7717 		}
7718 	}
7719 
7720 	smp_report_general(&ccb->smpio,
7721 			   retry_count,
7722 			   /*cbfcnp*/ NULL,
7723 			   rgrequest,
7724 			   /*request_len*/ sizeof(*rgrequest),
7725 			   (uint8_t *)rgresponse,
7726 			   /*response_len*/ sizeof(*rgresponse),
7727 			   /*long_response*/ long_response,
7728 			   timeout);
7729 
7730 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7731 
7732 	if (((retval = cam_send_ccb(device, ccb)) < 0)
7733 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7734 		const char warnstr[] = "error sending command";
7735 
7736 		if (retval < 0)
7737 			warn(warnstr);
7738 		else
7739 			warnx(warnstr);
7740 
7741 		if (arglist & CAM_ARG_VERBOSE) {
7742 			cam_error_print(device, ccb, CAM_ESF_ALL,
7743 					CAM_EPF_ALL, stderr);
7744 		}
7745 		retval = 1;
7746 		goto bailout;
7747 	}
7748 
7749 	num_phys = rgresponse->num_phys;
7750 
7751 	if (num_phys == 0) {
7752 		if (quiet == 0)
7753 			fprintf(stdout, "%s: No Phys reported\n", __func__);
7754 		retval = 1;
7755 		goto bailout;
7756 	}
7757 
7758 	devlist.path_id = device->path_id;
7759 
7760 	retval = buildbusdevlist(&devlist);
7761 	if (retval != 0)
7762 		goto bailout;
7763 
7764 	if (quiet == 0) {
7765 		fprintf(stdout, "%d PHYs:\n", num_phys);
7766 		fprintf(stdout, "PHY  Attached SAS Address\n");
7767 	}
7768 
7769 	disrequest = malloc(sizeof(*disrequest));
7770 	if (disrequest == NULL) {
7771 		warn("%s: unable to allocate %zd bytes", __func__,
7772 		     sizeof(*disrequest));
7773 		retval = 1;
7774 		goto bailout;
7775 	}
7776 
7777 	disresponse = malloc(sizeof(*disresponse));
7778 	if (disresponse == NULL) {
7779 		warn("%s: unable to allocate %zd bytes", __func__,
7780 		     sizeof(*disresponse));
7781 		retval = 1;
7782 		goto bailout;
7783 	}
7784 
7785 	for (i = 0; i < num_phys; i++) {
7786 		struct cam_devitem *item;
7787 		struct device_match_result *dev_match;
7788 		char vendor[16], product[48], revision[16];
7789 		char tmpstr[256];
7790 		int j;
7791 
7792 		bzero(&(&ccb->ccb_h)[1],
7793 		      sizeof(union ccb) - sizeof(struct ccb_hdr));
7794 
7795 		ccb->ccb_h.status = CAM_REQ_INPROG;
7796 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7797 
7798 		smp_discover(&ccb->smpio,
7799 			     retry_count,
7800 			     /*cbfcnp*/ NULL,
7801 			     disrequest,
7802 			     sizeof(*disrequest),
7803 			     (uint8_t *)disresponse,
7804 			     sizeof(*disresponse),
7805 			     long_response,
7806 			     /*ignore_zone_group*/ 0,
7807 			     /*phy*/ i,
7808 			     timeout);
7809 
7810 		if (((retval = cam_send_ccb(device, ccb)) < 0)
7811 		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7812 		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7813 			const char warnstr[] = "error sending command";
7814 
7815 			if (retval < 0)
7816 				warn(warnstr);
7817 			else
7818 				warnx(warnstr);
7819 
7820 			if (arglist & CAM_ARG_VERBOSE) {
7821 				cam_error_print(device, ccb, CAM_ESF_ALL,
7822 						CAM_EPF_ALL, stderr);
7823 			}
7824 			retval = 1;
7825 			goto bailout;
7826 		}
7827 
7828 		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7829 			if (quiet == 0)
7830 				fprintf(stdout, "%3d  <vacant>\n", i);
7831 			continue;
7832 		}
7833 
7834 		if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7835 			item = NULL;
7836 		} else {
7837 			item = findsasdevice(&devlist,
7838 			    scsi_8btou64(disresponse->attached_sas_address));
7839 		}
7840 
7841 		if ((quiet == 0)
7842 		 || (item != NULL)) {
7843 			fprintf(stdout, "%3d  0x%016jx", i,
7844 				(uintmax_t)scsi_8btou64(
7845 				disresponse->attached_sas_address));
7846 			if (item == NULL) {
7847 				fprintf(stdout, "\n");
7848 				continue;
7849 			}
7850 		} else if (quiet != 0)
7851 			continue;
7852 
7853 		dev_match = &item->dev_match;
7854 
7855 		if (dev_match->protocol == PROTO_SCSI) {
7856 			cam_strvis(vendor, dev_match->inq_data.vendor,
7857 				   sizeof(dev_match->inq_data.vendor),
7858 				   sizeof(vendor));
7859 			cam_strvis(product, dev_match->inq_data.product,
7860 				   sizeof(dev_match->inq_data.product),
7861 				   sizeof(product));
7862 			cam_strvis(revision, dev_match->inq_data.revision,
7863 				   sizeof(dev_match->inq_data.revision),
7864 				   sizeof(revision));
7865 			sprintf(tmpstr, "<%s %s %s>", vendor, product,
7866 				revision);
7867 		} else if ((dev_match->protocol == PROTO_ATA)
7868 			|| (dev_match->protocol == PROTO_SATAPM)) {
7869 			cam_strvis(product, dev_match->ident_data.model,
7870 				   sizeof(dev_match->ident_data.model),
7871 				   sizeof(product));
7872 			cam_strvis(revision, dev_match->ident_data.revision,
7873 				   sizeof(dev_match->ident_data.revision),
7874 				   sizeof(revision));
7875 			sprintf(tmpstr, "<%s %s>", product, revision);
7876 		} else {
7877 			sprintf(tmpstr, "<>");
7878 		}
7879 		fprintf(stdout, "   %-33s ", tmpstr);
7880 
7881 		/*
7882 		 * If we have 0 periphs, that's a bug...
7883 		 */
7884 		if (item->num_periphs == 0) {
7885 			fprintf(stdout, "\n");
7886 			continue;
7887 		}
7888 
7889 		fprintf(stdout, "(");
7890 		for (j = 0; j < item->num_periphs; j++) {
7891 			if (j > 0)
7892 				fprintf(stdout, ",");
7893 
7894 			fprintf(stdout, "%s%d",
7895 				item->periph_matches[j].periph_name,
7896 				item->periph_matches[j].unit_number);
7897 
7898 		}
7899 		fprintf(stdout, ")\n");
7900 	}
7901 bailout:
7902 	if (ccb != NULL)
7903 		cam_freeccb(ccb);
7904 
7905 	free(rgrequest);
7906 
7907 	free(rgresponse);
7908 
7909 	free(disrequest);
7910 
7911 	free(disresponse);
7912 
7913 	freebusdevlist(&devlist);
7914 
7915 	return (retval);
7916 }
7917 
7918 static int
7919 atapm(struct cam_device *device, int argc, char **argv,
7920 		 char *combinedopt, int retry_count, int timeout)
7921 {
7922 	union ccb *ccb;
7923 	int retval = 0;
7924 	int t = -1;
7925 	int c;
7926 	u_char cmd, sc;
7927 
7928 	ccb = cam_getccb(device);
7929 
7930 	if (ccb == NULL) {
7931 		warnx("%s: error allocating ccb", __func__);
7932 		return (1);
7933 	}
7934 
7935 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7936 		switch (c) {
7937 		case 't':
7938 			t = atoi(optarg);
7939 			break;
7940 		default:
7941 			break;
7942 		}
7943 	}
7944 	if (strcmp(argv[1], "idle") == 0) {
7945 		if (t == -1)
7946 			cmd = ATA_IDLE_IMMEDIATE;
7947 		else
7948 			cmd = ATA_IDLE_CMD;
7949 	} else if (strcmp(argv[1], "standby") == 0) {
7950 		if (t == -1)
7951 			cmd = ATA_STANDBY_IMMEDIATE;
7952 		else
7953 			cmd = ATA_STANDBY_CMD;
7954 	} else {
7955 		cmd = ATA_SLEEP;
7956 		t = -1;
7957 	}
7958 
7959 	if (t < 0)
7960 		sc = 0;
7961 	else if (t <= (240 * 5))
7962 		sc = (t + 4) / 5;
7963 	else if (t <= (252 * 5))
7964 		/* special encoding for 21 minutes */
7965 		sc = 252;
7966 	else if (t <= (11 * 30 * 60))
7967 		sc = (t - 1) / (30 * 60) + 241;
7968 	else
7969 		sc = 253;
7970 
7971 	retval = ata_do_28bit_cmd(device,
7972 	    ccb,
7973 	    /*retries*/retry_count,
7974 	    /*flags*/CAM_DIR_NONE,
7975 	    /*protocol*/AP_PROTO_NON_DATA,
7976 	    /*tag_action*/MSG_SIMPLE_Q_TAG,
7977 	    /*command*/cmd,
7978 	    /*features*/0,
7979 	    /*lba*/0,
7980 	    /*sector_count*/sc,
7981 	    /*data_ptr*/NULL,
7982 	    /*dxfer_len*/0,
7983 	    /*timeout*/timeout ? timeout : 30 * 1000,
7984 	    /*quiet*/1);
7985 
7986 	cam_freeccb(ccb);
7987 	return (retval);
7988 }
7989 
7990 static int
7991 ataaxm(struct cam_device *device, int argc, char **argv,
7992 		 char *combinedopt, int retry_count, int timeout)
7993 {
7994 	union ccb *ccb;
7995 	int retval = 0;
7996 	int l = -1;
7997 	int c;
7998 	u_char cmd, sc;
7999 
8000 	ccb = cam_getccb(device);
8001 
8002 	if (ccb == NULL) {
8003 		warnx("%s: error allocating ccb", __func__);
8004 		return (1);
8005 	}
8006 
8007 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8008 		switch (c) {
8009 		case 'l':
8010 			l = atoi(optarg);
8011 			break;
8012 		default:
8013 			break;
8014 		}
8015 	}
8016 	sc = 0;
8017 	if (strcmp(argv[1], "apm") == 0) {
8018 		if (l == -1)
8019 			cmd = 0x85;
8020 		else {
8021 			cmd = 0x05;
8022 			sc = l;
8023 		}
8024 	} else /* aam */ {
8025 		if (l == -1)
8026 			cmd = 0xC2;
8027 		else {
8028 			cmd = 0x42;
8029 			sc = l;
8030 		}
8031 	}
8032 
8033 	retval = ata_do_28bit_cmd(device,
8034 	    ccb,
8035 	    /*retries*/retry_count,
8036 	    /*flags*/CAM_DIR_NONE,
8037 	    /*protocol*/AP_PROTO_NON_DATA,
8038 	    /*tag_action*/MSG_SIMPLE_Q_TAG,
8039 	    /*command*/ATA_SETFEATURES,
8040 	    /*features*/cmd,
8041 	    /*lba*/0,
8042 	    /*sector_count*/sc,
8043 	    /*data_ptr*/NULL,
8044 	    /*dxfer_len*/0,
8045 	    /*timeout*/timeout ? timeout : 30 * 1000,
8046 	    /*quiet*/1);
8047 
8048 	cam_freeccb(ccb);
8049 	return (retval);
8050 }
8051 
8052 #endif /* MINIMALISTIC */
8053 
8054 void
8055 usage(int printlong)
8056 {
8057 
8058 	fprintf(printlong ? stdout : stderr,
8059 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
8060 "        camcontrol devlist    [-v]\n"
8061 #ifndef MINIMALISTIC
8062 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8063 "        camcontrol tur        [dev_id][generic args]\n"
8064 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
8065 "        camcontrol identify   [dev_id][generic args] [-v]\n"
8066 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8067 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8068 "                              [-q] [-s]\n"
8069 "        camcontrol start      [dev_id][generic args]\n"
8070 "        camcontrol stop       [dev_id][generic args]\n"
8071 "        camcontrol load       [dev_id][generic args]\n"
8072 "        camcontrol eject      [dev_id][generic args]\n"
8073 #endif /* MINIMALISTIC */
8074 "        camcontrol rescan     <all | bus[:target:lun]>\n"
8075 "        camcontrol reset      <all | bus[:target:lun]>\n"
8076 #ifndef MINIMALISTIC
8077 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
8078 "                              [-q][-s][-S offset][-X]\n"
8079 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
8080 "                              [-P pagectl][-e | -b][-d]\n"
8081 "        camcontrol cmd        [dev_id][generic args]\n"
8082 "                              <-a cmd [args] | -c cmd [args]>\n"
8083 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8084 "        camcontrol smpcmd     [dev_id][generic args]\n"
8085 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
8086 "        camcontrol smprg      [dev_id][generic args][-l]\n"
8087 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
8088 "                              [-o operation][-d name][-m rate][-M rate]\n"
8089 "                              [-T pp_timeout][-a enable|disable]\n"
8090 "                              [-A enable|disable][-s enable|disable]\n"
8091 "                              [-S enable|disable]\n"
8092 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8093 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8094 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
8095 "                              <all|bus[:target[:lun]]|off>\n"
8096 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
8097 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
8098 "                              [-D <enable|disable>][-M mode][-O offset]\n"
8099 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
8100 "                              [-U][-W bus_width]\n"
8101 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
8102 "        camcontrol sanitize   [dev_id][generic args]\n"
8103 "                              [-a overwrite|block|crypto|exitfailure]\n"
8104 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8105 "                              [-y]\n"
8106 "        camcontrol idle       [dev_id][generic args][-t time]\n"
8107 "        camcontrol standby    [dev_id][generic args][-t time]\n"
8108 "        camcontrol sleep      [dev_id][generic args]\n"
8109 "        camcontrol apm        [dev_id][generic args][-l level]\n"
8110 "        camcontrol aam        [dev_id][generic args][-l level]\n"
8111 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
8112 "        camcontrol security   [dev_id][generic args]\n"
8113 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8114 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8115 "                              [-U <user|master>] [-y]\n"
8116 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8117 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
8118 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
8119 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8120 "                              [-s scope][-S][-T type][-U]\n"
8121 #endif /* MINIMALISTIC */
8122 "        camcontrol help\n");
8123 	if (!printlong)
8124 		return;
8125 #ifndef MINIMALISTIC
8126 	fprintf(stdout,
8127 "Specify one of the following options:\n"
8128 "devlist     list all CAM devices\n"
8129 "periphlist  list all CAM peripheral drivers attached to a device\n"
8130 "tur         send a test unit ready to the named device\n"
8131 "inquiry     send a SCSI inquiry command to the named device\n"
8132 "identify    send a ATA identify command to the named device\n"
8133 "reportluns  send a SCSI report luns command to the device\n"
8134 "readcap     send a SCSI read capacity command to the device\n"
8135 "start       send a Start Unit command to the device\n"
8136 "stop        send a Stop Unit command to the device\n"
8137 "load        send a Start Unit command to the device with the load bit set\n"
8138 "eject       send a Stop Unit command to the device with the eject bit set\n"
8139 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
8140 "reset       reset all busses, the given bus, or bus:target:lun\n"
8141 "defects     read the defect list of the specified device\n"
8142 "modepage    display or edit (-e) the given mode page\n"
8143 "cmd         send the given SCSI command, may need -i or -o as well\n"
8144 "smpcmd      send the given SMP command, requires -o and -i\n"
8145 "smprg       send the SMP Report General command\n"
8146 "smppc       send the SMP PHY Control command, requires -p\n"
8147 "smpphylist  display phys attached to a SAS expander\n"
8148 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
8149 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
8150 "tags        report or set the number of transaction slots for a device\n"
8151 "negotiate   report or set device negotiation parameters\n"
8152 "format      send the SCSI FORMAT UNIT command to the named device\n"
8153 "sanitize    send the SCSI SANITIZE command to the named device\n"
8154 "idle        send the ATA IDLE command to the named device\n"
8155 "standby     send the ATA STANDBY command to the named device\n"
8156 "sleep       send the ATA SLEEP command to the named device\n"
8157 "fwdownload  program firmware of the named device with the given image\n"
8158 "security    report or send ATA security commands to the named device\n"
8159 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8160 "help        this message\n"
8161 "Device Identifiers:\n"
8162 "bus:target        specify the bus and target, lun defaults to 0\n"
8163 "bus:target:lun    specify the bus, target and lun\n"
8164 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
8165 "Generic arguments:\n"
8166 "-v                be verbose, print out sense information\n"
8167 "-t timeout        command timeout in seconds, overrides default timeout\n"
8168 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
8169 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
8170 "-E                have the kernel attempt to perform SCSI error recovery\n"
8171 "-C count          specify the SCSI command retry count (needs -E to work)\n"
8172 "modepage arguments:\n"
8173 "-l                list all available mode pages\n"
8174 "-m page           specify the mode page to view or edit\n"
8175 "-e                edit the specified mode page\n"
8176 "-b                force view to binary mode\n"
8177 "-d                disable block descriptors for mode sense\n"
8178 "-P pgctl          page control field 0-3\n"
8179 "defects arguments:\n"
8180 "-f format         specify defect list format (block, bfi or phys)\n"
8181 "-G                get the grown defect list\n"
8182 "-P                get the permanent defect list\n"
8183 "inquiry arguments:\n"
8184 "-D                get the standard inquiry data\n"
8185 "-S                get the serial number\n"
8186 "-R                get the transfer rate, etc.\n"
8187 "reportluns arguments:\n"
8188 "-c                only report a count of available LUNs\n"
8189 "-l                only print out luns, and not a count\n"
8190 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
8191 "readcap arguments\n"
8192 "-b                only report the blocksize\n"
8193 "-h                human readable device size, base 2\n"
8194 "-H                human readable device size, base 10\n"
8195 "-N                print the number of blocks instead of last block\n"
8196 "-q                quiet, print numbers only\n"
8197 "-s                only report the last block/device size\n"
8198 "cmd arguments:\n"
8199 "-c cdb [args]     specify the SCSI CDB\n"
8200 "-i len fmt        specify input data and input data format\n"
8201 "-o len fmt [args] specify output data and output data fmt\n"
8202 "smpcmd arguments:\n"
8203 "-r len fmt [args] specify the SMP command to be sent\n"
8204 "-R len fmt [args] specify SMP response format\n"
8205 "smprg arguments:\n"
8206 "-l                specify the long response format\n"
8207 "smppc arguments:\n"
8208 "-p phy            specify the PHY to operate on\n"
8209 "-l                specify the long request/response format\n"
8210 "-o operation      specify the phy control operation\n"
8211 "-d name           set the attached device name\n"
8212 "-m rate           set the minimum physical link rate\n"
8213 "-M rate           set the maximum physical link rate\n"
8214 "-T pp_timeout     set the partial pathway timeout value\n"
8215 "-a enable|disable enable or disable SATA slumber\n"
8216 "-A enable|disable enable or disable SATA partial phy power\n"
8217 "-s enable|disable enable or disable SAS slumber\n"
8218 "-S enable|disable enable or disable SAS partial phy power\n"
8219 "smpphylist arguments:\n"
8220 "-l                specify the long response format\n"
8221 "-q                only print phys with attached devices\n"
8222 "smpmaninfo arguments:\n"
8223 "-l                specify the long response format\n"
8224 "debug arguments:\n"
8225 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
8226 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
8227 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
8228 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
8229 "tags arguments:\n"
8230 "-N tags           specify the number of tags to use for this device\n"
8231 "-q                be quiet, don't report the number of tags\n"
8232 "-v                report a number of tag-related parameters\n"
8233 "negotiate arguments:\n"
8234 "-a                send a test unit ready after negotiation\n"
8235 "-c                report/set current negotiation settings\n"
8236 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
8237 "-M mode           set ATA mode\n"
8238 "-O offset         set command delay offset\n"
8239 "-q                be quiet, don't report anything\n"
8240 "-R syncrate       synchronization rate in MHz\n"
8241 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
8242 "-U                report/set user negotiation settings\n"
8243 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
8244 "-v                also print a Path Inquiry CCB for the controller\n"
8245 "format arguments:\n"
8246 "-q                be quiet, don't print status messages\n"
8247 "-r                run in report only mode\n"
8248 "-w                don't send immediate format command\n"
8249 "-y                don't ask any questions\n"
8250 "sanitize arguments:\n"
8251 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
8252 "-c passes         overwrite passes to perform (1 to 31)\n"
8253 "-I                invert overwrite pattern after each pass\n"
8254 "-P pattern        path to overwrite pattern file\n"
8255 "-q                be quiet, don't print status messages\n"
8256 "-r                run in report only mode\n"
8257 "-U                run operation in unrestricted completion exit mode\n"
8258 "-w                don't send immediate sanitize command\n"
8259 "-y                don't ask any questions\n"
8260 "idle/standby arguments:\n"
8261 "-t <arg>          number of seconds before respective state.\n"
8262 "fwdownload arguments:\n"
8263 "-f fw_image       path to firmware image file\n"
8264 "-y                don't ask any questions\n"
8265 "-s                run in simulation mode\n"
8266 "-v                print info for every firmware segment sent to device\n"
8267 "security arguments:\n"
8268 "-d pwd            disable security using the given password for the selected\n"
8269 "                  user\n"
8270 "-e pwd            erase the device using the given pwd for the selected user\n"
8271 "-f                freeze the security configuration of the specified device\n"
8272 "-h pwd            enhanced erase the device using the given pwd for the\n"
8273 "                  selected user\n"
8274 "-k pwd            unlock the device using the given pwd for the selected\n"
8275 "                  user\n"
8276 "-l <high|maximum> specifies which security level to set: high or maximum\n"
8277 "-q                be quiet, do not print any status messages\n"
8278 "-s pwd            password the device (enable security) using the given\n"
8279 "                  pwd for the selected user\n"
8280 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
8281 "-U <user|master>  specifies which user to set: user or master\n"
8282 "-y                don't ask any questions\n"
8283 "hpa arguments:\n"
8284 "-f                freeze the HPA configuration of the device\n"
8285 "-l                lock the HPA configuration of the device\n"
8286 "-P                make the HPA max sectors persist\n"
8287 "-p pwd            Set the HPA configuration password required for unlock\n"
8288 "                  calls\n"
8289 "-q                be quiet, do not print any status messages\n"
8290 "-s sectors        configures the maximum user accessible sectors of the\n"
8291 "                  device\n"
8292 "-U pwd            unlock the HPA configuration of the device\n"
8293 "-y                don't ask any questions\n"
8294 "persist arguments:\n"
8295 "-i action         specify read_keys, read_reservation, report_cap, or\n"
8296 "                  read_full_status\n"
8297 "-o action         specify register, register_ignore, reserve, release,\n"
8298 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
8299 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
8300 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8301 "-k key            specify the Reservation Key\n"
8302 "-K sa_key         specify the Service Action Reservation Key\n"
8303 "-p                set the Activate Persist Through Power Loss bit\n"
8304 "-R rtp            specify the Relative Target Port\n"
8305 "-s scope          specify the scope: lun, extent, element or a number\n"
8306 "-S                specify Transport ID for register, requires -I\n"
8307 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8308 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8309 "-U                unregister the current initiator for register_move\n"
8310 );
8311 #endif /* MINIMALISTIC */
8312 }
8313 
8314 int
8315 main(int argc, char **argv)
8316 {
8317 	int c;
8318 	char *device = NULL;
8319 	int unit = 0;
8320 	struct cam_device *cam_dev = NULL;
8321 	int timeout = 0, retry_count = 1;
8322 	camcontrol_optret optreturn;
8323 	char *tstr;
8324 	const char *mainopt = "C:En:t:u:v";
8325 	const char *subopt = NULL;
8326 	char combinedopt[256];
8327 	int error = 0, optstart = 2;
8328 	int devopen = 1;
8329 #ifndef MINIMALISTIC
8330 	path_id_t bus;
8331 	target_id_t target;
8332 	lun_id_t lun;
8333 #endif /* MINIMALISTIC */
8334 
8335 	cmdlist = CAM_CMD_NONE;
8336 	arglist = CAM_ARG_NONE;
8337 
8338 	if (argc < 2) {
8339 		usage(0);
8340 		exit(1);
8341 	}
8342 
8343 	/*
8344 	 * Get the base option.
8345 	 */
8346 	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8347 
8348 	if (optreturn == CC_OR_AMBIGUOUS) {
8349 		warnx("ambiguous option %s", argv[1]);
8350 		usage(0);
8351 		exit(1);
8352 	} else if (optreturn == CC_OR_NOT_FOUND) {
8353 		warnx("option %s not found", argv[1]);
8354 		usage(0);
8355 		exit(1);
8356 	}
8357 
8358 	/*
8359 	 * Ahh, getopt(3) is a pain.
8360 	 *
8361 	 * This is a gross hack.  There really aren't many other good
8362 	 * options (excuse the pun) for parsing options in a situation like
8363 	 * this.  getopt is kinda braindead, so you end up having to run
8364 	 * through the options twice, and give each invocation of getopt
8365 	 * the option string for the other invocation.
8366 	 *
8367 	 * You would think that you could just have two groups of options.
8368 	 * The first group would get parsed by the first invocation of
8369 	 * getopt, and the second group would get parsed by the second
8370 	 * invocation of getopt.  It doesn't quite work out that way.  When
8371 	 * the first invocation of getopt finishes, it leaves optind pointing
8372 	 * to the argument _after_ the first argument in the second group.
8373 	 * So when the second invocation of getopt comes around, it doesn't
8374 	 * recognize the first argument it gets and then bails out.
8375 	 *
8376 	 * A nice alternative would be to have a flag for getopt that says
8377 	 * "just keep parsing arguments even when you encounter an unknown
8378 	 * argument", but there isn't one.  So there's no real clean way to
8379 	 * easily parse two sets of arguments without having one invocation
8380 	 * of getopt know about the other.
8381 	 *
8382 	 * Without this hack, the first invocation of getopt would work as
8383 	 * long as the generic arguments are first, but the second invocation
8384 	 * (in the subfunction) would fail in one of two ways.  In the case
8385 	 * where you don't set optreset, it would fail because optind may be
8386 	 * pointing to the argument after the one it should be pointing at.
8387 	 * In the case where you do set optreset, and reset optind, it would
8388 	 * fail because getopt would run into the first set of options, which
8389 	 * it doesn't understand.
8390 	 *
8391 	 * All of this would "sort of" work if you could somehow figure out
8392 	 * whether optind had been incremented one option too far.  The
8393 	 * mechanics of that, however, are more daunting than just giving
8394 	 * both invocations all of the expect options for either invocation.
8395 	 *
8396 	 * Needless to say, I wouldn't mind if someone invented a better
8397 	 * (non-GPL!) command line parsing interface than getopt.  I
8398 	 * wouldn't mind if someone added more knobs to getopt to make it
8399 	 * work better.  Who knows, I may talk myself into doing it someday,
8400 	 * if the standards weenies let me.  As it is, it just leads to
8401 	 * hackery like this and causes people to avoid it in some cases.
8402 	 *
8403 	 * KDM, September 8th, 1998
8404 	 */
8405 	if (subopt != NULL)
8406 		sprintf(combinedopt, "%s%s", mainopt, subopt);
8407 	else
8408 		sprintf(combinedopt, "%s", mainopt);
8409 
8410 	/*
8411 	 * For these options we do not parse optional device arguments and
8412 	 * we do not open a passthrough device.
8413 	 */
8414 	if ((cmdlist == CAM_CMD_RESCAN)
8415 	 || (cmdlist == CAM_CMD_RESET)
8416 	 || (cmdlist == CAM_CMD_DEVTREE)
8417 	 || (cmdlist == CAM_CMD_USAGE)
8418 	 || (cmdlist == CAM_CMD_DEBUG))
8419 		devopen = 0;
8420 
8421 #ifndef MINIMALISTIC
8422 	if ((devopen == 1)
8423 	 && (argc > 2 && argv[2][0] != '-')) {
8424 		char name[30];
8425 		int rv;
8426 
8427 		if (isdigit(argv[2][0])) {
8428 			/* device specified as bus:target[:lun] */
8429 			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
8430 			if (rv < 2)
8431 				errx(1, "numeric device specification must "
8432 				     "be either bus:target, or "
8433 				     "bus:target:lun");
8434 			/* default to 0 if lun was not specified */
8435 			if ((arglist & CAM_ARG_LUN) == 0) {
8436 				lun = 0;
8437 				arglist |= CAM_ARG_LUN;
8438 			}
8439 			optstart++;
8440 		} else {
8441 			if (cam_get_device(argv[2], name, sizeof name, &unit)
8442 			    == -1)
8443 				errx(1, "%s", cam_errbuf);
8444 			device = strdup(name);
8445 			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
8446 			optstart++;
8447 		}
8448 	}
8449 #endif /* MINIMALISTIC */
8450 	/*
8451 	 * Start getopt processing at argv[2/3], since we've already
8452 	 * accepted argv[1..2] as the command name, and as a possible
8453 	 * device name.
8454 	 */
8455 	optind = optstart;
8456 
8457 	/*
8458 	 * Now we run through the argument list looking for generic
8459 	 * options, and ignoring options that possibly belong to
8460 	 * subfunctions.
8461 	 */
8462 	while ((c = getopt(argc, argv, combinedopt))!= -1){
8463 		switch(c) {
8464 			case 'C':
8465 				retry_count = strtol(optarg, NULL, 0);
8466 				if (retry_count < 0)
8467 					errx(1, "retry count %d is < 0",
8468 					     retry_count);
8469 				arglist |= CAM_ARG_RETRIES;
8470 				break;
8471 			case 'E':
8472 				arglist |= CAM_ARG_ERR_RECOVER;
8473 				break;
8474 			case 'n':
8475 				arglist |= CAM_ARG_DEVICE;
8476 				tstr = optarg;
8477 				while (isspace(*tstr) && (*tstr != '\0'))
8478 					tstr++;
8479 				device = (char *)strdup(tstr);
8480 				break;
8481 			case 't':
8482 				timeout = strtol(optarg, NULL, 0);
8483 				if (timeout < 0)
8484 					errx(1, "invalid timeout %d", timeout);
8485 				/* Convert the timeout from seconds to ms */
8486 				timeout *= 1000;
8487 				arglist |= CAM_ARG_TIMEOUT;
8488 				break;
8489 			case 'u':
8490 				arglist |= CAM_ARG_UNIT;
8491 				unit = strtol(optarg, NULL, 0);
8492 				break;
8493 			case 'v':
8494 				arglist |= CAM_ARG_VERBOSE;
8495 				break;
8496 			default:
8497 				break;
8498 		}
8499 	}
8500 
8501 #ifndef MINIMALISTIC
8502 	/*
8503 	 * For most commands we'll want to open the passthrough device
8504 	 * associated with the specified device.  In the case of the rescan
8505 	 * commands, we don't use a passthrough device at all, just the
8506 	 * transport layer device.
8507 	 */
8508 	if (devopen == 1) {
8509 		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
8510 		 && (((arglist & CAM_ARG_DEVICE) == 0)
8511 		  || ((arglist & CAM_ARG_UNIT) == 0))) {
8512 			errx(1, "subcommand \"%s\" requires a valid device "
8513 			     "identifier", argv[1]);
8514 		}
8515 
8516 		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
8517 				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
8518 				cam_open_spec_device(device,unit,O_RDWR,NULL)))
8519 		     == NULL)
8520 			errx(1,"%s", cam_errbuf);
8521 	}
8522 #endif /* MINIMALISTIC */
8523 
8524 	/*
8525 	 * Reset optind to 2, and reset getopt, so these routines can parse
8526 	 * the arguments again.
8527 	 */
8528 	optind = optstart;
8529 	optreset = 1;
8530 
8531 	switch(cmdlist) {
8532 #ifndef MINIMALISTIC
8533 		case CAM_CMD_DEVLIST:
8534 			error = getdevlist(cam_dev);
8535 			break;
8536 		case CAM_CMD_HPA:
8537 			error = atahpa(cam_dev, retry_count, timeout,
8538 				       argc, argv, combinedopt);
8539 			break;
8540 #endif /* MINIMALISTIC */
8541 		case CAM_CMD_DEVTREE:
8542 			error = getdevtree(argc, argv, combinedopt);
8543 			break;
8544 #ifndef MINIMALISTIC
8545 		case CAM_CMD_TUR:
8546 			error = testunitready(cam_dev, retry_count, timeout, 0);
8547 			break;
8548 		case CAM_CMD_INQUIRY:
8549 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
8550 					      retry_count, timeout);
8551 			break;
8552 		case CAM_CMD_IDENTIFY:
8553 			error = ataidentify(cam_dev, retry_count, timeout);
8554 			break;
8555 		case CAM_CMD_STARTSTOP:
8556 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
8557 					  arglist & CAM_ARG_EJECT, retry_count,
8558 					  timeout);
8559 			break;
8560 #endif /* MINIMALISTIC */
8561 		case CAM_CMD_RESCAN:
8562 			error = dorescan_or_reset(argc, argv, 1);
8563 			break;
8564 		case CAM_CMD_RESET:
8565 			error = dorescan_or_reset(argc, argv, 0);
8566 			break;
8567 #ifndef MINIMALISTIC
8568 		case CAM_CMD_READ_DEFECTS:
8569 			error = readdefects(cam_dev, argc, argv, combinedopt,
8570 					    retry_count, timeout);
8571 			break;
8572 		case CAM_CMD_MODE_PAGE:
8573 			modepage(cam_dev, argc, argv, combinedopt,
8574 				 retry_count, timeout);
8575 			break;
8576 		case CAM_CMD_SCSI_CMD:
8577 			error = scsicmd(cam_dev, argc, argv, combinedopt,
8578 					retry_count, timeout);
8579 			break;
8580 		case CAM_CMD_SMP_CMD:
8581 			error = smpcmd(cam_dev, argc, argv, combinedopt,
8582 				       retry_count, timeout);
8583 			break;
8584 		case CAM_CMD_SMP_RG:
8585 			error = smpreportgeneral(cam_dev, argc, argv,
8586 						 combinedopt, retry_count,
8587 						 timeout);
8588 			break;
8589 		case CAM_CMD_SMP_PC:
8590 			error = smpphycontrol(cam_dev, argc, argv, combinedopt,
8591 					      retry_count, timeout);
8592 			break;
8593 		case CAM_CMD_SMP_PHYLIST:
8594 			error = smpphylist(cam_dev, argc, argv, combinedopt,
8595 					   retry_count, timeout);
8596 			break;
8597 		case CAM_CMD_SMP_MANINFO:
8598 			error = smpmaninfo(cam_dev, argc, argv, combinedopt,
8599 					   retry_count, timeout);
8600 			break;
8601 		case CAM_CMD_DEBUG:
8602 			error = camdebug(argc, argv, combinedopt);
8603 			break;
8604 		case CAM_CMD_TAG:
8605 			error = tagcontrol(cam_dev, argc, argv, combinedopt);
8606 			break;
8607 		case CAM_CMD_RATE:
8608 			error = ratecontrol(cam_dev, retry_count, timeout,
8609 					    argc, argv, combinedopt);
8610 			break;
8611 		case CAM_CMD_FORMAT:
8612 			error = scsiformat(cam_dev, argc, argv,
8613 					   combinedopt, retry_count, timeout);
8614 			break;
8615 		case CAM_CMD_REPORTLUNS:
8616 			error = scsireportluns(cam_dev, argc, argv,
8617 					       combinedopt, retry_count,
8618 					       timeout);
8619 			break;
8620 		case CAM_CMD_READCAP:
8621 			error = scsireadcapacity(cam_dev, argc, argv,
8622 						 combinedopt, retry_count,
8623 						 timeout);
8624 			break;
8625 		case CAM_CMD_IDLE:
8626 		case CAM_CMD_STANDBY:
8627 		case CAM_CMD_SLEEP:
8628 			error = atapm(cam_dev, argc, argv,
8629 				      combinedopt, retry_count, timeout);
8630 			break;
8631 		case CAM_CMD_APM:
8632 		case CAM_CMD_AAM:
8633 			error = ataaxm(cam_dev, argc, argv,
8634 				      combinedopt, retry_count, timeout);
8635 			break;
8636 		case CAM_CMD_SECURITY:
8637 			error = atasecurity(cam_dev, retry_count, timeout,
8638 					    argc, argv, combinedopt);
8639 			break;
8640 		case CAM_CMD_DOWNLOAD_FW:
8641 			error = fwdownload(cam_dev, argc, argv, combinedopt,
8642 			    arglist & CAM_ARG_VERBOSE, retry_count, timeout,
8643 			    get_disk_type(cam_dev));
8644 			break;
8645 		case CAM_CMD_SANITIZE:
8646 			error = scsisanitize(cam_dev, argc, argv,
8647 					     combinedopt, retry_count, timeout);
8648 			break;
8649 		case CAM_CMD_PERSIST:
8650 			error = scsipersist(cam_dev, argc, argv, combinedopt,
8651 			    retry_count, timeout, arglist & CAM_ARG_VERBOSE,
8652 			    arglist & CAM_ARG_ERR_RECOVER);
8653 			break;
8654 #endif /* MINIMALISTIC */
8655 		case CAM_CMD_USAGE:
8656 			usage(1);
8657 			break;
8658 		default:
8659 			usage(0);
8660 			error = 1;
8661 			break;
8662 	}
8663 
8664 	if (cam_dev != NULL)
8665 		cam_close_device(cam_dev);
8666 
8667 	exit(error);
8668 }
8669