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