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