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