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