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