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