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