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