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