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