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