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