xref: /freebsd/sbin/camcontrol/camcontrol.c (revision 3fc36ee018bb836bd1796067cf4ef8683f166ebc)
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, matchccb;
3131 	int fd, 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 	if (bus != CAM_BUS_WILDCARD) {
3143 		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3144 		ccb.ccb_h.path_id = bus;
3145 		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3146 		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3147 		ccb.crcn.flags = CAM_FLAG_NONE;
3148 
3149 		/* run this at a low priority */
3150 		ccb.ccb_h.pinfo.priority = 5;
3151 
3152 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3153 			warn("CAMIOCOMMAND ioctl failed");
3154 			close(fd);
3155 			return(1);
3156 		}
3157 
3158 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3159 			fprintf(stdout, "%s of bus %d was successful\n",
3160 			    rescan ? "Re-scan" : "Reset", bus);
3161 		} else {
3162 			fprintf(stdout, "%s of bus %d returned error %#x\n",
3163 				rescan ? "Re-scan" : "Reset", bus,
3164 				ccb.ccb_h.status & CAM_STATUS_MASK);
3165 			retval = 1;
3166 		}
3167 
3168 		close(fd);
3169 		return(retval);
3170 
3171 	}
3172 
3173 
3174 	/*
3175 	 * The right way to handle this is to modify the xpt so that it can
3176 	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
3177 	 * that isn't implemented, so instead we enumerate the busses and
3178 	 * send the rescan or reset to those busses in the case where the
3179 	 * given bus is -1 (wildcard).  We don't send a rescan or reset
3180 	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
3181 	 * no-op, sending a rescan to the xpt bus would result in a status of
3182 	 * CAM_REQ_INVALID.
3183 	 */
3184 	CCB_CLEAR_ALL_EXCEPT_HDR(&matchccb.cdm);
3185 	matchccb.ccb_h.func_code = XPT_DEV_MATCH;
3186 	matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
3187 	bufsize = sizeof(struct dev_match_result) * 20;
3188 	matchccb.cdm.match_buf_len = bufsize;
3189 	matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
3190 	if (matchccb.cdm.matches == NULL) {
3191 		warnx("can't malloc memory for matches");
3192 		retval = 1;
3193 		goto bailout;
3194 	}
3195 	matchccb.cdm.num_matches = 0;
3196 
3197 	matchccb.cdm.num_patterns = 1;
3198 	matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3199 
3200 	matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
3201 		matchccb.cdm.pattern_buf_len);
3202 	if (matchccb.cdm.patterns == NULL) {
3203 		warnx("can't malloc memory for patterns");
3204 		retval = 1;
3205 		goto bailout;
3206 	}
3207 	matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
3208 	matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3209 
3210 	do {
3211 		unsigned int i;
3212 
3213 		if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
3214 			warn("CAMIOCOMMAND ioctl failed");
3215 			retval = 1;
3216 			goto bailout;
3217 		}
3218 
3219 		if ((matchccb.ccb_h.status != CAM_REQ_CMP)
3220 		 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
3221 		   && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
3222 			warnx("got CAM error %#x, CDM error %d\n",
3223 			      matchccb.ccb_h.status, matchccb.cdm.status);
3224 			retval = 1;
3225 			goto bailout;
3226 		}
3227 
3228 		for (i = 0; i < matchccb.cdm.num_matches; i++) {
3229 			struct bus_match_result *bus_result;
3230 
3231 			/* This shouldn't happen. */
3232 			if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
3233 				continue;
3234 
3235 			bus_result = &matchccb.cdm.matches[i].result.bus_result;
3236 
3237 			/*
3238 			 * We don't want to rescan or reset the xpt bus.
3239 			 * See above.
3240 			 */
3241 			if (bus_result->path_id == CAM_XPT_PATH_ID)
3242 				continue;
3243 
3244 			ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3245 						       XPT_RESET_BUS;
3246 			ccb.ccb_h.path_id = bus_result->path_id;
3247 			ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3248 			ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3249 			ccb.crcn.flags = CAM_FLAG_NONE;
3250 
3251 			/* run this at a low priority */
3252 			ccb.ccb_h.pinfo.priority = 5;
3253 
3254 			if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3255 				warn("CAMIOCOMMAND ioctl failed");
3256 				retval = 1;
3257 				goto bailout;
3258 			}
3259 
3260 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
3261 				fprintf(stdout, "%s of bus %d was successful\n",
3262 					rescan? "Re-scan" : "Reset",
3263 					bus_result->path_id);
3264 			} else {
3265 				/*
3266 				 * Don't bail out just yet, maybe the other
3267 				 * rescan or reset commands will complete
3268 				 * successfully.
3269 				 */
3270 				fprintf(stderr, "%s of bus %d returned error "
3271 					"%#x\n", rescan? "Re-scan" : "Reset",
3272 					bus_result->path_id,
3273 					ccb.ccb_h.status & CAM_STATUS_MASK);
3274 				retval = 1;
3275 			}
3276 		}
3277 	} while ((matchccb.ccb_h.status == CAM_REQ_CMP)
3278 		 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
3279 
3280 bailout:
3281 
3282 	if (fd != -1)
3283 		close(fd);
3284 
3285 	if (matchccb.cdm.patterns != NULL)
3286 		free(matchccb.cdm.patterns);
3287 	if (matchccb.cdm.matches != NULL)
3288 		free(matchccb.cdm.matches);
3289 
3290 	return(retval);
3291 }
3292 
3293 static int
3294 scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3295 {
3296 	union ccb ccb;
3297 	struct cam_device *device;
3298 	int fd;
3299 
3300 	device = NULL;
3301 
3302 	if (bus == CAM_BUS_WILDCARD) {
3303 		warnx("invalid bus number %d", bus);
3304 		return(1);
3305 	}
3306 
3307 	if (target == CAM_TARGET_WILDCARD) {
3308 		warnx("invalid target number %d", target);
3309 		return(1);
3310 	}
3311 
3312 	if (lun == CAM_LUN_WILDCARD) {
3313 		warnx("invalid lun number %jx", (uintmax_t)lun);
3314 		return(1);
3315 	}
3316 
3317 	fd = -1;
3318 
3319 	bzero(&ccb, sizeof(union ccb));
3320 
3321 	if (scan) {
3322 		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3323 			warnx("error opening transport layer device %s\n",
3324 			    XPT_DEVICE);
3325 			warn("%s", XPT_DEVICE);
3326 			return(1);
3327 		}
3328 	} else {
3329 		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3330 		if (device == NULL) {
3331 			warnx("%s", cam_errbuf);
3332 			return(1);
3333 		}
3334 	}
3335 
3336 	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3337 	ccb.ccb_h.path_id = bus;
3338 	ccb.ccb_h.target_id = target;
3339 	ccb.ccb_h.target_lun = lun;
3340 	ccb.ccb_h.timeout = 5000;
3341 	ccb.crcn.flags = CAM_FLAG_NONE;
3342 
3343 	/* run this at a low priority */
3344 	ccb.ccb_h.pinfo.priority = 5;
3345 
3346 	if (scan) {
3347 		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3348 			warn("CAMIOCOMMAND ioctl failed");
3349 			close(fd);
3350 			return(1);
3351 		}
3352 	} else {
3353 		if (cam_send_ccb(device, &ccb) < 0) {
3354 			warn("error sending XPT_RESET_DEV CCB");
3355 			cam_close_device(device);
3356 			return(1);
3357 		}
3358 	}
3359 
3360 	if (scan)
3361 		close(fd);
3362 	else
3363 		cam_close_device(device);
3364 
3365 	/*
3366 	 * An error code of CAM_BDR_SENT is normal for a BDR request.
3367 	 */
3368 	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3369 	 || ((!scan)
3370 	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3371 		fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3372 		    scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3373 		return(0);
3374 	} else {
3375 		fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3376 		    scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3377 		    ccb.ccb_h.status & CAM_STATUS_MASK);
3378 		return(1);
3379 	}
3380 }
3381 
3382 #ifndef MINIMALISTIC
3383 
3384 static struct scsi_nv defect_list_type_map[] = {
3385 	{ "block", SRDD10_BLOCK_FORMAT },
3386 	{ "extbfi", SRDD10_EXT_BFI_FORMAT },
3387 	{ "extphys", SRDD10_EXT_PHYS_FORMAT },
3388 	{ "longblock", SRDD10_LONG_BLOCK_FORMAT },
3389 	{ "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3390 	{ "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3391 };
3392 
3393 static int
3394 readdefects(struct cam_device *device, int argc, char **argv,
3395 	    char *combinedopt, int retry_count, int timeout)
3396 {
3397 	union ccb *ccb = NULL;
3398 	struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3399 	struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3400 	size_t hdr_size = 0, entry_size = 0;
3401 	int use_12byte = 0;
3402 	int hex_format = 0;
3403 	u_int8_t *defect_list = NULL;
3404 	u_int8_t list_format = 0;
3405 	int list_type_set = 0;
3406 	u_int32_t dlist_length = 0;
3407 	u_int32_t returned_length = 0, valid_len = 0;
3408 	u_int32_t num_returned = 0, num_valid = 0;
3409 	u_int32_t max_possible_size = 0, hdr_max = 0;
3410 	u_int32_t starting_offset = 0;
3411 	u_int8_t returned_format, returned_type;
3412 	unsigned int i;
3413 	int summary = 0, quiet = 0;
3414 	int c, error = 0;
3415 	int lists_specified = 0;
3416 	int get_length = 1, first_pass = 1;
3417 	int mads = 0;
3418 
3419 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3420 		switch(c){
3421 		case 'f':
3422 		{
3423 			scsi_nv_status status;
3424 			int entry_num = 0;
3425 
3426 			status = scsi_get_nv(defect_list_type_map,
3427 			    sizeof(defect_list_type_map) /
3428 			    sizeof(defect_list_type_map[0]), optarg,
3429 			    &entry_num, SCSI_NV_FLAG_IG_CASE);
3430 
3431 			if (status == SCSI_NV_FOUND) {
3432 				list_format = defect_list_type_map[
3433 				    entry_num].value;
3434 				list_type_set = 1;
3435 			} else {
3436 				warnx("%s: %s %s option %s", __func__,
3437 				    (status == SCSI_NV_AMBIGUOUS) ?
3438 				    "ambiguous" : "invalid", "defect list type",
3439 				    optarg);
3440 				error = 1;
3441 				goto defect_bailout;
3442 			}
3443 			break;
3444 		}
3445 		case 'G':
3446 			arglist |= CAM_ARG_GLIST;
3447 			break;
3448 		case 'P':
3449 			arglist |= CAM_ARG_PLIST;
3450 			break;
3451 		case 'q':
3452 			quiet = 1;
3453 			break;
3454 		case 's':
3455 			summary = 1;
3456 			break;
3457 		case 'S': {
3458 			char *endptr;
3459 
3460 			starting_offset = strtoul(optarg, &endptr, 0);
3461 			if (*endptr != '\0') {
3462 				error = 1;
3463 				warnx("invalid starting offset %s", optarg);
3464 				goto defect_bailout;
3465 			}
3466 			break;
3467 		}
3468 		case 'X':
3469 			hex_format = 1;
3470 			break;
3471 		default:
3472 			break;
3473 		}
3474 	}
3475 
3476 	if (list_type_set == 0) {
3477 		error = 1;
3478 		warnx("no defect list format specified");
3479 		goto defect_bailout;
3480 	}
3481 
3482 	if (arglist & CAM_ARG_PLIST) {
3483 		list_format |= SRDD10_PLIST;
3484 		lists_specified++;
3485 	}
3486 
3487 	if (arglist & CAM_ARG_GLIST) {
3488 		list_format |= SRDD10_GLIST;
3489 		lists_specified++;
3490 	}
3491 
3492 	/*
3493 	 * This implies a summary, and was the previous behavior.
3494 	 */
3495 	if (lists_specified == 0)
3496 		summary = 1;
3497 
3498 	ccb = cam_getccb(device);
3499 
3500 retry_12byte:
3501 
3502 	/*
3503 	 * We start off asking for just the header to determine how much
3504 	 * defect data is available.  Some Hitachi drives return an error
3505 	 * if you ask for more data than the drive has.  Once we know the
3506 	 * length, we retry the command with the returned length.
3507 	 */
3508 	if (use_12byte == 0)
3509 		dlist_length = sizeof(*hdr10);
3510 	else
3511 		dlist_length = sizeof(*hdr12);
3512 
3513 retry:
3514 	if (defect_list != NULL) {
3515 		free(defect_list);
3516 		defect_list = NULL;
3517 	}
3518 	defect_list = malloc(dlist_length);
3519 	if (defect_list == NULL) {
3520 		warnx("can't malloc memory for defect list");
3521 		error = 1;
3522 		goto defect_bailout;
3523 	}
3524 
3525 next_batch:
3526 	bzero(defect_list, dlist_length);
3527 
3528 	/*
3529 	 * cam_getccb() zeros the CCB header only.  So we need to zero the
3530 	 * payload portion of the ccb.
3531 	 */
3532 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
3533 
3534 	scsi_read_defects(&ccb->csio,
3535 			  /*retries*/ retry_count,
3536 			  /*cbfcnp*/ NULL,
3537 			  /*tag_action*/ MSG_SIMPLE_Q_TAG,
3538 			  /*list_format*/ list_format,
3539 			  /*addr_desc_index*/ starting_offset,
3540 			  /*data_ptr*/ defect_list,
3541 			  /*dxfer_len*/ dlist_length,
3542 			  /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3543 			  /*sense_len*/ SSD_FULL_SIZE,
3544 			  /*timeout*/ timeout ? timeout : 5000);
3545 
3546 	/* Disable freezing the device queue */
3547 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3548 
3549 	if (cam_send_ccb(device, ccb) < 0) {
3550 		perror("error reading defect list");
3551 
3552 		if (arglist & CAM_ARG_VERBOSE) {
3553 			cam_error_print(device, ccb, CAM_ESF_ALL,
3554 					CAM_EPF_ALL, stderr);
3555 		}
3556 
3557 		error = 1;
3558 		goto defect_bailout;
3559 	}
3560 
3561 	valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3562 
3563 	if (use_12byte == 0) {
3564 		hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3565 		hdr_size = sizeof(*hdr10);
3566 		hdr_max = SRDDH10_MAX_LENGTH;
3567 
3568 		if (valid_len >= hdr_size) {
3569 			returned_length = scsi_2btoul(hdr10->length);
3570 			returned_format = hdr10->format;
3571 		} else {
3572 			returned_length = 0;
3573 			returned_format = 0;
3574 		}
3575 	} else {
3576 		hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3577 		hdr_size = sizeof(*hdr12);
3578 		hdr_max = SRDDH12_MAX_LENGTH;
3579 
3580 		if (valid_len >= hdr_size) {
3581 			returned_length = scsi_4btoul(hdr12->length);
3582 			returned_format = hdr12->format;
3583 		} else {
3584 			returned_length = 0;
3585 			returned_format = 0;
3586 		}
3587 	}
3588 
3589 	returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3590 	switch (returned_type) {
3591 	case SRDD10_BLOCK_FORMAT:
3592 		entry_size = sizeof(struct scsi_defect_desc_block);
3593 		break;
3594 	case SRDD10_LONG_BLOCK_FORMAT:
3595 		entry_size = sizeof(struct scsi_defect_desc_long_block);
3596 		break;
3597 	case SRDD10_EXT_PHYS_FORMAT:
3598 	case SRDD10_PHYSICAL_SECTOR_FORMAT:
3599 		entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3600 		break;
3601 	case SRDD10_EXT_BFI_FORMAT:
3602 	case SRDD10_BYTES_FROM_INDEX_FORMAT:
3603 		entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3604 		break;
3605 	default:
3606 		warnx("Unknown defect format 0x%x\n", returned_type);
3607 		error = 1;
3608 		goto defect_bailout;
3609 		break;
3610 	}
3611 
3612 	max_possible_size = (hdr_max / entry_size) * entry_size;
3613 	num_returned = returned_length / entry_size;
3614 	num_valid = min(returned_length, valid_len - hdr_size);
3615 	num_valid /= entry_size;
3616 
3617 	if (get_length != 0) {
3618 		get_length = 0;
3619 
3620 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3621 		     CAM_SCSI_STATUS_ERROR) {
3622 			struct scsi_sense_data *sense;
3623 			int error_code, sense_key, asc, ascq;
3624 
3625 			sense = &ccb->csio.sense_data;
3626 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
3627 			    ccb->csio.sense_resid, &error_code, &sense_key,
3628 			    &asc, &ascq, /*show_errors*/ 1);
3629 
3630 			/*
3631 			 * If the drive is reporting that it just doesn't
3632 			 * support the defect list format, go ahead and use
3633 			 * the length it reported.  Otherwise, the length
3634 			 * may not be valid, so use the maximum.
3635 			 */
3636 			if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3637 			 && (asc == 0x1c) && (ascq == 0x00)
3638 			 && (returned_length > 0)) {
3639 				if ((use_12byte == 0)
3640 				 && (returned_length >= max_possible_size)) {
3641 					get_length = 1;
3642 					use_12byte = 1;
3643 					goto retry_12byte;
3644 				}
3645 				dlist_length = returned_length + hdr_size;
3646 			} else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3647 				&& (asc == 0x1f) && (ascq == 0x00)
3648 				&& (returned_length > 0)) {
3649 				/* Partial defect list transfer */
3650 				/*
3651 				 * Hitachi drives return this error
3652 				 * along with a partial defect list if they
3653 				 * have more defects than the 10 byte
3654 				 * command can support.  Retry with the 12
3655 				 * byte command.
3656 				 */
3657 				if (use_12byte == 0) {
3658 					get_length = 1;
3659 					use_12byte = 1;
3660 					goto retry_12byte;
3661 				}
3662 				dlist_length = returned_length + hdr_size;
3663 			} else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3664 				&& (asc == 0x24) && (ascq == 0x00)) {
3665 				/* Invalid field in CDB */
3666 				/*
3667 				 * SBC-3 says that if the drive has more
3668 				 * defects than can be reported with the
3669 				 * 10 byte command, it should return this
3670 	 			 * error and no data.  Retry with the 12
3671 				 * byte command.
3672 				 */
3673 				if (use_12byte == 0) {
3674 					get_length = 1;
3675 					use_12byte = 1;
3676 					goto retry_12byte;
3677 				}
3678 				dlist_length = returned_length + hdr_size;
3679 			} else {
3680 				/*
3681 				 * If we got a SCSI error and no valid length,
3682 				 * just use the 10 byte maximum.  The 12
3683 				 * byte maximum is too large.
3684 				 */
3685 				if (returned_length == 0)
3686 					dlist_length = SRDD10_MAX_LENGTH;
3687 				else {
3688 					if ((use_12byte == 0)
3689 					 && (returned_length >=
3690 					     max_possible_size)) {
3691 						get_length = 1;
3692 						use_12byte = 1;
3693 						goto retry_12byte;
3694 					}
3695 					dlist_length = returned_length +
3696 					    hdr_size;
3697 				}
3698 			}
3699 		} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3700 			    CAM_REQ_CMP){
3701 			error = 1;
3702 			warnx("Error reading defect header");
3703 			if (arglist & CAM_ARG_VERBOSE)
3704 				cam_error_print(device, ccb, CAM_ESF_ALL,
3705 						CAM_EPF_ALL, stderr);
3706 			goto defect_bailout;
3707 		} else {
3708 			if ((use_12byte == 0)
3709 			 && (returned_length >= max_possible_size)) {
3710 				get_length = 1;
3711 				use_12byte = 1;
3712 				goto retry_12byte;
3713 			}
3714 			dlist_length = returned_length + hdr_size;
3715 		}
3716 		if (summary != 0) {
3717 			fprintf(stdout, "%u", num_returned);
3718 			if (quiet == 0) {
3719 				fprintf(stdout, " defect%s",
3720 					(num_returned != 1) ? "s" : "");
3721 			}
3722 			fprintf(stdout, "\n");
3723 
3724 			goto defect_bailout;
3725 		}
3726 
3727 		/*
3728 		 * We always limit the list length to the 10-byte maximum
3729 		 * length (0xffff).  The reason is that some controllers
3730 		 * can't handle larger I/Os, and we can transfer the entire
3731 		 * 10 byte list in one shot.  For drives that support the 12
3732 		 * byte read defects command, we'll step through the list
3733 		 * by specifying a starting offset.  For drives that don't
3734 		 * support the 12 byte command's starting offset, we'll
3735 		 * just display the first 64K.
3736 		 */
3737 		dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3738 
3739 		goto retry;
3740 	}
3741 
3742 
3743 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3744 	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3745 	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3746 		struct scsi_sense_data *sense;
3747 		int error_code, sense_key, asc, ascq;
3748 
3749 		sense = &ccb->csio.sense_data;
3750 		scsi_extract_sense_len(sense, ccb->csio.sense_len -
3751 		    ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3752 		    &ascq, /*show_errors*/ 1);
3753 
3754 		/*
3755 		 * According to the SCSI spec, if the disk doesn't support
3756 		 * the requested format, it will generally return a sense
3757 		 * key of RECOVERED ERROR, and an additional sense code
3758 		 * of "DEFECT LIST NOT FOUND".  HGST drives also return
3759 		 * Primary/Grown defect list not found errors.  So just
3760 		 * check for an ASC of 0x1c.
3761 		 */
3762 		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3763 		 && (asc == 0x1c)) {
3764 			const char *format_str;
3765 
3766 			format_str = scsi_nv_to_str(defect_list_type_map,
3767 			    sizeof(defect_list_type_map) /
3768 			    sizeof(defect_list_type_map[0]),
3769 			    list_format & SRDD10_DLIST_FORMAT_MASK);
3770 			warnx("requested defect format %s not available",
3771 			    format_str ? format_str : "unknown");
3772 
3773 			format_str = scsi_nv_to_str(defect_list_type_map,
3774 			    sizeof(defect_list_type_map) /
3775 			    sizeof(defect_list_type_map[0]), returned_type);
3776 			if (format_str != NULL) {
3777 				warnx("Device returned %s format",
3778 				    format_str);
3779 			} else {
3780 				error = 1;
3781 				warnx("Device returned unknown defect"
3782 				     " data format %#x", returned_type);
3783 				goto defect_bailout;
3784 			}
3785 		} else {
3786 			error = 1;
3787 			warnx("Error returned from read defect data command");
3788 			if (arglist & CAM_ARG_VERBOSE)
3789 				cam_error_print(device, ccb, CAM_ESF_ALL,
3790 						CAM_EPF_ALL, stderr);
3791 			goto defect_bailout;
3792 		}
3793 	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3794 		error = 1;
3795 		warnx("Error returned from read defect data command");
3796 		if (arglist & CAM_ARG_VERBOSE)
3797 			cam_error_print(device, ccb, CAM_ESF_ALL,
3798 					CAM_EPF_ALL, stderr);
3799 		goto defect_bailout;
3800 	}
3801 
3802 	if (first_pass != 0) {
3803 		fprintf(stderr, "Got %d defect", num_returned);
3804 
3805 		if ((lists_specified == 0) || (num_returned == 0)) {
3806 			fprintf(stderr, "s.\n");
3807 			goto defect_bailout;
3808 		} else if (num_returned == 1)
3809 			fprintf(stderr, ":\n");
3810 		else
3811 			fprintf(stderr, "s:\n");
3812 
3813 		first_pass = 0;
3814 	}
3815 
3816 	/*
3817 	 * XXX KDM  I should probably clean up the printout format for the
3818 	 * disk defects.
3819 	 */
3820 	switch (returned_type) {
3821 	case SRDD10_PHYSICAL_SECTOR_FORMAT:
3822 	case SRDD10_EXT_PHYS_FORMAT:
3823 	{
3824 		struct scsi_defect_desc_phys_sector *dlist;
3825 
3826 		dlist = (struct scsi_defect_desc_phys_sector *)
3827 			(defect_list + hdr_size);
3828 
3829 		for (i = 0; i < num_valid; i++) {
3830 			uint32_t sector;
3831 
3832 			sector = scsi_4btoul(dlist[i].sector);
3833 			if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
3834 				mads = (sector & SDD_EXT_PHYS_MADS) ?
3835 				       0 : 1;
3836 				sector &= ~SDD_EXT_PHYS_FLAG_MASK;
3837 			}
3838 			if (hex_format == 0)
3839 				fprintf(stdout, "%d:%d:%d%s",
3840 					scsi_3btoul(dlist[i].cylinder),
3841 					dlist[i].head,
3842 					scsi_4btoul(dlist[i].sector),
3843 					mads ? " - " : "\n");
3844 			else
3845 				fprintf(stdout, "0x%x:0x%x:0x%x%s",
3846 					scsi_3btoul(dlist[i].cylinder),
3847 					dlist[i].head,
3848 					scsi_4btoul(dlist[i].sector),
3849 					mads ? " - " : "\n");
3850 			mads = 0;
3851 		}
3852 		if (num_valid < num_returned) {
3853 			starting_offset += num_valid;
3854 			goto next_batch;
3855 		}
3856 		break;
3857 	}
3858 	case SRDD10_BYTES_FROM_INDEX_FORMAT:
3859 	case SRDD10_EXT_BFI_FORMAT:
3860 	{
3861 		struct scsi_defect_desc_bytes_from_index *dlist;
3862 
3863 		dlist = (struct scsi_defect_desc_bytes_from_index *)
3864 			(defect_list + hdr_size);
3865 
3866 		for (i = 0; i < num_valid; i++) {
3867 			uint32_t bfi;
3868 
3869 			bfi = scsi_4btoul(dlist[i].bytes_from_index);
3870 			if (returned_type == SRDD10_EXT_BFI_FORMAT) {
3871 				mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
3872 				bfi &= ~SDD_EXT_BFI_FLAG_MASK;
3873 			}
3874 			if (hex_format == 0)
3875 				fprintf(stdout, "%d:%d:%d%s",
3876 					scsi_3btoul(dlist[i].cylinder),
3877 					dlist[i].head,
3878 					scsi_4btoul(dlist[i].bytes_from_index),
3879 					mads ? " - " : "\n");
3880 			else
3881 				fprintf(stdout, "0x%x:0x%x:0x%x%s",
3882 					scsi_3btoul(dlist[i].cylinder),
3883 					dlist[i].head,
3884 					scsi_4btoul(dlist[i].bytes_from_index),
3885 					mads ? " - " : "\n");
3886 
3887 			mads = 0;
3888 		}
3889 		if (num_valid < num_returned) {
3890 			starting_offset += num_valid;
3891 			goto next_batch;
3892 		}
3893 		break;
3894 	}
3895 	case SRDDH10_BLOCK_FORMAT:
3896 	{
3897 		struct scsi_defect_desc_block *dlist;
3898 
3899 		dlist = (struct scsi_defect_desc_block *)
3900 			(defect_list + hdr_size);
3901 
3902 		for (i = 0; i < num_valid; i++) {
3903 			if (hex_format == 0)
3904 				fprintf(stdout, "%u\n",
3905 					scsi_4btoul(dlist[i].address));
3906 			else
3907 				fprintf(stdout, "0x%x\n",
3908 					scsi_4btoul(dlist[i].address));
3909 		}
3910 
3911 		if (num_valid < num_returned) {
3912 			starting_offset += num_valid;
3913 			goto next_batch;
3914 		}
3915 
3916 		break;
3917 	}
3918 	case SRDD10_LONG_BLOCK_FORMAT:
3919 	{
3920 		struct scsi_defect_desc_long_block *dlist;
3921 
3922 		dlist = (struct scsi_defect_desc_long_block *)
3923 			(defect_list + hdr_size);
3924 
3925 		for (i = 0; i < num_valid; i++) {
3926 			if (hex_format == 0)
3927 				fprintf(stdout, "%ju\n",
3928 					(uintmax_t)scsi_8btou64(
3929 					dlist[i].address));
3930 			else
3931 				fprintf(stdout, "0x%jx\n",
3932 					(uintmax_t)scsi_8btou64(
3933 					dlist[i].address));
3934 		}
3935 
3936 		if (num_valid < num_returned) {
3937 			starting_offset += num_valid;
3938 			goto next_batch;
3939 		}
3940 		break;
3941 	}
3942 	default:
3943 		fprintf(stderr, "Unknown defect format 0x%x\n",
3944 			returned_type);
3945 		error = 1;
3946 		break;
3947 	}
3948 defect_bailout:
3949 
3950 	if (defect_list != NULL)
3951 		free(defect_list);
3952 
3953 	if (ccb != NULL)
3954 		cam_freeccb(ccb);
3955 
3956 	return(error);
3957 }
3958 #endif /* MINIMALISTIC */
3959 
3960 #if 0
3961 void
3962 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3963 {
3964 	union ccb *ccb;
3965 
3966 	ccb = cam_getccb(device);
3967 
3968 	cam_freeccb(ccb);
3969 }
3970 #endif
3971 
3972 #ifndef MINIMALISTIC
3973 void
3974 mode_sense(struct cam_device *device, int mode_page, int page_control,
3975 	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3976 {
3977 	union ccb *ccb;
3978 	int retval;
3979 
3980 	ccb = cam_getccb(device);
3981 
3982 	if (ccb == NULL)
3983 		errx(1, "mode_sense: couldn't allocate CCB");
3984 
3985 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
3986 
3987 	scsi_mode_sense(&ccb->csio,
3988 			/* retries */ retry_count,
3989 			/* cbfcnp */ NULL,
3990 			/* tag_action */ MSG_SIMPLE_Q_TAG,
3991 			/* dbd */ dbd,
3992 			/* page_code */ page_control << 6,
3993 			/* page */ mode_page,
3994 			/* param_buf */ data,
3995 			/* param_len */ datalen,
3996 			/* sense_len */ SSD_FULL_SIZE,
3997 			/* timeout */ timeout ? timeout : 5000);
3998 
3999 	if (arglist & CAM_ARG_ERR_RECOVER)
4000 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4001 
4002 	/* Disable freezing the device queue */
4003 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4004 
4005 	if (((retval = cam_send_ccb(device, ccb)) < 0)
4006 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4007 		if (arglist & CAM_ARG_VERBOSE) {
4008 			cam_error_print(device, ccb, CAM_ESF_ALL,
4009 					CAM_EPF_ALL, stderr);
4010 		}
4011 		cam_freeccb(ccb);
4012 		cam_close_device(device);
4013 		if (retval < 0)
4014 			err(1, "error sending mode sense command");
4015 		else
4016 			errx(1, "error sending mode sense command");
4017 	}
4018 
4019 	cam_freeccb(ccb);
4020 }
4021 
4022 void
4023 mode_select(struct cam_device *device, int save_pages, int retry_count,
4024 	   int timeout, u_int8_t *data, int datalen)
4025 {
4026 	union ccb *ccb;
4027 	int retval;
4028 
4029 	ccb = cam_getccb(device);
4030 
4031 	if (ccb == NULL)
4032 		errx(1, "mode_select: couldn't allocate CCB");
4033 
4034 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
4035 
4036 	scsi_mode_select(&ccb->csio,
4037 			 /* retries */ retry_count,
4038 			 /* cbfcnp */ NULL,
4039 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
4040 			 /* scsi_page_fmt */ 1,
4041 			 /* save_pages */ save_pages,
4042 			 /* param_buf */ data,
4043 			 /* param_len */ datalen,
4044 			 /* sense_len */ SSD_FULL_SIZE,
4045 			 /* timeout */ timeout ? timeout : 5000);
4046 
4047 	if (arglist & CAM_ARG_ERR_RECOVER)
4048 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4049 
4050 	/* Disable freezing the device queue */
4051 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4052 
4053 	if (((retval = cam_send_ccb(device, ccb)) < 0)
4054 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4055 		if (arglist & CAM_ARG_VERBOSE) {
4056 			cam_error_print(device, ccb, CAM_ESF_ALL,
4057 					CAM_EPF_ALL, stderr);
4058 		}
4059 		cam_freeccb(ccb);
4060 		cam_close_device(device);
4061 
4062 		if (retval < 0)
4063 			err(1, "error sending mode select command");
4064 		else
4065 			errx(1, "error sending mode select command");
4066 
4067 	}
4068 
4069 	cam_freeccb(ccb);
4070 }
4071 
4072 void
4073 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4074 	 int retry_count, int timeout)
4075 {
4076 	int c, mode_page = -1, page_control = 0;
4077 	int binary = 0, list = 0;
4078 
4079 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4080 		switch(c) {
4081 		case 'b':
4082 			binary = 1;
4083 			break;
4084 		case 'd':
4085 			arglist |= CAM_ARG_DBD;
4086 			break;
4087 		case 'e':
4088 			arglist |= CAM_ARG_MODE_EDIT;
4089 			break;
4090 		case 'l':
4091 			list = 1;
4092 			break;
4093 		case 'm':
4094 			mode_page = strtol(optarg, NULL, 0);
4095 			if (mode_page < 0)
4096 				errx(1, "invalid mode page %d", mode_page);
4097 			break;
4098 		case 'P':
4099 			page_control = strtol(optarg, NULL, 0);
4100 			if ((page_control < 0) || (page_control > 3))
4101 				errx(1, "invalid page control field %d",
4102 				     page_control);
4103 			arglist |= CAM_ARG_PAGE_CNTL;
4104 			break;
4105 		default:
4106 			break;
4107 		}
4108 	}
4109 
4110 	if (mode_page == -1 && list == 0)
4111 		errx(1, "you must specify a mode page!");
4112 
4113 	if (list) {
4114 		mode_list(device, page_control, arglist & CAM_ARG_DBD,
4115 		    retry_count, timeout);
4116 	} else {
4117 		mode_edit(device, mode_page, page_control,
4118 		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
4119 		    retry_count, timeout);
4120 	}
4121 }
4122 
4123 static int
4124 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4125 	int retry_count, int timeout)
4126 {
4127 	union ccb *ccb;
4128 	u_int32_t flags = CAM_DIR_NONE;
4129 	u_int8_t *data_ptr = NULL;
4130 	u_int8_t cdb[20];
4131 	u_int8_t atacmd[12];
4132 	struct get_hook hook;
4133 	int c, data_bytes = 0;
4134 	int cdb_len = 0;
4135 	int atacmd_len = 0;
4136 	int dmacmd = 0;
4137 	int fpdmacmd = 0;
4138 	int need_res = 0;
4139 	char *datastr = NULL, *tstr, *resstr = NULL;
4140 	int error = 0;
4141 	int fd_data = 0, fd_res = 0;
4142 	int retval;
4143 
4144 	ccb = cam_getccb(device);
4145 
4146 	if (ccb == NULL) {
4147 		warnx("scsicmd: error allocating ccb");
4148 		return(1);
4149 	}
4150 
4151 	CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
4152 
4153 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4154 		switch(c) {
4155 		case 'a':
4156 			tstr = optarg;
4157 			while (isspace(*tstr) && (*tstr != '\0'))
4158 				tstr++;
4159 			hook.argc = argc - optind;
4160 			hook.argv = argv + optind;
4161 			hook.got = 0;
4162 			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4163 						    iget, &hook);
4164 			/*
4165 			 * Increment optind by the number of arguments the
4166 			 * encoding routine processed.  After each call to
4167 			 * getopt(3), optind points to the argument that
4168 			 * getopt should process _next_.  In this case,
4169 			 * that means it points to the first command string
4170 			 * argument, if there is one.  Once we increment
4171 			 * this, it should point to either the next command
4172 			 * line argument, or it should be past the end of
4173 			 * the list.
4174 			 */
4175 			optind += hook.got;
4176 			break;
4177 		case 'c':
4178 			tstr = optarg;
4179 			while (isspace(*tstr) && (*tstr != '\0'))
4180 				tstr++;
4181 			hook.argc = argc - optind;
4182 			hook.argv = argv + optind;
4183 			hook.got = 0;
4184 			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4185 						    iget, &hook);
4186 			/*
4187 			 * Increment optind by the number of arguments the
4188 			 * encoding routine processed.  After each call to
4189 			 * getopt(3), optind points to the argument that
4190 			 * getopt should process _next_.  In this case,
4191 			 * that means it points to the first command string
4192 			 * argument, if there is one.  Once we increment
4193 			 * this, it should point to either the next command
4194 			 * line argument, or it should be past the end of
4195 			 * the list.
4196 			 */
4197 			optind += hook.got;
4198 			break;
4199 		case 'd':
4200 			dmacmd = 1;
4201 			break;
4202 		case 'f':
4203 			fpdmacmd = 1;
4204 			break;
4205 		case 'i':
4206 			if (arglist & CAM_ARG_CMD_OUT) {
4207 				warnx("command must either be "
4208 				      "read or write, not both");
4209 				error = 1;
4210 				goto scsicmd_bailout;
4211 			}
4212 			arglist |= CAM_ARG_CMD_IN;
4213 			flags = CAM_DIR_IN;
4214 			data_bytes = strtol(optarg, NULL, 0);
4215 			if (data_bytes <= 0) {
4216 				warnx("invalid number of input bytes %d",
4217 				      data_bytes);
4218 				error = 1;
4219 				goto scsicmd_bailout;
4220 			}
4221 			hook.argc = argc - optind;
4222 			hook.argv = argv + optind;
4223 			hook.got = 0;
4224 			optind++;
4225 			datastr = cget(&hook, NULL);
4226 			/*
4227 			 * If the user supplied "-" instead of a format, he
4228 			 * wants the data to be written to stdout.
4229 			 */
4230 			if ((datastr != NULL)
4231 			 && (datastr[0] == '-'))
4232 				fd_data = 1;
4233 
4234 			data_ptr = (u_int8_t *)malloc(data_bytes);
4235 			if (data_ptr == NULL) {
4236 				warnx("can't malloc memory for data_ptr");
4237 				error = 1;
4238 				goto scsicmd_bailout;
4239 			}
4240 			break;
4241 		case 'o':
4242 			if (arglist & CAM_ARG_CMD_IN) {
4243 				warnx("command must either be "
4244 				      "read or write, not both");
4245 				error = 1;
4246 				goto scsicmd_bailout;
4247 			}
4248 			arglist |= CAM_ARG_CMD_OUT;
4249 			flags = CAM_DIR_OUT;
4250 			data_bytes = strtol(optarg, NULL, 0);
4251 			if (data_bytes <= 0) {
4252 				warnx("invalid number of output bytes %d",
4253 				      data_bytes);
4254 				error = 1;
4255 				goto scsicmd_bailout;
4256 			}
4257 			hook.argc = argc - optind;
4258 			hook.argv = argv + optind;
4259 			hook.got = 0;
4260 			datastr = cget(&hook, NULL);
4261 			data_ptr = (u_int8_t *)malloc(data_bytes);
4262 			if (data_ptr == NULL) {
4263 				warnx("can't malloc memory for data_ptr");
4264 				error = 1;
4265 				goto scsicmd_bailout;
4266 			}
4267 			bzero(data_ptr, data_bytes);
4268 			/*
4269 			 * If the user supplied "-" instead of a format, he
4270 			 * wants the data to be read from stdin.
4271 			 */
4272 			if ((datastr != NULL)
4273 			 && (datastr[0] == '-'))
4274 				fd_data = 1;
4275 			else
4276 				buff_encode_visit(data_ptr, data_bytes, datastr,
4277 						  iget, &hook);
4278 			optind += hook.got;
4279 			break;
4280 		case 'r':
4281 			need_res = 1;
4282 			hook.argc = argc - optind;
4283 			hook.argv = argv + optind;
4284 			hook.got = 0;
4285 			resstr = cget(&hook, NULL);
4286 			if ((resstr != NULL) && (resstr[0] == '-'))
4287 				fd_res = 1;
4288 			optind += hook.got;
4289 			break;
4290 		default:
4291 			break;
4292 		}
4293 	}
4294 
4295 	/*
4296 	 * If fd_data is set, and we're writing to the device, we need to
4297 	 * read the data the user wants written from stdin.
4298 	 */
4299 	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4300 		ssize_t amt_read;
4301 		int amt_to_read = data_bytes;
4302 		u_int8_t *buf_ptr = data_ptr;
4303 
4304 		for (amt_read = 0; amt_to_read > 0;
4305 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4306 			if (amt_read == -1) {
4307 				warn("error reading data from stdin");
4308 				error = 1;
4309 				goto scsicmd_bailout;
4310 			}
4311 			amt_to_read -= amt_read;
4312 			buf_ptr += amt_read;
4313 		}
4314 	}
4315 
4316 	if (arglist & CAM_ARG_ERR_RECOVER)
4317 		flags |= CAM_PASS_ERR_RECOVER;
4318 
4319 	/* Disable freezing the device queue */
4320 	flags |= CAM_DEV_QFRZDIS;
4321 
4322 	if (cdb_len) {
4323 		/*
4324 		 * This is taken from the SCSI-3 draft spec.
4325 		 * (T10/1157D revision 0.3)
4326 		 * The top 3 bits of an opcode are the group code.
4327 		 * The next 5 bits are the command code.
4328 		 * Group 0:  six byte commands
4329 		 * Group 1:  ten byte commands
4330 		 * Group 2:  ten byte commands
4331 		 * Group 3:  reserved
4332 		 * Group 4:  sixteen byte commands
4333 		 * Group 5:  twelve byte commands
4334 		 * Group 6:  vendor specific
4335 		 * Group 7:  vendor specific
4336 		 */
4337 		switch((cdb[0] >> 5) & 0x7) {
4338 			case 0:
4339 				cdb_len = 6;
4340 				break;
4341 			case 1:
4342 			case 2:
4343 				cdb_len = 10;
4344 				break;
4345 			case 3:
4346 			case 6:
4347 			case 7:
4348 			        /* computed by buff_encode_visit */
4349 				break;
4350 			case 4:
4351 				cdb_len = 16;
4352 				break;
4353 			case 5:
4354 				cdb_len = 12;
4355 				break;
4356 		}
4357 
4358 		/*
4359 		 * We should probably use csio_build_visit or something like that
4360 		 * here, but it's easier to encode arguments as you go.  The
4361 		 * alternative would be skipping the CDB argument and then encoding
4362 		 * it here, since we've got the data buffer argument by now.
4363 		 */
4364 		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4365 
4366 		cam_fill_csio(&ccb->csio,
4367 		      /*retries*/ retry_count,
4368 		      /*cbfcnp*/ NULL,
4369 		      /*flags*/ flags,
4370 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
4371 		      /*data_ptr*/ data_ptr,
4372 		      /*dxfer_len*/ data_bytes,
4373 		      /*sense_len*/ SSD_FULL_SIZE,
4374 		      /*cdb_len*/ cdb_len,
4375 		      /*timeout*/ timeout ? timeout : 5000);
4376 	} else {
4377 		atacmd_len = 12;
4378 		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4379 		if (need_res)
4380 			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4381 		if (dmacmd)
4382 			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4383 		if (fpdmacmd)
4384 			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4385 
4386 		cam_fill_ataio(&ccb->ataio,
4387 		      /*retries*/ retry_count,
4388 		      /*cbfcnp*/ NULL,
4389 		      /*flags*/ flags,
4390 		      /*tag_action*/ 0,
4391 		      /*data_ptr*/ data_ptr,
4392 		      /*dxfer_len*/ data_bytes,
4393 		      /*timeout*/ timeout ? timeout : 5000);
4394 	}
4395 
4396 	if (((retval = cam_send_ccb(device, ccb)) < 0)
4397 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4398 		const char warnstr[] = "error sending command";
4399 
4400 		if (retval < 0)
4401 			warn(warnstr);
4402 		else
4403 			warnx(warnstr);
4404 
4405 		if (arglist & CAM_ARG_VERBOSE) {
4406 			cam_error_print(device, ccb, CAM_ESF_ALL,
4407 					CAM_EPF_ALL, stderr);
4408 		}
4409 
4410 		error = 1;
4411 		goto scsicmd_bailout;
4412 	}
4413 
4414 	if (atacmd_len && need_res) {
4415 		if (fd_res == 0) {
4416 			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4417 					  arg_put, NULL);
4418 			fprintf(stdout, "\n");
4419 		} else {
4420 			fprintf(stdout,
4421 			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4422 			    ccb->ataio.res.status,
4423 			    ccb->ataio.res.error,
4424 			    ccb->ataio.res.lba_low,
4425 			    ccb->ataio.res.lba_mid,
4426 			    ccb->ataio.res.lba_high,
4427 			    ccb->ataio.res.device,
4428 			    ccb->ataio.res.lba_low_exp,
4429 			    ccb->ataio.res.lba_mid_exp,
4430 			    ccb->ataio.res.lba_high_exp,
4431 			    ccb->ataio.res.sector_count,
4432 			    ccb->ataio.res.sector_count_exp);
4433 			fflush(stdout);
4434 		}
4435 	}
4436 
4437 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4438 	 && (arglist & CAM_ARG_CMD_IN)
4439 	 && (data_bytes > 0)) {
4440 		if (fd_data == 0) {
4441 			buff_decode_visit(data_ptr, data_bytes, datastr,
4442 					  arg_put, NULL);
4443 			fprintf(stdout, "\n");
4444 		} else {
4445 			ssize_t amt_written;
4446 			int amt_to_write = data_bytes;
4447 			u_int8_t *buf_ptr = data_ptr;
4448 
4449 			for (amt_written = 0; (amt_to_write > 0) &&
4450 			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4451 				amt_to_write -= amt_written;
4452 				buf_ptr += amt_written;
4453 			}
4454 			if (amt_written == -1) {
4455 				warn("error writing data to stdout");
4456 				error = 1;
4457 				goto scsicmd_bailout;
4458 			} else if ((amt_written == 0)
4459 				&& (amt_to_write > 0)) {
4460 				warnx("only wrote %u bytes out of %u",
4461 				      data_bytes - amt_to_write, data_bytes);
4462 			}
4463 		}
4464 	}
4465 
4466 scsicmd_bailout:
4467 
4468 	if ((data_bytes > 0) && (data_ptr != NULL))
4469 		free(data_ptr);
4470 
4471 	cam_freeccb(ccb);
4472 
4473 	return(error);
4474 }
4475 
4476 static int
4477 camdebug(int argc, char **argv, char *combinedopt)
4478 {
4479 	int c, fd;
4480 	path_id_t bus = CAM_BUS_WILDCARD;
4481 	target_id_t target = CAM_TARGET_WILDCARD;
4482 	lun_id_t lun = CAM_LUN_WILDCARD;
4483 	char *tstr, *tmpstr = NULL;
4484 	union ccb ccb;
4485 	int error = 0;
4486 
4487 	bzero(&ccb, sizeof(union ccb));
4488 
4489 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4490 		switch(c) {
4491 		case 'I':
4492 			arglist |= CAM_ARG_DEBUG_INFO;
4493 			ccb.cdbg.flags |= CAM_DEBUG_INFO;
4494 			break;
4495 		case 'P':
4496 			arglist |= CAM_ARG_DEBUG_PERIPH;
4497 			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4498 			break;
4499 		case 'S':
4500 			arglist |= CAM_ARG_DEBUG_SUBTRACE;
4501 			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4502 			break;
4503 		case 'T':
4504 			arglist |= CAM_ARG_DEBUG_TRACE;
4505 			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4506 			break;
4507 		case 'X':
4508 			arglist |= CAM_ARG_DEBUG_XPT;
4509 			ccb.cdbg.flags |= CAM_DEBUG_XPT;
4510 			break;
4511 		case 'c':
4512 			arglist |= CAM_ARG_DEBUG_CDB;
4513 			ccb.cdbg.flags |= CAM_DEBUG_CDB;
4514 			break;
4515 		case 'p':
4516 			arglist |= CAM_ARG_DEBUG_PROBE;
4517 			ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4518 			break;
4519 		default:
4520 			break;
4521 		}
4522 	}
4523 
4524 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4525 		warnx("error opening transport layer device %s", XPT_DEVICE);
4526 		warn("%s", XPT_DEVICE);
4527 		return(1);
4528 	}
4529 	argc -= optind;
4530 	argv += optind;
4531 
4532 	if (argc <= 0) {
4533 		warnx("you must specify \"off\", \"all\" or a bus,");
4534 		warnx("bus:target, or bus:target:lun");
4535 		close(fd);
4536 		return(1);
4537 	}
4538 
4539 	tstr = *argv;
4540 
4541 	while (isspace(*tstr) && (*tstr != '\0'))
4542 		tstr++;
4543 
4544 	if (strncmp(tstr, "off", 3) == 0) {
4545 		ccb.cdbg.flags = CAM_DEBUG_NONE;
4546 		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4547 			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4548 			     CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4549 	} else if (strncmp(tstr, "all", 3) != 0) {
4550 		tmpstr = (char *)strtok(tstr, ":");
4551 		if ((tmpstr != NULL) && (*tmpstr != '\0')){
4552 			bus = strtol(tmpstr, NULL, 0);
4553 			arglist |= CAM_ARG_BUS;
4554 			tmpstr = (char *)strtok(NULL, ":");
4555 			if ((tmpstr != NULL) && (*tmpstr != '\0')){
4556 				target = strtol(tmpstr, NULL, 0);
4557 				arglist |= CAM_ARG_TARGET;
4558 				tmpstr = (char *)strtok(NULL, ":");
4559 				if ((tmpstr != NULL) && (*tmpstr != '\0')){
4560 					lun = strtol(tmpstr, NULL, 0);
4561 					arglist |= CAM_ARG_LUN;
4562 				}
4563 			}
4564 		} else {
4565 			error = 1;
4566 			warnx("you must specify \"all\", \"off\", or a bus,");
4567 			warnx("bus:target, or bus:target:lun to debug");
4568 		}
4569 	}
4570 
4571 	if (error == 0) {
4572 
4573 		ccb.ccb_h.func_code = XPT_DEBUG;
4574 		ccb.ccb_h.path_id = bus;
4575 		ccb.ccb_h.target_id = target;
4576 		ccb.ccb_h.target_lun = lun;
4577 
4578 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4579 			warn("CAMIOCOMMAND ioctl failed");
4580 			error = 1;
4581 		}
4582 
4583 		if (error == 0) {
4584 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4585 			     CAM_FUNC_NOTAVAIL) {
4586 				warnx("CAM debugging not available");
4587 				warnx("you need to put options CAMDEBUG in"
4588 				      " your kernel config file!");
4589 				error = 1;
4590 			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4591 				    CAM_REQ_CMP) {
4592 				warnx("XPT_DEBUG CCB failed with status %#x",
4593 				      ccb.ccb_h.status);
4594 				error = 1;
4595 			} else {
4596 				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4597 					fprintf(stderr,
4598 						"Debugging turned off\n");
4599 				} else {
4600 					fprintf(stderr,
4601 						"Debugging enabled for "
4602 						"%d:%d:%jx\n",
4603 						bus, target, (uintmax_t)lun);
4604 				}
4605 			}
4606 		}
4607 		close(fd);
4608 	}
4609 
4610 	return(error);
4611 }
4612 
4613 static int
4614 tagcontrol(struct cam_device *device, int argc, char **argv,
4615 	   char *combinedopt)
4616 {
4617 	int c;
4618 	union ccb *ccb;
4619 	int numtags = -1;
4620 	int retval = 0;
4621 	int quiet = 0;
4622 	char pathstr[1024];
4623 
4624 	ccb = cam_getccb(device);
4625 
4626 	if (ccb == NULL) {
4627 		warnx("tagcontrol: error allocating ccb");
4628 		return(1);
4629 	}
4630 
4631 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4632 		switch(c) {
4633 		case 'N':
4634 			numtags = strtol(optarg, NULL, 0);
4635 			if (numtags < 0) {
4636 				warnx("tag count %d is < 0", numtags);
4637 				retval = 1;
4638 				goto tagcontrol_bailout;
4639 			}
4640 			break;
4641 		case 'q':
4642 			quiet++;
4643 			break;
4644 		default:
4645 			break;
4646 		}
4647 	}
4648 
4649 	cam_path_string(device, pathstr, sizeof(pathstr));
4650 
4651 	if (numtags >= 0) {
4652 		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->crs);
4653 		ccb->ccb_h.func_code = XPT_REL_SIMQ;
4654 		ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4655 		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4656 		ccb->crs.openings = numtags;
4657 
4658 
4659 		if (cam_send_ccb(device, ccb) < 0) {
4660 			perror("error sending XPT_REL_SIMQ CCB");
4661 			retval = 1;
4662 			goto tagcontrol_bailout;
4663 		}
4664 
4665 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4666 			warnx("XPT_REL_SIMQ CCB failed");
4667 			cam_error_print(device, ccb, CAM_ESF_ALL,
4668 					CAM_EPF_ALL, stderr);
4669 			retval = 1;
4670 			goto tagcontrol_bailout;
4671 		}
4672 
4673 
4674 		if (quiet == 0)
4675 			fprintf(stdout, "%stagged openings now %d\n",
4676 				pathstr, ccb->crs.openings);
4677 	}
4678 
4679 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgds);
4680 
4681 	ccb->ccb_h.func_code = XPT_GDEV_STATS;
4682 
4683 	if (cam_send_ccb(device, ccb) < 0) {
4684 		perror("error sending XPT_GDEV_STATS CCB");
4685 		retval = 1;
4686 		goto tagcontrol_bailout;
4687 	}
4688 
4689 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4690 		warnx("XPT_GDEV_STATS CCB failed");
4691 		cam_error_print(device, ccb, CAM_ESF_ALL,
4692 				CAM_EPF_ALL, stderr);
4693 		retval = 1;
4694 		goto tagcontrol_bailout;
4695 	}
4696 
4697 	if (arglist & CAM_ARG_VERBOSE) {
4698 		fprintf(stdout, "%s", pathstr);
4699 		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4700 		fprintf(stdout, "%s", pathstr);
4701 		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4702 		fprintf(stdout, "%s", pathstr);
4703 		fprintf(stdout, "allocated     %d\n", ccb->cgds.allocated);
4704 		fprintf(stdout, "%s", pathstr);
4705 		fprintf(stdout, "queued        %d\n", ccb->cgds.queued);
4706 		fprintf(stdout, "%s", pathstr);
4707 		fprintf(stdout, "held          %d\n", ccb->cgds.held);
4708 		fprintf(stdout, "%s", pathstr);
4709 		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4710 		fprintf(stdout, "%s", pathstr);
4711 		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4712 	} else {
4713 		if (quiet == 0) {
4714 			fprintf(stdout, "%s", pathstr);
4715 			fprintf(stdout, "device openings: ");
4716 		}
4717 		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4718 			ccb->cgds.dev_active);
4719 	}
4720 
4721 tagcontrol_bailout:
4722 
4723 	cam_freeccb(ccb);
4724 	return(retval);
4725 }
4726 
4727 static void
4728 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4729 {
4730 	char pathstr[1024];
4731 
4732 	cam_path_string(device, pathstr, sizeof(pathstr));
4733 
4734 	if (cts->transport == XPORT_SPI) {
4735 		struct ccb_trans_settings_spi *spi =
4736 		    &cts->xport_specific.spi;
4737 
4738 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4739 
4740 			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4741 				spi->sync_period);
4742 
4743 			if (spi->sync_offset != 0) {
4744 				u_int freq;
4745 
4746 				freq = scsi_calc_syncsrate(spi->sync_period);
4747 				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4748 					pathstr, freq / 1000, freq % 1000);
4749 			}
4750 		}
4751 
4752 		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4753 			fprintf(stdout, "%soffset: %d\n", pathstr,
4754 			    spi->sync_offset);
4755 		}
4756 
4757 		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4758 			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4759 				(0x01 << spi->bus_width) * 8);
4760 		}
4761 
4762 		if (spi->valid & CTS_SPI_VALID_DISC) {
4763 			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4764 				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4765 				"enabled" : "disabled");
4766 		}
4767 	}
4768 	if (cts->transport == XPORT_FC) {
4769 		struct ccb_trans_settings_fc *fc =
4770 		    &cts->xport_specific.fc;
4771 
4772 		if (fc->valid & CTS_FC_VALID_WWNN)
4773 			fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4774 			    (long long) fc->wwnn);
4775 		if (fc->valid & CTS_FC_VALID_WWPN)
4776 			fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4777 			    (long long) fc->wwpn);
4778 		if (fc->valid & CTS_FC_VALID_PORT)
4779 			fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4780 		if (fc->valid & CTS_FC_VALID_SPEED)
4781 			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4782 			    pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4783 	}
4784 	if (cts->transport == XPORT_SAS) {
4785 		struct ccb_trans_settings_sas *sas =
4786 		    &cts->xport_specific.sas;
4787 
4788 		if (sas->valid & CTS_SAS_VALID_SPEED)
4789 			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4790 			    pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4791 	}
4792 	if (cts->transport == XPORT_ATA) {
4793 		struct ccb_trans_settings_pata *pata =
4794 		    &cts->xport_specific.ata;
4795 
4796 		if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4797 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4798 				ata_mode2string(pata->mode));
4799 		}
4800 		if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4801 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4802 				pata->atapi);
4803 		}
4804 		if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4805 			fprintf(stdout, "%sPIO transaction length: %d\n",
4806 				pathstr, pata->bytecount);
4807 		}
4808 	}
4809 	if (cts->transport == XPORT_SATA) {
4810 		struct ccb_trans_settings_sata *sata =
4811 		    &cts->xport_specific.sata;
4812 
4813 		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4814 			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4815 				sata->revision);
4816 		}
4817 		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4818 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4819 				ata_mode2string(sata->mode));
4820 		}
4821 		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4822 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4823 				sata->atapi);
4824 		}
4825 		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4826 			fprintf(stdout, "%sPIO transaction length: %d\n",
4827 				pathstr, sata->bytecount);
4828 		}
4829 		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4830 			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4831 				sata->pm_present);
4832 		}
4833 		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4834 			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4835 				sata->tags);
4836 		}
4837 		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4838 			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4839 				sata->caps);
4840 		}
4841 	}
4842 	if (cts->protocol == PROTO_ATA) {
4843 		struct ccb_trans_settings_ata *ata=
4844 		    &cts->proto_specific.ata;
4845 
4846 		if (ata->valid & CTS_ATA_VALID_TQ) {
4847 			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4848 				(ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4849 				"enabled" : "disabled");
4850 		}
4851 	}
4852 	if (cts->protocol == PROTO_SCSI) {
4853 		struct ccb_trans_settings_scsi *scsi=
4854 		    &cts->proto_specific.scsi;
4855 
4856 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
4857 			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4858 				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4859 				"enabled" : "disabled");
4860 		}
4861 	}
4862 
4863 }
4864 
4865 /*
4866  * Get a path inquiry CCB for the specified device.
4867  */
4868 static int
4869 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4870 {
4871 	union ccb *ccb;
4872 	int retval = 0;
4873 
4874 	ccb = cam_getccb(device);
4875 	if (ccb == NULL) {
4876 		warnx("get_cpi: couldn't allocate CCB");
4877 		return(1);
4878 	}
4879 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
4880 	ccb->ccb_h.func_code = XPT_PATH_INQ;
4881 	if (cam_send_ccb(device, ccb) < 0) {
4882 		warn("get_cpi: error sending Path Inquiry CCB");
4883 		if (arglist & CAM_ARG_VERBOSE)
4884 			cam_error_print(device, ccb, CAM_ESF_ALL,
4885 					CAM_EPF_ALL, stderr);
4886 		retval = 1;
4887 		goto get_cpi_bailout;
4888 	}
4889 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4890 		if (arglist & CAM_ARG_VERBOSE)
4891 			cam_error_print(device, ccb, CAM_ESF_ALL,
4892 					CAM_EPF_ALL, stderr);
4893 		retval = 1;
4894 		goto get_cpi_bailout;
4895 	}
4896 	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4897 
4898 get_cpi_bailout:
4899 	cam_freeccb(ccb);
4900 	return(retval);
4901 }
4902 
4903 /*
4904  * Get a get device CCB for the specified device.
4905  */
4906 static int
4907 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4908 {
4909 	union ccb *ccb;
4910 	int retval = 0;
4911 
4912 	ccb = cam_getccb(device);
4913 	if (ccb == NULL) {
4914 		warnx("get_cgd: couldn't allocate CCB");
4915 		return(1);
4916 	}
4917 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgd);
4918 	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4919 	if (cam_send_ccb(device, ccb) < 0) {
4920 		warn("get_cgd: error sending Path Inquiry CCB");
4921 		if (arglist & CAM_ARG_VERBOSE)
4922 			cam_error_print(device, ccb, CAM_ESF_ALL,
4923 					CAM_EPF_ALL, stderr);
4924 		retval = 1;
4925 		goto get_cgd_bailout;
4926 	}
4927 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4928 		if (arglist & CAM_ARG_VERBOSE)
4929 			cam_error_print(device, ccb, CAM_ESF_ALL,
4930 					CAM_EPF_ALL, stderr);
4931 		retval = 1;
4932 		goto get_cgd_bailout;
4933 	}
4934 	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4935 
4936 get_cgd_bailout:
4937 	cam_freeccb(ccb);
4938 	return(retval);
4939 }
4940 
4941 /*
4942  * Returns 1 if the device has the VPD page, 0 if it does not, and -1 on an
4943  * error.
4944  */
4945 int
4946 dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count,
4947 		 int timeout, int verbosemode)
4948 {
4949 	union ccb *ccb = NULL;
4950 	struct scsi_vpd_supported_page_list sup_pages;
4951 	int i;
4952 	int retval = 0;
4953 
4954 	ccb = cam_getccb(dev);
4955 	if (ccb == NULL) {
4956 		warn("Unable to allocate CCB");
4957 		retval = -1;
4958 		goto bailout;
4959 	}
4960 
4961 	/* cam_getccb cleans up the header, caller has to zero the payload */
4962 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
4963 
4964 	bzero(&sup_pages, sizeof(sup_pages));
4965 
4966 	scsi_inquiry(&ccb->csio,
4967 		     /*retries*/ retry_count,
4968 		     /*cbfcnp*/ NULL,
4969 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
4970 		     /* inq_buf */ (u_int8_t *)&sup_pages,
4971 		     /* inq_len */ sizeof(sup_pages),
4972 		     /* evpd */ 1,
4973 		     /* page_code */ SVPD_SUPPORTED_PAGE_LIST,
4974 		     /* sense_len */ SSD_FULL_SIZE,
4975 		     /* timeout */ timeout ? timeout : 5000);
4976 
4977 	/* Disable freezing the device queue */
4978 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4979 
4980 	if (retry_count != 0)
4981 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4982 
4983 	if (cam_send_ccb(dev, ccb) < 0) {
4984 		cam_freeccb(ccb);
4985 		ccb = NULL;
4986 		retval = -1;
4987 		goto bailout;
4988 	}
4989 
4990 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4991 		if (verbosemode != 0)
4992 			cam_error_print(dev, ccb, CAM_ESF_ALL,
4993 					CAM_EPF_ALL, stderr);
4994 		retval = -1;
4995 		goto bailout;
4996 	}
4997 
4998 	for (i = 0; i < sup_pages.length; i++) {
4999 		if (sup_pages.list[i] == page_id) {
5000 			retval = 1;
5001 			goto bailout;
5002 		}
5003 	}
5004 bailout:
5005 	if (ccb != NULL)
5006 		cam_freeccb(ccb);
5007 
5008 	return (retval);
5009 }
5010 
5011 /*
5012  * devtype is filled in with the type of device.
5013  * Returns 0 for success, non-zero for failure.
5014  */
5015 int
5016 get_device_type(struct cam_device *dev, int retry_count, int timeout,
5017 		    int verbosemode, camcontrol_devtype *devtype)
5018 {
5019 	struct ccb_getdev cgd;
5020 	int retval = 0;
5021 
5022 	retval = get_cgd(dev, &cgd);
5023 	if (retval != 0)
5024 		goto bailout;
5025 
5026 	switch (cgd.protocol) {
5027 	case PROTO_SCSI:
5028 		break;
5029 	case PROTO_ATA:
5030 	case PROTO_ATAPI:
5031 	case PROTO_SATAPM:
5032 		*devtype = CC_DT_ATA;
5033 		goto bailout;
5034 		break; /*NOTREACHED*/
5035 	default:
5036 		*devtype = CC_DT_UNKNOWN;
5037 		goto bailout;
5038 		break; /*NOTREACHED*/
5039 	}
5040 
5041 	/*
5042 	 * Check for the ATA Information VPD page (0x89).  If this is an
5043 	 * ATA device behind a SCSI to ATA translation layer, this VPD page
5044 	 * should be present.
5045 	 *
5046 	 * If that VPD page isn't present, or we get an error back from the
5047 	 * INQUIRY command, we'll just treat it as a normal SCSI device.
5048 	 */
5049 	retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5050 				  timeout, verbosemode);
5051 	if (retval == 1)
5052 		*devtype = CC_DT_ATA_BEHIND_SCSI;
5053 	else
5054 		*devtype = CC_DT_SCSI;
5055 
5056 	retval = 0;
5057 
5058 bailout:
5059 	return (retval);
5060 }
5061 
5062 int
5063 build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5064     uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5065     uint16_t sector_count, uint64_t lba, uint8_t command, uint32_t auxiliary,
5066     uint8_t *data_ptr, uint32_t dxfer_len, uint8_t *cdb_storage,
5067     size_t cdb_storage_len, uint8_t sense_len, uint32_t timeout,
5068     int is48bit, camcontrol_devtype devtype)
5069 {
5070 	int retval = 0;
5071 
5072 	if (devtype == CC_DT_ATA) {
5073 		cam_fill_ataio(&ccb->ataio,
5074 		    /*retries*/ retry_count,
5075 		    /*cbfcnp*/ NULL,
5076 		    /*flags*/ flags,
5077 		    /*tag_action*/ tag_action,
5078 		    /*data_ptr*/ data_ptr,
5079 		    /*dxfer_len*/ dxfer_len,
5080 		    /*timeout*/ timeout);
5081 		if (is48bit || lba > ATA_MAX_28BIT_LBA)
5082 			ata_48bit_cmd(&ccb->ataio, command, features, lba,
5083 			    sector_count);
5084 		else
5085 			ata_28bit_cmd(&ccb->ataio, command, features, lba,
5086 			    sector_count);
5087 
5088 		if (auxiliary != 0) {
5089 			ccb->ataio.ata_flags |= ATA_FLAG_AUX;
5090 			ccb->ataio.aux = auxiliary;
5091 		}
5092 
5093 		if (ata_flags & AP_FLAG_CHK_COND)
5094 			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
5095 
5096 		if ((protocol & AP_PROTO_MASK) == AP_PROTO_DMA)
5097 			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
5098 		else if ((protocol & AP_PROTO_MASK) == AP_PROTO_FPDMA)
5099 			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
5100 	} else {
5101 		if (is48bit || lba > ATA_MAX_28BIT_LBA)
5102 			protocol |= AP_EXTEND;
5103 
5104 		retval = scsi_ata_pass(&ccb->csio,
5105 		    /*retries*/ retry_count,
5106 		    /*cbfcnp*/ NULL,
5107 		    /*flags*/ flags,
5108 		    /*tag_action*/ tag_action,
5109 		    /*protocol*/ protocol,
5110 		    /*ata_flags*/ ata_flags,
5111 		    /*features*/ features,
5112 		    /*sector_count*/ sector_count,
5113 		    /*lba*/ lba,
5114 		    /*command*/ command,
5115 		    /*device*/ 0,
5116 		    /*icc*/ 0,
5117 		    /*auxiliary*/ auxiliary,
5118 		    /*control*/ 0,
5119 		    /*data_ptr*/ data_ptr,
5120 		    /*dxfer_len*/ dxfer_len,
5121 		    /*cdb_storage*/ cdb_storage,
5122 		    /*cdb_storage_len*/ cdb_storage_len,
5123 		    /*minimum_cmd_size*/ 0,
5124 		    /*sense_len*/ sense_len,
5125 		    /*timeout*/ timeout);
5126 	}
5127 
5128 	return (retval);
5129 }
5130 
5131 int
5132 get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
5133 	       uint16_t *count, uint64_t *lba, uint8_t *device, uint8_t *status)
5134 {
5135 	int retval = 0;
5136 
5137 	switch (ccb->ccb_h.func_code) {
5138 	case XPT_SCSI_IO: {
5139 		uint8_t opcode;
5140 		int error_code = 0, sense_key = 0, asc = 0, ascq = 0;
5141 
5142 		/*
5143 		 * In this case, we have SCSI ATA PASS-THROUGH command, 12
5144 		 * or 16 byte, and need to see what
5145 		 */
5146 		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
5147 			opcode = ccb->csio.cdb_io.cdb_ptr[0];
5148 		else
5149 			opcode = ccb->csio.cdb_io.cdb_bytes[0];
5150 		if ((opcode != ATA_PASS_12)
5151 		 && (opcode != ATA_PASS_16)) {
5152 			retval = 1;
5153 			warnx("%s: unsupported opcode %02x", __func__, opcode);
5154 			goto bailout;
5155 		}
5156 
5157 		retval = scsi_extract_sense_ccb(ccb, &error_code, &sense_key,
5158 						&asc, &ascq);
5159 		/* Note: the _ccb() variant returns 0 for an error */
5160 		if (retval == 0) {
5161 			retval = 1;
5162 			goto bailout;
5163 		} else
5164 			retval = 0;
5165 
5166 		switch (error_code) {
5167 		case SSD_DESC_CURRENT_ERROR:
5168 		case SSD_DESC_DEFERRED_ERROR: {
5169 			struct scsi_sense_data_desc *sense;
5170 			struct scsi_sense_ata_ret_desc *desc;
5171 			uint8_t *desc_ptr;
5172 
5173 			sense = (struct scsi_sense_data_desc *)
5174 			    &ccb->csio.sense_data;
5175 
5176 			desc_ptr = scsi_find_desc(sense, ccb->csio.sense_len -
5177 			    ccb->csio.sense_resid, SSD_DESC_ATA);
5178 			if (desc_ptr == NULL) {
5179 				cam_error_print(dev, ccb, CAM_ESF_ALL,
5180 				    CAM_EPF_ALL, stderr);
5181 				retval = 1;
5182 				goto bailout;
5183 			}
5184 			desc = (struct scsi_sense_ata_ret_desc *)desc_ptr;
5185 
5186 			*error = desc->error;
5187 			*count = (desc->count_15_8 << 8) |
5188 				  desc->count_7_0;
5189 			*lba = ((uint64_t)desc->lba_47_40 << 40) |
5190 			       ((uint64_t)desc->lba_39_32 << 32) |
5191 			       ((uint64_t)desc->lba_31_24 << 24) |
5192 			       (desc->lba_23_16 << 16) |
5193 			       (desc->lba_15_8  <<  8) |
5194 			        desc->lba_7_0;
5195 			*device = desc->device;
5196 			*status = desc->status;
5197 
5198 			/*
5199 			 * If the extend bit isn't set, the result is for a
5200 			 * 12-byte ATA PASS-THROUGH command or a 16 or 32 byte
5201 			 * command without the extend bit set.  This means
5202 			 * that the device is supposed to return 28-bit
5203 			 * status.  The count field is only 8 bits, and the
5204 			 * LBA field is only 8 bits.
5205 			 */
5206 			if ((desc->flags & SSD_DESC_ATA_FLAG_EXTEND) == 0){
5207 				*count &= 0xff;
5208 				*lba &= 0x0fffffff;
5209 			}
5210 			break;
5211 		}
5212 		case SSD_CURRENT_ERROR:
5213 		case SSD_DEFERRED_ERROR: {
5214 #if 0
5215 			struct scsi_sense_data_fixed *sense;
5216 #endif
5217 			/*
5218 			 * XXX KDM need to support fixed sense data.
5219 			 */
5220 			warnx("%s: Fixed sense data not supported yet",
5221 			    __func__);
5222 			retval = 1;
5223 			goto bailout;
5224 			break; /*NOTREACHED*/
5225 		}
5226 		default:
5227 			retval = 1;
5228 			goto bailout;
5229 			break;
5230 		}
5231 
5232 		break;
5233 	}
5234 	case XPT_ATA_IO: {
5235 		struct ata_res *res;
5236 
5237 		/*
5238 		 * In this case, we have an ATA command, and we need to
5239 		 * fill in the requested values from the result register
5240 		 * set.
5241 		 */
5242 		res = &ccb->ataio.res;
5243 		*error = res->error;
5244 		*status = res->status;
5245 		*device = res->device;
5246 		*count = res->sector_count;
5247 		*lba = (res->lba_high << 16) |
5248 		       (res->lba_mid << 8) |
5249 		       (res->lba_low);
5250 		if (res->flags & CAM_ATAIO_48BIT) {
5251 			*count |= (res->sector_count_exp << 8);
5252 			*lba |= ((uint64_t)res->lba_low_exp << 24) |
5253 				((uint64_t)res->lba_mid_exp << 32) |
5254 				((uint64_t)res->lba_high_exp << 40);
5255 		} else {
5256 			*lba |= (res->device & 0xf) << 24;
5257 		}
5258 		break;
5259 	}
5260 	default:
5261 		retval = 1;
5262 		break;
5263 	}
5264 bailout:
5265 	return (retval);
5266 }
5267 
5268 static void
5269 cpi_print(struct ccb_pathinq *cpi)
5270 {
5271 	char adapter_str[1024];
5272 	int i;
5273 
5274 	snprintf(adapter_str, sizeof(adapter_str),
5275 		 "%s%d:", cpi->dev_name, cpi->unit_number);
5276 
5277 	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5278 		cpi->version_num);
5279 
5280 	for (i = 1; i < 0xff; i = i << 1) {
5281 		const char *str;
5282 
5283 		if ((i & cpi->hba_inquiry) == 0)
5284 			continue;
5285 
5286 		fprintf(stdout, "%s supports ", adapter_str);
5287 
5288 		switch(i) {
5289 		case PI_MDP_ABLE:
5290 			str = "MDP message";
5291 			break;
5292 		case PI_WIDE_32:
5293 			str = "32 bit wide SCSI";
5294 			break;
5295 		case PI_WIDE_16:
5296 			str = "16 bit wide SCSI";
5297 			break;
5298 		case PI_SDTR_ABLE:
5299 			str = "SDTR message";
5300 			break;
5301 		case PI_LINKED_CDB:
5302 			str = "linked CDBs";
5303 			break;
5304 		case PI_TAG_ABLE:
5305 			str = "tag queue messages";
5306 			break;
5307 		case PI_SOFT_RST:
5308 			str = "soft reset alternative";
5309 			break;
5310 		case PI_SATAPM:
5311 			str = "SATA Port Multiplier";
5312 			break;
5313 		default:
5314 			str = "unknown PI bit set";
5315 			break;
5316 		}
5317 		fprintf(stdout, "%s\n", str);
5318 	}
5319 
5320 	for (i = 1; i < 0xff; i = i << 1) {
5321 		const char *str;
5322 
5323 		if ((i & cpi->hba_misc) == 0)
5324 			continue;
5325 
5326 		fprintf(stdout, "%s ", adapter_str);
5327 
5328 		switch(i) {
5329 		case PIM_SCANHILO:
5330 			str = "bus scans from high ID to low ID";
5331 			break;
5332 		case PIM_NOREMOVE:
5333 			str = "removable devices not included in scan";
5334 			break;
5335 		case PIM_NOINITIATOR:
5336 			str = "initiator role not supported";
5337 			break;
5338 		case PIM_NOBUSRESET:
5339 			str = "user has disabled initial BUS RESET or"
5340 			      " controller is in target/mixed mode";
5341 			break;
5342 		case PIM_NO_6_BYTE:
5343 			str = "do not send 6-byte commands";
5344 			break;
5345 		case PIM_SEQSCAN:
5346 			str = "scan bus sequentially";
5347 			break;
5348 		default:
5349 			str = "unknown PIM bit set";
5350 			break;
5351 		}
5352 		fprintf(stdout, "%s\n", str);
5353 	}
5354 
5355 	for (i = 1; i < 0xff; i = i << 1) {
5356 		const char *str;
5357 
5358 		if ((i & cpi->target_sprt) == 0)
5359 			continue;
5360 
5361 		fprintf(stdout, "%s supports ", adapter_str);
5362 		switch(i) {
5363 		case PIT_PROCESSOR:
5364 			str = "target mode processor mode";
5365 			break;
5366 		case PIT_PHASE:
5367 			str = "target mode phase cog. mode";
5368 			break;
5369 		case PIT_DISCONNECT:
5370 			str = "disconnects in target mode";
5371 			break;
5372 		case PIT_TERM_IO:
5373 			str = "terminate I/O message in target mode";
5374 			break;
5375 		case PIT_GRP_6:
5376 			str = "group 6 commands in target mode";
5377 			break;
5378 		case PIT_GRP_7:
5379 			str = "group 7 commands in target mode";
5380 			break;
5381 		default:
5382 			str = "unknown PIT bit set";
5383 			break;
5384 		}
5385 
5386 		fprintf(stdout, "%s\n", str);
5387 	}
5388 	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5389 		cpi->hba_eng_cnt);
5390 	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5391 		cpi->max_target);
5392 	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5393 		cpi->max_lun);
5394 	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5395 		adapter_str, cpi->hpath_id);
5396 	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5397 		cpi->initiator_id);
5398 	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5399 	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5400 	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5401 	    adapter_str, cpi->hba_vendor);
5402 	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5403 	    adapter_str, cpi->hba_device);
5404 	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5405 	    adapter_str, cpi->hba_subvendor);
5406 	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5407 	    adapter_str, cpi->hba_subdevice);
5408 	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5409 	fprintf(stdout, "%s base transfer speed: ", adapter_str);
5410 	if (cpi->base_transfer_speed > 1000)
5411 		fprintf(stdout, "%d.%03dMB/sec\n",
5412 			cpi->base_transfer_speed / 1000,
5413 			cpi->base_transfer_speed % 1000);
5414 	else
5415 		fprintf(stdout, "%dKB/sec\n",
5416 			(cpi->base_transfer_speed % 1000) * 1000);
5417 	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5418 	    adapter_str, cpi->maxio);
5419 }
5420 
5421 static int
5422 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5423 	      struct ccb_trans_settings *cts)
5424 {
5425 	int retval;
5426 	union ccb *ccb;
5427 
5428 	retval = 0;
5429 	ccb = cam_getccb(device);
5430 
5431 	if (ccb == NULL) {
5432 		warnx("get_print_cts: error allocating ccb");
5433 		return(1);
5434 	}
5435 
5436 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5437 
5438 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5439 
5440 	if (user_settings == 0)
5441 		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5442 	else
5443 		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5444 
5445 	if (cam_send_ccb(device, ccb) < 0) {
5446 		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5447 		if (arglist & CAM_ARG_VERBOSE)
5448 			cam_error_print(device, ccb, CAM_ESF_ALL,
5449 					CAM_EPF_ALL, stderr);
5450 		retval = 1;
5451 		goto get_print_cts_bailout;
5452 	}
5453 
5454 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5455 		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5456 		if (arglist & CAM_ARG_VERBOSE)
5457 			cam_error_print(device, ccb, CAM_ESF_ALL,
5458 					CAM_EPF_ALL, stderr);
5459 		retval = 1;
5460 		goto get_print_cts_bailout;
5461 	}
5462 
5463 	if (quiet == 0)
5464 		cts_print(device, &ccb->cts);
5465 
5466 	if (cts != NULL)
5467 		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5468 
5469 get_print_cts_bailout:
5470 
5471 	cam_freeccb(ccb);
5472 
5473 	return(retval);
5474 }
5475 
5476 static int
5477 ratecontrol(struct cam_device *device, int retry_count, int timeout,
5478 	    int argc, char **argv, char *combinedopt)
5479 {
5480 	int c;
5481 	union ccb *ccb;
5482 	int user_settings = 0;
5483 	int retval = 0;
5484 	int disc_enable = -1, tag_enable = -1;
5485 	int mode = -1;
5486 	int offset = -1;
5487 	double syncrate = -1;
5488 	int bus_width = -1;
5489 	int quiet = 0;
5490 	int change_settings = 0, send_tur = 0;
5491 	struct ccb_pathinq cpi;
5492 
5493 	ccb = cam_getccb(device);
5494 	if (ccb == NULL) {
5495 		warnx("ratecontrol: error allocating ccb");
5496 		return(1);
5497 	}
5498 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5499 		switch(c){
5500 		case 'a':
5501 			send_tur = 1;
5502 			break;
5503 		case 'c':
5504 			user_settings = 0;
5505 			break;
5506 		case 'D':
5507 			if (strncasecmp(optarg, "enable", 6) == 0)
5508 				disc_enable = 1;
5509 			else if (strncasecmp(optarg, "disable", 7) == 0)
5510 				disc_enable = 0;
5511 			else {
5512 				warnx("-D argument \"%s\" is unknown", optarg);
5513 				retval = 1;
5514 				goto ratecontrol_bailout;
5515 			}
5516 			change_settings = 1;
5517 			break;
5518 		case 'M':
5519 			mode = ata_string2mode(optarg);
5520 			if (mode < 0) {
5521 				warnx("unknown mode '%s'", optarg);
5522 				retval = 1;
5523 				goto ratecontrol_bailout;
5524 			}
5525 			change_settings = 1;
5526 			break;
5527 		case 'O':
5528 			offset = strtol(optarg, NULL, 0);
5529 			if (offset < 0) {
5530 				warnx("offset value %d is < 0", offset);
5531 				retval = 1;
5532 				goto ratecontrol_bailout;
5533 			}
5534 			change_settings = 1;
5535 			break;
5536 		case 'q':
5537 			quiet++;
5538 			break;
5539 		case 'R':
5540 			syncrate = atof(optarg);
5541 			if (syncrate < 0) {
5542 				warnx("sync rate %f is < 0", syncrate);
5543 				retval = 1;
5544 				goto ratecontrol_bailout;
5545 			}
5546 			change_settings = 1;
5547 			break;
5548 		case 'T':
5549 			if (strncasecmp(optarg, "enable", 6) == 0)
5550 				tag_enable = 1;
5551 			else if (strncasecmp(optarg, "disable", 7) == 0)
5552 				tag_enable = 0;
5553 			else {
5554 				warnx("-T argument \"%s\" is unknown", optarg);
5555 				retval = 1;
5556 				goto ratecontrol_bailout;
5557 			}
5558 			change_settings = 1;
5559 			break;
5560 		case 'U':
5561 			user_settings = 1;
5562 			break;
5563 		case 'W':
5564 			bus_width = strtol(optarg, NULL, 0);
5565 			if (bus_width < 0) {
5566 				warnx("bus width %d is < 0", bus_width);
5567 				retval = 1;
5568 				goto ratecontrol_bailout;
5569 			}
5570 			change_settings = 1;
5571 			break;
5572 		default:
5573 			break;
5574 		}
5575 	}
5576 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
5577 	/*
5578 	 * Grab path inquiry information, so we can determine whether
5579 	 * or not the initiator is capable of the things that the user
5580 	 * requests.
5581 	 */
5582 	ccb->ccb_h.func_code = XPT_PATH_INQ;
5583 	if (cam_send_ccb(device, ccb) < 0) {
5584 		perror("error sending XPT_PATH_INQ CCB");
5585 		if (arglist & CAM_ARG_VERBOSE) {
5586 			cam_error_print(device, ccb, CAM_ESF_ALL,
5587 					CAM_EPF_ALL, stderr);
5588 		}
5589 		retval = 1;
5590 		goto ratecontrol_bailout;
5591 	}
5592 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5593 		warnx("XPT_PATH_INQ CCB failed");
5594 		if (arglist & CAM_ARG_VERBOSE) {
5595 			cam_error_print(device, ccb, CAM_ESF_ALL,
5596 					CAM_EPF_ALL, stderr);
5597 		}
5598 		retval = 1;
5599 		goto ratecontrol_bailout;
5600 	}
5601 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5602 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5603 	if (quiet == 0) {
5604 		fprintf(stdout, "%s parameters:\n",
5605 		    user_settings ? "User" : "Current");
5606 	}
5607 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5608 	if (retval != 0)
5609 		goto ratecontrol_bailout;
5610 
5611 	if (arglist & CAM_ARG_VERBOSE)
5612 		cpi_print(&cpi);
5613 
5614 	if (change_settings) {
5615 		int didsettings = 0;
5616 		struct ccb_trans_settings_spi *spi = NULL;
5617 		struct ccb_trans_settings_pata *pata = NULL;
5618 		struct ccb_trans_settings_sata *sata = NULL;
5619 		struct ccb_trans_settings_ata *ata = NULL;
5620 		struct ccb_trans_settings_scsi *scsi = NULL;
5621 
5622 		if (ccb->cts.transport == XPORT_SPI)
5623 			spi = &ccb->cts.xport_specific.spi;
5624 		if (ccb->cts.transport == XPORT_ATA)
5625 			pata = &ccb->cts.xport_specific.ata;
5626 		if (ccb->cts.transport == XPORT_SATA)
5627 			sata = &ccb->cts.xport_specific.sata;
5628 		if (ccb->cts.protocol == PROTO_ATA)
5629 			ata = &ccb->cts.proto_specific.ata;
5630 		if (ccb->cts.protocol == PROTO_SCSI)
5631 			scsi = &ccb->cts.proto_specific.scsi;
5632 		ccb->cts.xport_specific.valid = 0;
5633 		ccb->cts.proto_specific.valid = 0;
5634 		if (spi && disc_enable != -1) {
5635 			spi->valid |= CTS_SPI_VALID_DISC;
5636 			if (disc_enable == 0)
5637 				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5638 			else
5639 				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5640 			didsettings++;
5641 		}
5642 		if (tag_enable != -1) {
5643 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5644 				warnx("HBA does not support tagged queueing, "
5645 				      "so you cannot modify tag settings");
5646 				retval = 1;
5647 				goto ratecontrol_bailout;
5648 			}
5649 			if (ata) {
5650 				ata->valid |= CTS_SCSI_VALID_TQ;
5651 				if (tag_enable == 0)
5652 					ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5653 				else
5654 					ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5655 				didsettings++;
5656 			} else if (scsi) {
5657 				scsi->valid |= CTS_SCSI_VALID_TQ;
5658 				if (tag_enable == 0)
5659 					scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5660 				else
5661 					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5662 				didsettings++;
5663 			}
5664 		}
5665 		if (spi && offset != -1) {
5666 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5667 				warnx("HBA is not capable of changing offset");
5668 				retval = 1;
5669 				goto ratecontrol_bailout;
5670 			}
5671 			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5672 			spi->sync_offset = offset;
5673 			didsettings++;
5674 		}
5675 		if (spi && syncrate != -1) {
5676 			int prelim_sync_period;
5677 
5678 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5679 				warnx("HBA is not capable of changing "
5680 				      "transfer rates");
5681 				retval = 1;
5682 				goto ratecontrol_bailout;
5683 			}
5684 			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5685 			/*
5686 			 * The sync rate the user gives us is in MHz.
5687 			 * We need to translate it into KHz for this
5688 			 * calculation.
5689 			 */
5690 			syncrate *= 1000;
5691 			/*
5692 			 * Next, we calculate a "preliminary" sync period
5693 			 * in tenths of a nanosecond.
5694 			 */
5695 			if (syncrate == 0)
5696 				prelim_sync_period = 0;
5697 			else
5698 				prelim_sync_period = 10000000 / syncrate;
5699 			spi->sync_period =
5700 				scsi_calc_syncparam(prelim_sync_period);
5701 			didsettings++;
5702 		}
5703 		if (sata && syncrate != -1) {
5704 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5705 				warnx("HBA is not capable of changing "
5706 				      "transfer rates");
5707 				retval = 1;
5708 				goto ratecontrol_bailout;
5709 			}
5710 			if  (!user_settings) {
5711 				warnx("You can modify only user rate "
5712 				    "settings for SATA");
5713 				retval = 1;
5714 				goto ratecontrol_bailout;
5715 			}
5716 			sata->revision = ata_speed2revision(syncrate * 100);
5717 			if (sata->revision < 0) {
5718 				warnx("Invalid rate %f", syncrate);
5719 				retval = 1;
5720 				goto ratecontrol_bailout;
5721 			}
5722 			sata->valid |= CTS_SATA_VALID_REVISION;
5723 			didsettings++;
5724 		}
5725 		if ((pata || sata) && mode != -1) {
5726 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5727 				warnx("HBA is not capable of changing "
5728 				      "transfer rates");
5729 				retval = 1;
5730 				goto ratecontrol_bailout;
5731 			}
5732 			if  (!user_settings) {
5733 				warnx("You can modify only user mode "
5734 				    "settings for ATA/SATA");
5735 				retval = 1;
5736 				goto ratecontrol_bailout;
5737 			}
5738 			if (pata) {
5739 				pata->mode = mode;
5740 				pata->valid |= CTS_ATA_VALID_MODE;
5741 			} else {
5742 				sata->mode = mode;
5743 				sata->valid |= CTS_SATA_VALID_MODE;
5744 			}
5745 			didsettings++;
5746 		}
5747 		/*
5748 		 * The bus_width argument goes like this:
5749 		 * 0 == 8 bit
5750 		 * 1 == 16 bit
5751 		 * 2 == 32 bit
5752 		 * Therefore, if you shift the number of bits given on the
5753 		 * command line right by 4, you should get the correct
5754 		 * number.
5755 		 */
5756 		if (spi && bus_width != -1) {
5757 			/*
5758 			 * We might as well validate things here with a
5759 			 * decipherable error message, rather than what
5760 			 * will probably be an indecipherable error message
5761 			 * by the time it gets back to us.
5762 			 */
5763 			if ((bus_width == 16)
5764 			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5765 				warnx("HBA does not support 16 bit bus width");
5766 				retval = 1;
5767 				goto ratecontrol_bailout;
5768 			} else if ((bus_width == 32)
5769 				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5770 				warnx("HBA does not support 32 bit bus width");
5771 				retval = 1;
5772 				goto ratecontrol_bailout;
5773 			} else if ((bus_width != 8)
5774 				&& (bus_width != 16)
5775 				&& (bus_width != 32)) {
5776 				warnx("Invalid bus width %d", bus_width);
5777 				retval = 1;
5778 				goto ratecontrol_bailout;
5779 			}
5780 			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5781 			spi->bus_width = bus_width >> 4;
5782 			didsettings++;
5783 		}
5784 		if  (didsettings == 0) {
5785 			goto ratecontrol_bailout;
5786 		}
5787 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5788 		if (cam_send_ccb(device, ccb) < 0) {
5789 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5790 			if (arglist & CAM_ARG_VERBOSE) {
5791 				cam_error_print(device, ccb, CAM_ESF_ALL,
5792 						CAM_EPF_ALL, stderr);
5793 			}
5794 			retval = 1;
5795 			goto ratecontrol_bailout;
5796 		}
5797 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5798 			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5799 			if (arglist & CAM_ARG_VERBOSE) {
5800 				cam_error_print(device, ccb, CAM_ESF_ALL,
5801 						CAM_EPF_ALL, stderr);
5802 			}
5803 			retval = 1;
5804 			goto ratecontrol_bailout;
5805 		}
5806 	}
5807 	if (send_tur) {
5808 		retval = testunitready(device, retry_count, timeout,
5809 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5810 		/*
5811 		 * If the TUR didn't succeed, just bail.
5812 		 */
5813 		if (retval != 0) {
5814 			if (quiet == 0)
5815 				fprintf(stderr, "Test Unit Ready failed\n");
5816 			goto ratecontrol_bailout;
5817 		}
5818 	}
5819 	if ((change_settings || send_tur) && !quiet &&
5820 	    (ccb->cts.transport == XPORT_ATA ||
5821 	     ccb->cts.transport == XPORT_SATA || send_tur)) {
5822 		fprintf(stdout, "New parameters:\n");
5823 		retval = get_print_cts(device, user_settings, 0, NULL);
5824 	}
5825 
5826 ratecontrol_bailout:
5827 	cam_freeccb(ccb);
5828 	return(retval);
5829 }
5830 
5831 static int
5832 scsiformat(struct cam_device *device, int argc, char **argv,
5833 	   char *combinedopt, int retry_count, int timeout)
5834 {
5835 	union ccb *ccb;
5836 	int c;
5837 	int ycount = 0, quiet = 0;
5838 	int error = 0, retval = 0;
5839 	int use_timeout = 10800 * 1000;
5840 	int immediate = 1;
5841 	struct format_defect_list_header fh;
5842 	u_int8_t *data_ptr = NULL;
5843 	u_int32_t dxfer_len = 0;
5844 	u_int8_t byte2 = 0;
5845 	int num_warnings = 0;
5846 	int reportonly = 0;
5847 
5848 	ccb = cam_getccb(device);
5849 
5850 	if (ccb == NULL) {
5851 		warnx("scsiformat: error allocating ccb");
5852 		return(1);
5853 	}
5854 
5855 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5856 
5857 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5858 		switch(c) {
5859 		case 'q':
5860 			quiet++;
5861 			break;
5862 		case 'r':
5863 			reportonly = 1;
5864 			break;
5865 		case 'w':
5866 			immediate = 0;
5867 			break;
5868 		case 'y':
5869 			ycount++;
5870 			break;
5871 		}
5872 	}
5873 
5874 	if (reportonly)
5875 		goto doreport;
5876 
5877 	if (quiet == 0) {
5878 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5879 			"following device:\n");
5880 
5881 		error = scsidoinquiry(device, argc, argv, combinedopt,
5882 				      retry_count, timeout);
5883 
5884 		if (error != 0) {
5885 			warnx("scsiformat: error sending inquiry");
5886 			goto scsiformat_bailout;
5887 		}
5888 	}
5889 
5890 	if (ycount == 0) {
5891 		if (!get_confirmation()) {
5892 			error = 1;
5893 			goto scsiformat_bailout;
5894 		}
5895 	}
5896 
5897 	if (timeout != 0)
5898 		use_timeout = timeout;
5899 
5900 	if (quiet == 0) {
5901 		fprintf(stdout, "Current format timeout is %d seconds\n",
5902 			use_timeout / 1000);
5903 	}
5904 
5905 	/*
5906 	 * If the user hasn't disabled questions and didn't specify a
5907 	 * timeout on the command line, ask them if they want the current
5908 	 * timeout.
5909 	 */
5910 	if ((ycount == 0)
5911 	 && (timeout == 0)) {
5912 		char str[1024];
5913 		int new_timeout = 0;
5914 
5915 		fprintf(stdout, "Enter new timeout in seconds or press\n"
5916 			"return to keep the current timeout [%d] ",
5917 			use_timeout / 1000);
5918 
5919 		if (fgets(str, sizeof(str), stdin) != NULL) {
5920 			if (str[0] != '\0')
5921 				new_timeout = atoi(str);
5922 		}
5923 
5924 		if (new_timeout != 0) {
5925 			use_timeout = new_timeout * 1000;
5926 			fprintf(stdout, "Using new timeout value %d\n",
5927 				use_timeout / 1000);
5928 		}
5929 	}
5930 
5931 	/*
5932 	 * Keep this outside the if block below to silence any unused
5933 	 * variable warnings.
5934 	 */
5935 	bzero(&fh, sizeof(fh));
5936 
5937 	/*
5938 	 * If we're in immediate mode, we've got to include the format
5939 	 * header
5940 	 */
5941 	if (immediate != 0) {
5942 		fh.byte2 = FU_DLH_IMMED;
5943 		data_ptr = (u_int8_t *)&fh;
5944 		dxfer_len = sizeof(fh);
5945 		byte2 = FU_FMT_DATA;
5946 	} else if (quiet == 0) {
5947 		fprintf(stdout, "Formatting...");
5948 		fflush(stdout);
5949 	}
5950 
5951 	scsi_format_unit(&ccb->csio,
5952 			 /* retries */ retry_count,
5953 			 /* cbfcnp */ NULL,
5954 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
5955 			 /* byte2 */ byte2,
5956 			 /* ileave */ 0,
5957 			 /* data_ptr */ data_ptr,
5958 			 /* dxfer_len */ dxfer_len,
5959 			 /* sense_len */ SSD_FULL_SIZE,
5960 			 /* timeout */ use_timeout);
5961 
5962 	/* Disable freezing the device queue */
5963 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5964 
5965 	if (arglist & CAM_ARG_ERR_RECOVER)
5966 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5967 
5968 	if (((retval = cam_send_ccb(device, ccb)) < 0)
5969 	 || ((immediate == 0)
5970 	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5971 		const char errstr[] = "error sending format command";
5972 
5973 		if (retval < 0)
5974 			warn(errstr);
5975 		else
5976 			warnx(errstr);
5977 
5978 		if (arglist & CAM_ARG_VERBOSE) {
5979 			cam_error_print(device, ccb, CAM_ESF_ALL,
5980 					CAM_EPF_ALL, stderr);
5981 		}
5982 		error = 1;
5983 		goto scsiformat_bailout;
5984 	}
5985 
5986 	/*
5987 	 * If we ran in non-immediate mode, we already checked for errors
5988 	 * above and printed out any necessary information.  If we're in
5989 	 * immediate mode, we need to loop through and get status
5990 	 * information periodically.
5991 	 */
5992 	if (immediate == 0) {
5993 		if (quiet == 0) {
5994 			fprintf(stdout, "Format Complete\n");
5995 		}
5996 		goto scsiformat_bailout;
5997 	}
5998 
5999 doreport:
6000 	do {
6001 		cam_status status;
6002 
6003 		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6004 
6005 		/*
6006 		 * There's really no need to do error recovery or
6007 		 * retries here, since we're just going to sit in a
6008 		 * loop and wait for the device to finish formatting.
6009 		 */
6010 		scsi_test_unit_ready(&ccb->csio,
6011 				     /* retries */ 0,
6012 				     /* cbfcnp */ NULL,
6013 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
6014 				     /* sense_len */ SSD_FULL_SIZE,
6015 				     /* timeout */ 5000);
6016 
6017 		/* Disable freezing the device queue */
6018 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6019 
6020 		retval = cam_send_ccb(device, ccb);
6021 
6022 		/*
6023 		 * If we get an error from the ioctl, bail out.  SCSI
6024 		 * errors are expected.
6025 		 */
6026 		if (retval < 0) {
6027 			warn("error sending CAMIOCOMMAND ioctl");
6028 			if (arglist & CAM_ARG_VERBOSE) {
6029 				cam_error_print(device, ccb, CAM_ESF_ALL,
6030 						CAM_EPF_ALL, stderr);
6031 			}
6032 			error = 1;
6033 			goto scsiformat_bailout;
6034 		}
6035 
6036 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
6037 
6038 		if ((status != CAM_REQ_CMP)
6039 		 && (status == CAM_SCSI_STATUS_ERROR)
6040 		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6041 			struct scsi_sense_data *sense;
6042 			int error_code, sense_key, asc, ascq;
6043 
6044 			sense = &ccb->csio.sense_data;
6045 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6046 			    ccb->csio.sense_resid, &error_code, &sense_key,
6047 			    &asc, &ascq, /*show_errors*/ 1);
6048 
6049 			/*
6050 			 * According to the SCSI-2 and SCSI-3 specs, a
6051 			 * drive that is in the middle of a format should
6052 			 * return NOT READY with an ASC of "logical unit
6053 			 * not ready, format in progress".  The sense key
6054 			 * specific bytes will then be a progress indicator.
6055 			 */
6056 			if ((sense_key == SSD_KEY_NOT_READY)
6057 			 && (asc == 0x04) && (ascq == 0x04)) {
6058 				uint8_t sks[3];
6059 
6060 				if ((scsi_get_sks(sense, ccb->csio.sense_len -
6061 				     ccb->csio.sense_resid, sks) == 0)
6062 				 && (quiet == 0)) {
6063 					int val;
6064 					u_int64_t percentage;
6065 
6066 					val = scsi_2btoul(&sks[1]);
6067 					percentage = 10000 * val;
6068 
6069 					fprintf(stdout,
6070 						"\rFormatting:  %ju.%02u %% "
6071 						"(%d/%d) done",
6072 						(uintmax_t)(percentage /
6073 						(0x10000 * 100)),
6074 						(unsigned)((percentage /
6075 						0x10000) % 100),
6076 						val, 0x10000);
6077 					fflush(stdout);
6078 				} else if ((quiet == 0)
6079 					&& (++num_warnings <= 1)) {
6080 					warnx("Unexpected SCSI Sense Key "
6081 					      "Specific value returned "
6082 					      "during format:");
6083 					scsi_sense_print(device, &ccb->csio,
6084 							 stderr);
6085 					warnx("Unable to print status "
6086 					      "information, but format will "
6087 					      "proceed.");
6088 					warnx("will exit when format is "
6089 					      "complete");
6090 				}
6091 				sleep(1);
6092 			} else {
6093 				warnx("Unexpected SCSI error during format");
6094 				cam_error_print(device, ccb, CAM_ESF_ALL,
6095 						CAM_EPF_ALL, stderr);
6096 				error = 1;
6097 				goto scsiformat_bailout;
6098 			}
6099 
6100 		} else if (status != CAM_REQ_CMP) {
6101 			warnx("Unexpected CAM status %#x", status);
6102 			if (arglist & CAM_ARG_VERBOSE)
6103 				cam_error_print(device, ccb, CAM_ESF_ALL,
6104 						CAM_EPF_ALL, stderr);
6105 			error = 1;
6106 			goto scsiformat_bailout;
6107 		}
6108 
6109 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6110 
6111 	if (quiet == 0)
6112 		fprintf(stdout, "\nFormat Complete\n");
6113 
6114 scsiformat_bailout:
6115 
6116 	cam_freeccb(ccb);
6117 
6118 	return(error);
6119 }
6120 
6121 static int
6122 scsisanitize(struct cam_device *device, int argc, char **argv,
6123 	     char *combinedopt, int retry_count, int timeout)
6124 {
6125 	union ccb *ccb;
6126 	u_int8_t action = 0;
6127 	int c;
6128 	int ycount = 0, quiet = 0;
6129 	int error = 0, retval = 0;
6130 	int use_timeout = 10800 * 1000;
6131 	int immediate = 1;
6132 	int invert = 0;
6133 	int passes = 0;
6134 	int ause = 0;
6135 	int fd = -1;
6136 	const char *pattern = NULL;
6137 	u_int8_t *data_ptr = NULL;
6138 	u_int32_t dxfer_len = 0;
6139 	u_int8_t byte2 = 0;
6140 	int num_warnings = 0;
6141 	int reportonly = 0;
6142 
6143 	ccb = cam_getccb(device);
6144 
6145 	if (ccb == NULL) {
6146 		warnx("scsisanitize: error allocating ccb");
6147 		return(1);
6148 	}
6149 
6150 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6151 
6152 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6153 		switch(c) {
6154 		case 'a':
6155 			if (strcasecmp(optarg, "overwrite") == 0)
6156 				action = SSZ_SERVICE_ACTION_OVERWRITE;
6157 			else if (strcasecmp(optarg, "block") == 0)
6158 				action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6159 			else if (strcasecmp(optarg, "crypto") == 0)
6160 				action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6161 			else if (strcasecmp(optarg, "exitfailure") == 0)
6162 				action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6163 			else {
6164 				warnx("invalid service operation \"%s\"",
6165 				      optarg);
6166 				error = 1;
6167 				goto scsisanitize_bailout;
6168 			}
6169 			break;
6170 		case 'c':
6171 			passes = strtol(optarg, NULL, 0);
6172 			if (passes < 1 || passes > 31) {
6173 				warnx("invalid passes value %d", passes);
6174 				error = 1;
6175 				goto scsisanitize_bailout;
6176 			}
6177 			break;
6178 		case 'I':
6179 			invert = 1;
6180 			break;
6181 		case 'P':
6182 			pattern = optarg;
6183 			break;
6184 		case 'q':
6185 			quiet++;
6186 			break;
6187 		case 'U':
6188 			ause = 1;
6189 			break;
6190 		case 'r':
6191 			reportonly = 1;
6192 			break;
6193 		case 'w':
6194 			immediate = 0;
6195 			break;
6196 		case 'y':
6197 			ycount++;
6198 			break;
6199 		}
6200 	}
6201 
6202 	if (reportonly)
6203 		goto doreport;
6204 
6205 	if (action == 0) {
6206 		warnx("an action is required");
6207 		error = 1;
6208 		goto scsisanitize_bailout;
6209 	} else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6210 		struct scsi_sanitize_parameter_list *pl;
6211 		struct stat sb;
6212 		ssize_t sz, amt;
6213 
6214 		if (pattern == NULL) {
6215 			warnx("overwrite action requires -P argument");
6216 			error = 1;
6217 			goto scsisanitize_bailout;
6218 		}
6219 		fd = open(pattern, O_RDONLY);
6220 		if (fd < 0) {
6221 			warn("cannot open pattern file %s", pattern);
6222 			error = 1;
6223 			goto scsisanitize_bailout;
6224 		}
6225 		if (fstat(fd, &sb) < 0) {
6226 			warn("cannot stat pattern file %s", pattern);
6227 			error = 1;
6228 			goto scsisanitize_bailout;
6229 		}
6230 		sz = sb.st_size;
6231 		if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6232 			warnx("pattern file size exceeds maximum value %d",
6233 			      SSZPL_MAX_PATTERN_LENGTH);
6234 			error = 1;
6235 			goto scsisanitize_bailout;
6236 		}
6237 		dxfer_len = sizeof(*pl) + sz;
6238 		data_ptr = calloc(1, dxfer_len);
6239 		if (data_ptr == NULL) {
6240 			warnx("cannot allocate parameter list buffer");
6241 			error = 1;
6242 			goto scsisanitize_bailout;
6243 		}
6244 
6245 		amt = read(fd, data_ptr + sizeof(*pl), sz);
6246 		if (amt < 0) {
6247 			warn("cannot read pattern file");
6248 			error = 1;
6249 			goto scsisanitize_bailout;
6250 		} else if (amt != sz) {
6251 			warnx("short pattern file read");
6252 			error = 1;
6253 			goto scsisanitize_bailout;
6254 		}
6255 
6256 		pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6257 		if (passes == 0)
6258 			pl->byte1 = 1;
6259 		else
6260 			pl->byte1 = passes;
6261 		if (invert != 0)
6262 			pl->byte1 |= SSZPL_INVERT;
6263 		scsi_ulto2b(sz, pl->length);
6264 	} else {
6265 		const char *arg;
6266 
6267 		if (passes != 0)
6268 			arg = "-c";
6269 		else if (invert != 0)
6270 			arg = "-I";
6271 		else if (pattern != NULL)
6272 			arg = "-P";
6273 		else
6274 			arg = NULL;
6275 		if (arg != NULL) {
6276 			warnx("%s argument only valid with overwrite "
6277 			      "operation", arg);
6278 			error = 1;
6279 			goto scsisanitize_bailout;
6280 		}
6281 	}
6282 
6283 	if (quiet == 0) {
6284 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6285 			"following device:\n");
6286 
6287 		error = scsidoinquiry(device, argc, argv, combinedopt,
6288 				      retry_count, timeout);
6289 
6290 		if (error != 0) {
6291 			warnx("scsisanitize: error sending inquiry");
6292 			goto scsisanitize_bailout;
6293 		}
6294 	}
6295 
6296 	if (ycount == 0) {
6297 		if (!get_confirmation()) {
6298 			error = 1;
6299 			goto scsisanitize_bailout;
6300 		}
6301 	}
6302 
6303 	if (timeout != 0)
6304 		use_timeout = timeout;
6305 
6306 	if (quiet == 0) {
6307 		fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6308 			use_timeout / 1000);
6309 	}
6310 
6311 	/*
6312 	 * If the user hasn't disabled questions and didn't specify a
6313 	 * timeout on the command line, ask them if they want the current
6314 	 * timeout.
6315 	 */
6316 	if ((ycount == 0)
6317 	 && (timeout == 0)) {
6318 		char str[1024];
6319 		int new_timeout = 0;
6320 
6321 		fprintf(stdout, "Enter new timeout in seconds or press\n"
6322 			"return to keep the current timeout [%d] ",
6323 			use_timeout / 1000);
6324 
6325 		if (fgets(str, sizeof(str), stdin) != NULL) {
6326 			if (str[0] != '\0')
6327 				new_timeout = atoi(str);
6328 		}
6329 
6330 		if (new_timeout != 0) {
6331 			use_timeout = new_timeout * 1000;
6332 			fprintf(stdout, "Using new timeout value %d\n",
6333 				use_timeout / 1000);
6334 		}
6335 	}
6336 
6337 	byte2 = action;
6338 	if (ause != 0)
6339 		byte2 |= SSZ_UNRESTRICTED_EXIT;
6340 	if (immediate != 0)
6341 		byte2 |= SSZ_IMMED;
6342 
6343 	scsi_sanitize(&ccb->csio,
6344 		      /* retries */ retry_count,
6345 		      /* cbfcnp */ NULL,
6346 		      /* tag_action */ MSG_SIMPLE_Q_TAG,
6347 		      /* byte2 */ byte2,
6348 		      /* control */ 0,
6349 		      /* data_ptr */ data_ptr,
6350 		      /* dxfer_len */ dxfer_len,
6351 		      /* sense_len */ SSD_FULL_SIZE,
6352 		      /* timeout */ use_timeout);
6353 
6354 	/* Disable freezing the device queue */
6355 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6356 
6357 	if (arglist & CAM_ARG_ERR_RECOVER)
6358 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6359 
6360 	if (cam_send_ccb(device, ccb) < 0) {
6361 		warn("error sending sanitize command");
6362 		error = 1;
6363 		goto scsisanitize_bailout;
6364 	}
6365 
6366 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6367 		struct scsi_sense_data *sense;
6368 		int error_code, sense_key, asc, ascq;
6369 
6370 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6371 		    CAM_SCSI_STATUS_ERROR) {
6372 			sense = &ccb->csio.sense_data;
6373 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6374 			    ccb->csio.sense_resid, &error_code, &sense_key,
6375 			    &asc, &ascq, /*show_errors*/ 1);
6376 
6377 			if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6378 			    asc == 0x20 && ascq == 0x00)
6379 				warnx("sanitize is not supported by "
6380 				      "this device");
6381 			else
6382 				warnx("error sanitizing this device");
6383 		} else
6384 			warnx("error sanitizing this device");
6385 
6386 		if (arglist & CAM_ARG_VERBOSE) {
6387 			cam_error_print(device, ccb, CAM_ESF_ALL,
6388 					CAM_EPF_ALL, stderr);
6389 		}
6390 		error = 1;
6391 		goto scsisanitize_bailout;
6392 	}
6393 
6394 	/*
6395 	 * If we ran in non-immediate mode, we already checked for errors
6396 	 * above and printed out any necessary information.  If we're in
6397 	 * immediate mode, we need to loop through and get status
6398 	 * information periodically.
6399 	 */
6400 	if (immediate == 0) {
6401 		if (quiet == 0) {
6402 			fprintf(stdout, "Sanitize Complete\n");
6403 		}
6404 		goto scsisanitize_bailout;
6405 	}
6406 
6407 doreport:
6408 	do {
6409 		cam_status status;
6410 
6411 		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6412 
6413 		/*
6414 		 * There's really no need to do error recovery or
6415 		 * retries here, since we're just going to sit in a
6416 		 * loop and wait for the device to finish sanitizing.
6417 		 */
6418 		scsi_test_unit_ready(&ccb->csio,
6419 				     /* retries */ 0,
6420 				     /* cbfcnp */ NULL,
6421 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
6422 				     /* sense_len */ SSD_FULL_SIZE,
6423 				     /* timeout */ 5000);
6424 
6425 		/* Disable freezing the device queue */
6426 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6427 
6428 		retval = cam_send_ccb(device, ccb);
6429 
6430 		/*
6431 		 * If we get an error from the ioctl, bail out.  SCSI
6432 		 * errors are expected.
6433 		 */
6434 		if (retval < 0) {
6435 			warn("error sending CAMIOCOMMAND ioctl");
6436 			if (arglist & CAM_ARG_VERBOSE) {
6437 				cam_error_print(device, ccb, CAM_ESF_ALL,
6438 						CAM_EPF_ALL, stderr);
6439 			}
6440 			error = 1;
6441 			goto scsisanitize_bailout;
6442 		}
6443 
6444 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
6445 
6446 		if ((status != CAM_REQ_CMP)
6447 		 && (status == CAM_SCSI_STATUS_ERROR)
6448 		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6449 			struct scsi_sense_data *sense;
6450 			int error_code, sense_key, asc, ascq;
6451 
6452 			sense = &ccb->csio.sense_data;
6453 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6454 			    ccb->csio.sense_resid, &error_code, &sense_key,
6455 			    &asc, &ascq, /*show_errors*/ 1);
6456 
6457 			/*
6458 			 * According to the SCSI-3 spec, a drive that is in the
6459 			 * middle of a sanitize should return NOT READY with an
6460 			 * ASC of "logical unit not ready, sanitize in
6461 			 * progress". The sense key specific bytes will then
6462 			 * be a progress indicator.
6463 			 */
6464 			if ((sense_key == SSD_KEY_NOT_READY)
6465 			 && (asc == 0x04) && (ascq == 0x1b)) {
6466 				uint8_t sks[3];
6467 
6468 				if ((scsi_get_sks(sense, ccb->csio.sense_len -
6469 				     ccb->csio.sense_resid, sks) == 0)
6470 				 && (quiet == 0)) {
6471 					int val;
6472 					u_int64_t percentage;
6473 
6474 					val = scsi_2btoul(&sks[1]);
6475 					percentage = 10000 * val;
6476 
6477 					fprintf(stdout,
6478 						"\rSanitizing:  %ju.%02u %% "
6479 						"(%d/%d) done",
6480 						(uintmax_t)(percentage /
6481 						(0x10000 * 100)),
6482 						(unsigned)((percentage /
6483 						0x10000) % 100),
6484 						val, 0x10000);
6485 					fflush(stdout);
6486 				} else if ((quiet == 0)
6487 					&& (++num_warnings <= 1)) {
6488 					warnx("Unexpected SCSI Sense Key "
6489 					      "Specific value returned "
6490 					      "during sanitize:");
6491 					scsi_sense_print(device, &ccb->csio,
6492 							 stderr);
6493 					warnx("Unable to print status "
6494 					      "information, but sanitze will "
6495 					      "proceed.");
6496 					warnx("will exit when sanitize is "
6497 					      "complete");
6498 				}
6499 				sleep(1);
6500 			} else {
6501 				warnx("Unexpected SCSI error during sanitize");
6502 				cam_error_print(device, ccb, CAM_ESF_ALL,
6503 						CAM_EPF_ALL, stderr);
6504 				error = 1;
6505 				goto scsisanitize_bailout;
6506 			}
6507 
6508 		} else if (status != CAM_REQ_CMP) {
6509 			warnx("Unexpected CAM status %#x", status);
6510 			if (arglist & CAM_ARG_VERBOSE)
6511 				cam_error_print(device, ccb, CAM_ESF_ALL,
6512 						CAM_EPF_ALL, stderr);
6513 			error = 1;
6514 			goto scsisanitize_bailout;
6515 		}
6516 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6517 
6518 	if (quiet == 0)
6519 		fprintf(stdout, "\nSanitize Complete\n");
6520 
6521 scsisanitize_bailout:
6522 	if (fd >= 0)
6523 		close(fd);
6524 	if (data_ptr != NULL)
6525 		free(data_ptr);
6526 	cam_freeccb(ccb);
6527 
6528 	return(error);
6529 }
6530 
6531 static int
6532 scsireportluns(struct cam_device *device, int argc, char **argv,
6533 	       char *combinedopt, int retry_count, int timeout)
6534 {
6535 	union ccb *ccb;
6536 	int c, countonly, lunsonly;
6537 	struct scsi_report_luns_data *lundata;
6538 	int alloc_len;
6539 	uint8_t report_type;
6540 	uint32_t list_len, i, j;
6541 	int retval;
6542 
6543 	retval = 0;
6544 	lundata = NULL;
6545 	report_type = RPL_REPORT_DEFAULT;
6546 	ccb = cam_getccb(device);
6547 
6548 	if (ccb == NULL) {
6549 		warnx("%s: error allocating ccb", __func__);
6550 		return (1);
6551 	}
6552 
6553 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6554 
6555 	countonly = 0;
6556 	lunsonly = 0;
6557 
6558 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6559 		switch (c) {
6560 		case 'c':
6561 			countonly++;
6562 			break;
6563 		case 'l':
6564 			lunsonly++;
6565 			break;
6566 		case 'r':
6567 			if (strcasecmp(optarg, "default") == 0)
6568 				report_type = RPL_REPORT_DEFAULT;
6569 			else if (strcasecmp(optarg, "wellknown") == 0)
6570 				report_type = RPL_REPORT_WELLKNOWN;
6571 			else if (strcasecmp(optarg, "all") == 0)
6572 				report_type = RPL_REPORT_ALL;
6573 			else {
6574 				warnx("%s: invalid report type \"%s\"",
6575 				      __func__, optarg);
6576 				retval = 1;
6577 				goto bailout;
6578 			}
6579 			break;
6580 		default:
6581 			break;
6582 		}
6583 	}
6584 
6585 	if ((countonly != 0)
6586 	 && (lunsonly != 0)) {
6587 		warnx("%s: you can only specify one of -c or -l", __func__);
6588 		retval = 1;
6589 		goto bailout;
6590 	}
6591 	/*
6592 	 * According to SPC-4, the allocation length must be at least 16
6593 	 * bytes -- enough for the header and one LUN.
6594 	 */
6595 	alloc_len = sizeof(*lundata) + 8;
6596 
6597 retry:
6598 
6599 	lundata = malloc(alloc_len);
6600 
6601 	if (lundata == NULL) {
6602 		warn("%s: error mallocing %d bytes", __func__, alloc_len);
6603 		retval = 1;
6604 		goto bailout;
6605 	}
6606 
6607 	scsi_report_luns(&ccb->csio,
6608 			 /*retries*/ retry_count,
6609 			 /*cbfcnp*/ NULL,
6610 			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6611 			 /*select_report*/ report_type,
6612 			 /*rpl_buf*/ lundata,
6613 			 /*alloc_len*/ alloc_len,
6614 			 /*sense_len*/ SSD_FULL_SIZE,
6615 			 /*timeout*/ timeout ? timeout : 5000);
6616 
6617 	/* Disable freezing the device queue */
6618 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6619 
6620 	if (arglist & CAM_ARG_ERR_RECOVER)
6621 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6622 
6623 	if (cam_send_ccb(device, ccb) < 0) {
6624 		warn("error sending REPORT LUNS command");
6625 
6626 		if (arglist & CAM_ARG_VERBOSE)
6627 			cam_error_print(device, ccb, CAM_ESF_ALL,
6628 					CAM_EPF_ALL, stderr);
6629 
6630 		retval = 1;
6631 		goto bailout;
6632 	}
6633 
6634 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6635 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6636 		retval = 1;
6637 		goto bailout;
6638 	}
6639 
6640 
6641 	list_len = scsi_4btoul(lundata->length);
6642 
6643 	/*
6644 	 * If we need to list the LUNs, and our allocation
6645 	 * length was too short, reallocate and retry.
6646 	 */
6647 	if ((countonly == 0)
6648 	 && (list_len > (alloc_len - sizeof(*lundata)))) {
6649 		alloc_len = list_len + sizeof(*lundata);
6650 		free(lundata);
6651 		goto retry;
6652 	}
6653 
6654 	if (lunsonly == 0)
6655 		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6656 			((list_len / 8) > 1) ? "s" : "");
6657 
6658 	if (countonly != 0)
6659 		goto bailout;
6660 
6661 	for (i = 0; i < (list_len / 8); i++) {
6662 		int no_more;
6663 
6664 		no_more = 0;
6665 		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6666 			if (j != 0)
6667 				fprintf(stdout, ",");
6668 			switch (lundata->luns[i].lundata[j] &
6669 				RPL_LUNDATA_ATYP_MASK) {
6670 			case RPL_LUNDATA_ATYP_PERIPH:
6671 				if ((lundata->luns[i].lundata[j] &
6672 				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6673 					fprintf(stdout, "%d:",
6674 						lundata->luns[i].lundata[j] &
6675 						RPL_LUNDATA_PERIPH_BUS_MASK);
6676 				else if ((j == 0)
6677 				      && ((lundata->luns[i].lundata[j+2] &
6678 					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6679 					no_more = 1;
6680 
6681 				fprintf(stdout, "%d",
6682 					lundata->luns[i].lundata[j+1]);
6683 				break;
6684 			case RPL_LUNDATA_ATYP_FLAT: {
6685 				uint8_t tmplun[2];
6686 				tmplun[0] = lundata->luns[i].lundata[j] &
6687 					RPL_LUNDATA_FLAT_LUN_MASK;
6688 				tmplun[1] = lundata->luns[i].lundata[j+1];
6689 
6690 				fprintf(stdout, "%d", scsi_2btoul(tmplun));
6691 				no_more = 1;
6692 				break;
6693 			}
6694 			case RPL_LUNDATA_ATYP_LUN:
6695 				fprintf(stdout, "%d:%d:%d",
6696 					(lundata->luns[i].lundata[j+1] &
6697 					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6698 					lundata->luns[i].lundata[j] &
6699 					RPL_LUNDATA_LUN_TARG_MASK,
6700 					lundata->luns[i].lundata[j+1] &
6701 					RPL_LUNDATA_LUN_LUN_MASK);
6702 				break;
6703 			case RPL_LUNDATA_ATYP_EXTLUN: {
6704 				int field_len_code, eam_code;
6705 
6706 				eam_code = lundata->luns[i].lundata[j] &
6707 					RPL_LUNDATA_EXT_EAM_MASK;
6708 				field_len_code = (lundata->luns[i].lundata[j] &
6709 					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6710 
6711 				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6712 				 && (field_len_code == 0x00)) {
6713 					fprintf(stdout, "%d",
6714 						lundata->luns[i].lundata[j+1]);
6715 				} else if ((eam_code ==
6716 					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6717 					&& (field_len_code == 0x03)) {
6718 					uint8_t tmp_lun[8];
6719 
6720 					/*
6721 					 * This format takes up all 8 bytes.
6722 					 * If we aren't starting at offset 0,
6723 					 * that's a bug.
6724 					 */
6725 					if (j != 0) {
6726 						fprintf(stdout, "Invalid "
6727 							"offset %d for "
6728 							"Extended LUN not "
6729 							"specified format", j);
6730 						no_more = 1;
6731 						break;
6732 					}
6733 					bzero(tmp_lun, sizeof(tmp_lun));
6734 					bcopy(&lundata->luns[i].lundata[j+1],
6735 					      &tmp_lun[1], sizeof(tmp_lun) - 1);
6736 					fprintf(stdout, "%#jx",
6737 					       (intmax_t)scsi_8btou64(tmp_lun));
6738 					no_more = 1;
6739 				} else {
6740 					fprintf(stderr, "Unknown Extended LUN"
6741 						"Address method %#x, length "
6742 						"code %#x", eam_code,
6743 						field_len_code);
6744 					no_more = 1;
6745 				}
6746 				break;
6747 			}
6748 			default:
6749 				fprintf(stderr, "Unknown LUN address method "
6750 					"%#x\n", lundata->luns[i].lundata[0] &
6751 					RPL_LUNDATA_ATYP_MASK);
6752 				break;
6753 			}
6754 			/*
6755 			 * For the flat addressing method, there are no
6756 			 * other levels after it.
6757 			 */
6758 			if (no_more != 0)
6759 				break;
6760 		}
6761 		fprintf(stdout, "\n");
6762 	}
6763 
6764 bailout:
6765 
6766 	cam_freeccb(ccb);
6767 
6768 	free(lundata);
6769 
6770 	return (retval);
6771 }
6772 
6773 static int
6774 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6775 		 char *combinedopt, int retry_count, int timeout)
6776 {
6777 	union ccb *ccb;
6778 	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6779 	struct scsi_read_capacity_data rcap;
6780 	struct scsi_read_capacity_data_long rcaplong;
6781 	uint64_t maxsector;
6782 	uint32_t block_len;
6783 	int retval;
6784 	int c;
6785 
6786 	blocksizeonly = 0;
6787 	humanize = 0;
6788 	numblocks = 0;
6789 	quiet = 0;
6790 	sizeonly = 0;
6791 	baseten = 0;
6792 	retval = 0;
6793 
6794 	ccb = cam_getccb(device);
6795 
6796 	if (ccb == NULL) {
6797 		warnx("%s: error allocating ccb", __func__);
6798 		return (1);
6799 	}
6800 
6801 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6802 
6803 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6804 		switch (c) {
6805 		case 'b':
6806 			blocksizeonly++;
6807 			break;
6808 		case 'h':
6809 			humanize++;
6810 			baseten = 0;
6811 			break;
6812 		case 'H':
6813 			humanize++;
6814 			baseten++;
6815 			break;
6816 		case 'N':
6817 			numblocks++;
6818 			break;
6819 		case 'q':
6820 			quiet++;
6821 			break;
6822 		case 's':
6823 			sizeonly++;
6824 			break;
6825 		default:
6826 			break;
6827 		}
6828 	}
6829 
6830 	if ((blocksizeonly != 0)
6831 	 && (numblocks != 0)) {
6832 		warnx("%s: you can only specify one of -b or -N", __func__);
6833 		retval = 1;
6834 		goto bailout;
6835 	}
6836 
6837 	if ((blocksizeonly != 0)
6838 	 && (sizeonly != 0)) {
6839 		warnx("%s: you can only specify one of -b or -s", __func__);
6840 		retval = 1;
6841 		goto bailout;
6842 	}
6843 
6844 	if ((humanize != 0)
6845 	 && (quiet != 0)) {
6846 		warnx("%s: you can only specify one of -h/-H or -q", __func__);
6847 		retval = 1;
6848 		goto bailout;
6849 	}
6850 
6851 	if ((humanize != 0)
6852 	 && (blocksizeonly != 0)) {
6853 		warnx("%s: you can only specify one of -h/-H or -b", __func__);
6854 		retval = 1;
6855 		goto bailout;
6856 	}
6857 
6858 	scsi_read_capacity(&ccb->csio,
6859 			   /*retries*/ retry_count,
6860 			   /*cbfcnp*/ NULL,
6861 			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
6862 			   &rcap,
6863 			   SSD_FULL_SIZE,
6864 			   /*timeout*/ timeout ? timeout : 5000);
6865 
6866 	/* Disable freezing the device queue */
6867 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6868 
6869 	if (arglist & CAM_ARG_ERR_RECOVER)
6870 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6871 
6872 	if (cam_send_ccb(device, ccb) < 0) {
6873 		warn("error sending READ CAPACITY command");
6874 
6875 		if (arglist & CAM_ARG_VERBOSE)
6876 			cam_error_print(device, ccb, CAM_ESF_ALL,
6877 					CAM_EPF_ALL, stderr);
6878 
6879 		retval = 1;
6880 		goto bailout;
6881 	}
6882 
6883 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6884 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6885 		retval = 1;
6886 		goto bailout;
6887 	}
6888 
6889 	maxsector = scsi_4btoul(rcap.addr);
6890 	block_len = scsi_4btoul(rcap.length);
6891 
6892 	/*
6893 	 * A last block of 2^32-1 means that the true capacity is over 2TB,
6894 	 * and we need to issue the long READ CAPACITY to get the real
6895 	 * capacity.  Otherwise, we're all set.
6896 	 */
6897 	if (maxsector != 0xffffffff)
6898 		goto do_print;
6899 
6900 	scsi_read_capacity_16(&ccb->csio,
6901 			      /*retries*/ retry_count,
6902 			      /*cbfcnp*/ NULL,
6903 			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
6904 			      /*lba*/ 0,
6905 			      /*reladdr*/ 0,
6906 			      /*pmi*/ 0,
6907 			      /*rcap_buf*/ (uint8_t *)&rcaplong,
6908 			      /*rcap_buf_len*/ sizeof(rcaplong),
6909 			      /*sense_len*/ SSD_FULL_SIZE,
6910 			      /*timeout*/ timeout ? timeout : 5000);
6911 
6912 	/* Disable freezing the device queue */
6913 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6914 
6915 	if (arglist & CAM_ARG_ERR_RECOVER)
6916 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6917 
6918 	if (cam_send_ccb(device, ccb) < 0) {
6919 		warn("error sending READ CAPACITY (16) command");
6920 
6921 		if (arglist & CAM_ARG_VERBOSE)
6922 			cam_error_print(device, ccb, CAM_ESF_ALL,
6923 					CAM_EPF_ALL, stderr);
6924 
6925 		retval = 1;
6926 		goto bailout;
6927 	}
6928 
6929 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6930 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6931 		retval = 1;
6932 		goto bailout;
6933 	}
6934 
6935 	maxsector = scsi_8btou64(rcaplong.addr);
6936 	block_len = scsi_4btoul(rcaplong.length);
6937 
6938 do_print:
6939 	if (blocksizeonly == 0) {
6940 		/*
6941 		 * Humanize implies !quiet, and also implies numblocks.
6942 		 */
6943 		if (humanize != 0) {
6944 			char tmpstr[6];
6945 			int64_t tmpbytes;
6946 			int ret;
6947 
6948 			tmpbytes = (maxsector + 1) * block_len;
6949 			ret = humanize_number(tmpstr, sizeof(tmpstr),
6950 					      tmpbytes, "", HN_AUTOSCALE,
6951 					      HN_B | HN_DECIMAL |
6952 					      ((baseten != 0) ?
6953 					      HN_DIVISOR_1000 : 0));
6954 			if (ret == -1) {
6955 				warnx("%s: humanize_number failed!", __func__);
6956 				retval = 1;
6957 				goto bailout;
6958 			}
6959 			fprintf(stdout, "Device Size: %s%s", tmpstr,
6960 				(sizeonly == 0) ?  ", " : "\n");
6961 		} else if (numblocks != 0) {
6962 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6963 				"Blocks: " : "", (uintmax_t)maxsector + 1,
6964 				(sizeonly == 0) ? ", " : "\n");
6965 		} else {
6966 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6967 				"Last Block: " : "", (uintmax_t)maxsector,
6968 				(sizeonly == 0) ? ", " : "\n");
6969 		}
6970 	}
6971 	if (sizeonly == 0)
6972 		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6973 			"Block Length: " : "", block_len, (quiet == 0) ?
6974 			" bytes" : "");
6975 bailout:
6976 	cam_freeccb(ccb);
6977 
6978 	return (retval);
6979 }
6980 
6981 static int
6982 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6983        int retry_count, int timeout)
6984 {
6985 	int c, error = 0;
6986 	union ccb *ccb;
6987 	uint8_t *smp_request = NULL, *smp_response = NULL;
6988 	int request_size = 0, response_size = 0;
6989 	int fd_request = 0, fd_response = 0;
6990 	char *datastr = NULL;
6991 	struct get_hook hook;
6992 	int retval;
6993 	int flags = 0;
6994 
6995 	/*
6996 	 * Note that at the moment we don't support sending SMP CCBs to
6997 	 * devices that aren't probed by CAM.
6998 	 */
6999 	ccb = cam_getccb(device);
7000 	if (ccb == NULL) {
7001 		warnx("%s: error allocating CCB", __func__);
7002 		return (1);
7003 	}
7004 
7005 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7006 
7007 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7008 		switch (c) {
7009 		case 'R':
7010 			arglist |= CAM_ARG_CMD_IN;
7011 			response_size = strtol(optarg, NULL, 0);
7012 			if (response_size <= 0) {
7013 				warnx("invalid number of response bytes %d",
7014 				      response_size);
7015 				error = 1;
7016 				goto smpcmd_bailout;
7017 			}
7018 			hook.argc = argc - optind;
7019 			hook.argv = argv + optind;
7020 			hook.got = 0;
7021 			optind++;
7022 			datastr = cget(&hook, NULL);
7023 			/*
7024 			 * If the user supplied "-" instead of a format, he
7025 			 * wants the data to be written to stdout.
7026 			 */
7027 			if ((datastr != NULL)
7028 			 && (datastr[0] == '-'))
7029 				fd_response = 1;
7030 
7031 			smp_response = (u_int8_t *)malloc(response_size);
7032 			if (smp_response == NULL) {
7033 				warn("can't malloc memory for SMP response");
7034 				error = 1;
7035 				goto smpcmd_bailout;
7036 			}
7037 			break;
7038 		case 'r':
7039 			arglist |= CAM_ARG_CMD_OUT;
7040 			request_size = strtol(optarg, NULL, 0);
7041 			if (request_size <= 0) {
7042 				warnx("invalid number of request bytes %d",
7043 				      request_size);
7044 				error = 1;
7045 				goto smpcmd_bailout;
7046 			}
7047 			hook.argc = argc - optind;
7048 			hook.argv = argv + optind;
7049 			hook.got = 0;
7050 			datastr = cget(&hook, NULL);
7051 			smp_request = (u_int8_t *)malloc(request_size);
7052 			if (smp_request == NULL) {
7053 				warn("can't malloc memory for SMP request");
7054 				error = 1;
7055 				goto smpcmd_bailout;
7056 			}
7057 			bzero(smp_request, request_size);
7058 			/*
7059 			 * If the user supplied "-" instead of a format, he
7060 			 * wants the data to be read from stdin.
7061 			 */
7062 			if ((datastr != NULL)
7063 			 && (datastr[0] == '-'))
7064 				fd_request = 1;
7065 			else
7066 				buff_encode_visit(smp_request, request_size,
7067 						  datastr,
7068 						  iget, &hook);
7069 			optind += hook.got;
7070 			break;
7071 		default:
7072 			break;
7073 		}
7074 	}
7075 
7076 	/*
7077 	 * If fd_data is set, and we're writing to the device, we need to
7078 	 * read the data the user wants written from stdin.
7079 	 */
7080 	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
7081 		ssize_t amt_read;
7082 		int amt_to_read = request_size;
7083 		u_int8_t *buf_ptr = smp_request;
7084 
7085 		for (amt_read = 0; amt_to_read > 0;
7086 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
7087 			if (amt_read == -1) {
7088 				warn("error reading data from stdin");
7089 				error = 1;
7090 				goto smpcmd_bailout;
7091 			}
7092 			amt_to_read -= amt_read;
7093 			buf_ptr += amt_read;
7094 		}
7095 	}
7096 
7097 	if (((arglist & CAM_ARG_CMD_IN) == 0)
7098 	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
7099 		warnx("%s: need both the request (-r) and response (-R) "
7100 		      "arguments", __func__);
7101 		error = 1;
7102 		goto smpcmd_bailout;
7103 	}
7104 
7105 	flags |= CAM_DEV_QFRZDIS;
7106 
7107 	cam_fill_smpio(&ccb->smpio,
7108 		       /*retries*/ retry_count,
7109 		       /*cbfcnp*/ NULL,
7110 		       /*flags*/ flags,
7111 		       /*smp_request*/ smp_request,
7112 		       /*smp_request_len*/ request_size,
7113 		       /*smp_response*/ smp_response,
7114 		       /*smp_response_len*/ response_size,
7115 		       /*timeout*/ timeout ? timeout : 5000);
7116 
7117 	ccb->smpio.flags = SMP_FLAG_NONE;
7118 
7119 	if (((retval = cam_send_ccb(device, ccb)) < 0)
7120 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7121 		const char warnstr[] = "error sending command";
7122 
7123 		if (retval < 0)
7124 			warn(warnstr);
7125 		else
7126 			warnx(warnstr);
7127 
7128 		if (arglist & CAM_ARG_VERBOSE) {
7129 			cam_error_print(device, ccb, CAM_ESF_ALL,
7130 					CAM_EPF_ALL, stderr);
7131 		}
7132 	}
7133 
7134 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
7135 	 && (response_size > 0)) {
7136 		if (fd_response == 0) {
7137 			buff_decode_visit(smp_response, response_size,
7138 					  datastr, arg_put, NULL);
7139 			fprintf(stdout, "\n");
7140 		} else {
7141 			ssize_t amt_written;
7142 			int amt_to_write = response_size;
7143 			u_int8_t *buf_ptr = smp_response;
7144 
7145 			for (amt_written = 0; (amt_to_write > 0) &&
7146 			     (amt_written = write(STDOUT_FILENO, buf_ptr,
7147 						  amt_to_write)) > 0;){
7148 				amt_to_write -= amt_written;
7149 				buf_ptr += amt_written;
7150 			}
7151 			if (amt_written == -1) {
7152 				warn("error writing data to stdout");
7153 				error = 1;
7154 				goto smpcmd_bailout;
7155 			} else if ((amt_written == 0)
7156 				&& (amt_to_write > 0)) {
7157 				warnx("only wrote %u bytes out of %u",
7158 				      response_size - amt_to_write,
7159 				      response_size);
7160 			}
7161 		}
7162 	}
7163 smpcmd_bailout:
7164 	if (ccb != NULL)
7165 		cam_freeccb(ccb);
7166 
7167 	if (smp_request != NULL)
7168 		free(smp_request);
7169 
7170 	if (smp_response != NULL)
7171 		free(smp_response);
7172 
7173 	return (error);
7174 }
7175 
7176 static int
7177 smpreportgeneral(struct cam_device *device, int argc, char **argv,
7178 		 char *combinedopt, int retry_count, int timeout)
7179 {
7180 	union ccb *ccb;
7181 	struct smp_report_general_request *request = NULL;
7182 	struct smp_report_general_response *response = NULL;
7183 	struct sbuf *sb = NULL;
7184 	int error = 0;
7185 	int c, long_response = 0;
7186 	int retval;
7187 
7188 	/*
7189 	 * Note that at the moment we don't support sending SMP CCBs to
7190 	 * devices that aren't probed by CAM.
7191 	 */
7192 	ccb = cam_getccb(device);
7193 	if (ccb == NULL) {
7194 		warnx("%s: error allocating CCB", __func__);
7195 		return (1);
7196 	}
7197 
7198 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7199 
7200 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7201 		switch (c) {
7202 		case 'l':
7203 			long_response = 1;
7204 			break;
7205 		default:
7206 			break;
7207 		}
7208 	}
7209 	request = malloc(sizeof(*request));
7210 	if (request == NULL) {
7211 		warn("%s: unable to allocate %zd bytes", __func__,
7212 		     sizeof(*request));
7213 		error = 1;
7214 		goto bailout;
7215 	}
7216 
7217 	response = malloc(sizeof(*response));
7218 	if (response == NULL) {
7219 		warn("%s: unable to allocate %zd bytes", __func__,
7220 		     sizeof(*response));
7221 		error = 1;
7222 		goto bailout;
7223 	}
7224 
7225 try_long:
7226 	smp_report_general(&ccb->smpio,
7227 			   retry_count,
7228 			   /*cbfcnp*/ NULL,
7229 			   request,
7230 			   /*request_len*/ sizeof(*request),
7231 			   (uint8_t *)response,
7232 			   /*response_len*/ sizeof(*response),
7233 			   /*long_response*/ long_response,
7234 			   timeout);
7235 
7236 	if (((retval = cam_send_ccb(device, ccb)) < 0)
7237 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7238 		const char warnstr[] = "error sending command";
7239 
7240 		if (retval < 0)
7241 			warn(warnstr);
7242 		else
7243 			warnx(warnstr);
7244 
7245 		if (arglist & CAM_ARG_VERBOSE) {
7246 			cam_error_print(device, ccb, CAM_ESF_ALL,
7247 					CAM_EPF_ALL, stderr);
7248 		}
7249 		error = 1;
7250 		goto bailout;
7251 	}
7252 
7253 	/*
7254 	 * If the device supports the long response bit, try again and see
7255 	 * if we can get all of the data.
7256 	 */
7257 	if ((response->long_response & SMP_RG_LONG_RESPONSE)
7258 	 && (long_response == 0)) {
7259 		ccb->ccb_h.status = CAM_REQ_INPROG;
7260 		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7261 		long_response = 1;
7262 		goto try_long;
7263 	}
7264 
7265 	/*
7266 	 * XXX KDM detect and decode SMP errors here.
7267 	 */
7268 	sb = sbuf_new_auto();
7269 	if (sb == NULL) {
7270 		warnx("%s: error allocating sbuf", __func__);
7271 		goto bailout;
7272 	}
7273 
7274 	smp_report_general_sbuf(response, sizeof(*response), sb);
7275 
7276 	if (sbuf_finish(sb) != 0) {
7277 		warnx("%s: sbuf_finish", __func__);
7278 		goto bailout;
7279 	}
7280 
7281 	printf("%s", sbuf_data(sb));
7282 
7283 bailout:
7284 	if (ccb != NULL)
7285 		cam_freeccb(ccb);
7286 
7287 	if (request != NULL)
7288 		free(request);
7289 
7290 	if (response != NULL)
7291 		free(response);
7292 
7293 	if (sb != NULL)
7294 		sbuf_delete(sb);
7295 
7296 	return (error);
7297 }
7298 
7299 static struct camcontrol_opts phy_ops[] = {
7300 	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7301 	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7302 	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7303 	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7304 	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7305 	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7306 	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7307 	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7308 	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7309 	{NULL, 0, 0, NULL}
7310 };
7311 
7312 static int
7313 smpphycontrol(struct cam_device *device, int argc, char **argv,
7314 	      char *combinedopt, int retry_count, int timeout)
7315 {
7316 	union ccb *ccb;
7317 	struct smp_phy_control_request *request = NULL;
7318 	struct smp_phy_control_response *response = NULL;
7319 	int long_response = 0;
7320 	int retval = 0;
7321 	int phy = -1;
7322 	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7323 	int phy_op_set = 0;
7324 	uint64_t attached_dev_name = 0;
7325 	int dev_name_set = 0;
7326 	uint32_t min_plr = 0, max_plr = 0;
7327 	uint32_t pp_timeout_val = 0;
7328 	int slumber_partial = 0;
7329 	int set_pp_timeout_val = 0;
7330 	int c;
7331 
7332 	/*
7333 	 * Note that at the moment we don't support sending SMP CCBs to
7334 	 * devices that aren't probed by CAM.
7335 	 */
7336 	ccb = cam_getccb(device);
7337 	if (ccb == NULL) {
7338 		warnx("%s: error allocating CCB", __func__);
7339 		return (1);
7340 	}
7341 
7342 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7343 
7344 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7345 		switch (c) {
7346 		case 'a':
7347 		case 'A':
7348 		case 's':
7349 		case 'S': {
7350 			int enable = -1;
7351 
7352 			if (strcasecmp(optarg, "enable") == 0)
7353 				enable = 1;
7354 			else if (strcasecmp(optarg, "disable") == 0)
7355 				enable = 2;
7356 			else {
7357 				warnx("%s: Invalid argument %s", __func__,
7358 				      optarg);
7359 				retval = 1;
7360 				goto bailout;
7361 			}
7362 			switch (c) {
7363 			case 's':
7364 				slumber_partial |= enable <<
7365 						   SMP_PC_SAS_SLUMBER_SHIFT;
7366 				break;
7367 			case 'S':
7368 				slumber_partial |= enable <<
7369 						   SMP_PC_SAS_PARTIAL_SHIFT;
7370 				break;
7371 			case 'a':
7372 				slumber_partial |= enable <<
7373 						   SMP_PC_SATA_SLUMBER_SHIFT;
7374 				break;
7375 			case 'A':
7376 				slumber_partial |= enable <<
7377 						   SMP_PC_SATA_PARTIAL_SHIFT;
7378 				break;
7379 			default:
7380 				warnx("%s: programmer error", __func__);
7381 				retval = 1;
7382 				goto bailout;
7383 				break; /*NOTREACHED*/
7384 			}
7385 			break;
7386 		}
7387 		case 'd':
7388 			attached_dev_name = (uintmax_t)strtoumax(optarg,
7389 								 NULL,0);
7390 			dev_name_set = 1;
7391 			break;
7392 		case 'l':
7393 			long_response = 1;
7394 			break;
7395 		case 'm':
7396 			/*
7397 			 * We don't do extensive checking here, so this
7398 			 * will continue to work when new speeds come out.
7399 			 */
7400 			min_plr = strtoul(optarg, NULL, 0);
7401 			if ((min_plr == 0)
7402 			 || (min_plr > 0xf)) {
7403 				warnx("%s: invalid link rate %x",
7404 				      __func__, min_plr);
7405 				retval = 1;
7406 				goto bailout;
7407 			}
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 			max_plr = strtoul(optarg, NULL, 0);
7415 			if ((max_plr == 0)
7416 			 || (max_plr > 0xf)) {
7417 				warnx("%s: invalid link rate %x",
7418 				      __func__, max_plr);
7419 				retval = 1;
7420 				goto bailout;
7421 			}
7422 			break;
7423 		case 'o': {
7424 			camcontrol_optret optreturn;
7425 			cam_argmask argnums;
7426 			const char *subopt;
7427 
7428 			if (phy_op_set != 0) {
7429 				warnx("%s: only one phy operation argument "
7430 				      "(-o) allowed", __func__);
7431 				retval = 1;
7432 				goto bailout;
7433 			}
7434 
7435 			phy_op_set = 1;
7436 
7437 			/*
7438 			 * Allow the user to specify the phy operation
7439 			 * numerically, as well as with a name.  This will
7440 			 * future-proof it a bit, so options that are added
7441 			 * in future specs can be used.
7442 			 */
7443 			if (isdigit(optarg[0])) {
7444 				phy_operation = strtoul(optarg, NULL, 0);
7445 				if ((phy_operation == 0)
7446 				 || (phy_operation > 0xff)) {
7447 					warnx("%s: invalid phy operation %#x",
7448 					      __func__, phy_operation);
7449 					retval = 1;
7450 					goto bailout;
7451 				}
7452 				break;
7453 			}
7454 			optreturn = getoption(phy_ops, optarg, &phy_operation,
7455 					      &argnums, &subopt);
7456 
7457 			if (optreturn == CC_OR_AMBIGUOUS) {
7458 				warnx("%s: ambiguous option %s", __func__,
7459 				      optarg);
7460 				usage(0);
7461 				retval = 1;
7462 				goto bailout;
7463 			} else if (optreturn == CC_OR_NOT_FOUND) {
7464 				warnx("%s: option %s not found", __func__,
7465 				      optarg);
7466 				usage(0);
7467 				retval = 1;
7468 				goto bailout;
7469 			}
7470 			break;
7471 		}
7472 		case 'p':
7473 			phy = atoi(optarg);
7474 			break;
7475 		case 'T':
7476 			pp_timeout_val = strtoul(optarg, NULL, 0);
7477 			if (pp_timeout_val > 15) {
7478 				warnx("%s: invalid partial pathway timeout "
7479 				      "value %u, need a value less than 16",
7480 				      __func__, pp_timeout_val);
7481 				retval = 1;
7482 				goto bailout;
7483 			}
7484 			set_pp_timeout_val = 1;
7485 			break;
7486 		default:
7487 			break;
7488 		}
7489 	}
7490 
7491 	if (phy == -1) {
7492 		warnx("%s: a PHY (-p phy) argument is required",__func__);
7493 		retval = 1;
7494 		goto bailout;
7495 	}
7496 
7497 	if (((dev_name_set != 0)
7498 	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7499 	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7500 	  && (dev_name_set == 0))) {
7501 		warnx("%s: -d name and -o setdevname arguments both "
7502 		      "required to set device name", __func__);
7503 		retval = 1;
7504 		goto bailout;
7505 	}
7506 
7507 	request = malloc(sizeof(*request));
7508 	if (request == NULL) {
7509 		warn("%s: unable to allocate %zd bytes", __func__,
7510 		     sizeof(*request));
7511 		retval = 1;
7512 		goto bailout;
7513 	}
7514 
7515 	response = malloc(sizeof(*response));
7516 	if (response == NULL) {
7517 		warn("%s: unable to allocate %zd bytes", __func__,
7518 		     sizeof(*response));
7519 		retval = 1;
7520 		goto bailout;
7521 	}
7522 
7523 	smp_phy_control(&ccb->smpio,
7524 			retry_count,
7525 			/*cbfcnp*/ NULL,
7526 			request,
7527 			sizeof(*request),
7528 			(uint8_t *)response,
7529 			sizeof(*response),
7530 			long_response,
7531 			/*expected_exp_change_count*/ 0,
7532 			phy,
7533 			phy_operation,
7534 			(set_pp_timeout_val != 0) ? 1 : 0,
7535 			attached_dev_name,
7536 			min_plr,
7537 			max_plr,
7538 			slumber_partial,
7539 			pp_timeout_val,
7540 			timeout);
7541 
7542 	if (((retval = cam_send_ccb(device, ccb)) < 0)
7543 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7544 		const char warnstr[] = "error sending command";
7545 
7546 		if (retval < 0)
7547 			warn(warnstr);
7548 		else
7549 			warnx(warnstr);
7550 
7551 		if (arglist & CAM_ARG_VERBOSE) {
7552 			/*
7553 			 * Use CAM_EPF_NORMAL so we only get one line of
7554 			 * SMP command decoding.
7555 			 */
7556 			cam_error_print(device, ccb, CAM_ESF_ALL,
7557 					CAM_EPF_NORMAL, stderr);
7558 		}
7559 		retval = 1;
7560 		goto bailout;
7561 	}
7562 
7563 	/* XXX KDM print out something here for success? */
7564 bailout:
7565 	if (ccb != NULL)
7566 		cam_freeccb(ccb);
7567 
7568 	if (request != NULL)
7569 		free(request);
7570 
7571 	if (response != NULL)
7572 		free(response);
7573 
7574 	return (retval);
7575 }
7576 
7577 static int
7578 smpmaninfo(struct cam_device *device, int argc, char **argv,
7579 	   char *combinedopt, int retry_count, int timeout)
7580 {
7581 	union ccb *ccb;
7582 	struct smp_report_manuf_info_request request;
7583 	struct smp_report_manuf_info_response response;
7584 	struct sbuf *sb = NULL;
7585 	int long_response = 0;
7586 	int retval = 0;
7587 	int c;
7588 
7589 	/*
7590 	 * Note that at the moment we don't support sending SMP CCBs to
7591 	 * devices that aren't probed by CAM.
7592 	 */
7593 	ccb = cam_getccb(device);
7594 	if (ccb == NULL) {
7595 		warnx("%s: error allocating CCB", __func__);
7596 		return (1);
7597 	}
7598 
7599 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7600 
7601 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7602 		switch (c) {
7603 		case 'l':
7604 			long_response = 1;
7605 			break;
7606 		default:
7607 			break;
7608 		}
7609 	}
7610 	bzero(&request, sizeof(request));
7611 	bzero(&response, sizeof(response));
7612 
7613 	smp_report_manuf_info(&ccb->smpio,
7614 			      retry_count,
7615 			      /*cbfcnp*/ NULL,
7616 			      &request,
7617 			      sizeof(request),
7618 			      (uint8_t *)&response,
7619 			      sizeof(response),
7620 			      long_response,
7621 			      timeout);
7622 
7623 	if (((retval = cam_send_ccb(device, ccb)) < 0)
7624 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7625 		const char warnstr[] = "error sending command";
7626 
7627 		if (retval < 0)
7628 			warn(warnstr);
7629 		else
7630 			warnx(warnstr);
7631 
7632 		if (arglist & CAM_ARG_VERBOSE) {
7633 			cam_error_print(device, ccb, CAM_ESF_ALL,
7634 					CAM_EPF_ALL, stderr);
7635 		}
7636 		retval = 1;
7637 		goto bailout;
7638 	}
7639 
7640 	sb = sbuf_new_auto();
7641 	if (sb == NULL) {
7642 		warnx("%s: error allocating sbuf", __func__);
7643 		goto bailout;
7644 	}
7645 
7646 	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7647 
7648 	if (sbuf_finish(sb) != 0) {
7649 		warnx("%s: sbuf_finish", __func__);
7650 		goto bailout;
7651 	}
7652 
7653 	printf("%s", sbuf_data(sb));
7654 
7655 bailout:
7656 
7657 	if (ccb != NULL)
7658 		cam_freeccb(ccb);
7659 
7660 	if (sb != NULL)
7661 		sbuf_delete(sb);
7662 
7663 	return (retval);
7664 }
7665 
7666 static int
7667 getdevid(struct cam_devitem *item)
7668 {
7669 	int retval = 0;
7670 	union ccb *ccb = NULL;
7671 
7672 	struct cam_device *dev;
7673 
7674 	dev = cam_open_btl(item->dev_match.path_id,
7675 			   item->dev_match.target_id,
7676 			   item->dev_match.target_lun, O_RDWR, NULL);
7677 
7678 	if (dev == NULL) {
7679 		warnx("%s", cam_errbuf);
7680 		retval = 1;
7681 		goto bailout;
7682 	}
7683 
7684 	item->device_id_len = 0;
7685 
7686 	ccb = cam_getccb(dev);
7687 	if (ccb == NULL) {
7688 		warnx("%s: error allocating CCB", __func__);
7689 		retval = 1;
7690 		goto bailout;
7691 	}
7692 
7693 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai);
7694 
7695 	/*
7696 	 * On the first try, we just probe for the size of the data, and
7697 	 * then allocate that much memory and try again.
7698 	 */
7699 retry:
7700 	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7701 	ccb->ccb_h.flags = CAM_DIR_IN;
7702 	ccb->cdai.flags = CDAI_FLAG_NONE;
7703 	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7704 	ccb->cdai.bufsiz = item->device_id_len;
7705 	if (item->device_id_len != 0)
7706 		ccb->cdai.buf = (uint8_t *)item->device_id;
7707 
7708 	if (cam_send_ccb(dev, ccb) < 0) {
7709 		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7710 		retval = 1;
7711 		goto bailout;
7712 	}
7713 
7714 	if (ccb->ccb_h.status != CAM_REQ_CMP) {
7715 		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7716 		retval = 1;
7717 		goto bailout;
7718 	}
7719 
7720 	if (item->device_id_len == 0) {
7721 		/*
7722 		 * This is our first time through.  Allocate the buffer,
7723 		 * and then go back to get the data.
7724 		 */
7725 		if (ccb->cdai.provsiz == 0) {
7726 			warnx("%s: invalid .provsiz field returned with "
7727 			     "XPT_GDEV_ADVINFO CCB", __func__);
7728 			retval = 1;
7729 			goto bailout;
7730 		}
7731 		item->device_id_len = ccb->cdai.provsiz;
7732 		item->device_id = malloc(item->device_id_len);
7733 		if (item->device_id == NULL) {
7734 			warn("%s: unable to allocate %d bytes", __func__,
7735 			     item->device_id_len);
7736 			retval = 1;
7737 			goto bailout;
7738 		}
7739 		ccb->ccb_h.status = CAM_REQ_INPROG;
7740 		goto retry;
7741 	}
7742 
7743 bailout:
7744 	if (dev != NULL)
7745 		cam_close_device(dev);
7746 
7747 	if (ccb != NULL)
7748 		cam_freeccb(ccb);
7749 
7750 	return (retval);
7751 }
7752 
7753 /*
7754  * XXX KDM merge this code with getdevtree()?
7755  */
7756 static int
7757 buildbusdevlist(struct cam_devlist *devlist)
7758 {
7759 	union ccb ccb;
7760 	int bufsize, fd = -1;
7761 	struct dev_match_pattern *patterns;
7762 	struct cam_devitem *item = NULL;
7763 	int skip_device = 0;
7764 	int retval = 0;
7765 
7766 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7767 		warn("couldn't open %s", XPT_DEVICE);
7768 		return(1);
7769 	}
7770 
7771 	bzero(&ccb, sizeof(union ccb));
7772 
7773 	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7774 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7775 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7776 
7777 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
7778 	bufsize = sizeof(struct dev_match_result) * 100;
7779 	ccb.cdm.match_buf_len = bufsize;
7780 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7781 	if (ccb.cdm.matches == NULL) {
7782 		warnx("can't malloc memory for matches");
7783 		close(fd);
7784 		return(1);
7785 	}
7786 	ccb.cdm.num_matches = 0;
7787 	ccb.cdm.num_patterns = 2;
7788 	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7789 		ccb.cdm.num_patterns;
7790 
7791 	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7792 	if (patterns == NULL) {
7793 		warnx("can't malloc memory for patterns");
7794 		retval = 1;
7795 		goto bailout;
7796 	}
7797 
7798 	ccb.cdm.patterns = patterns;
7799 	bzero(patterns, ccb.cdm.pattern_buf_len);
7800 
7801 	patterns[0].type = DEV_MATCH_DEVICE;
7802 	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7803 	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7804 	patterns[1].type = DEV_MATCH_PERIPH;
7805 	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7806 	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7807 
7808 	/*
7809 	 * We do the ioctl multiple times if necessary, in case there are
7810 	 * more than 100 nodes in the EDT.
7811 	 */
7812 	do {
7813 		unsigned int i;
7814 
7815 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7816 			warn("error sending CAMIOCOMMAND ioctl");
7817 			retval = 1;
7818 			goto bailout;
7819 		}
7820 
7821 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
7822 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7823 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7824 			warnx("got CAM error %#x, CDM error %d\n",
7825 			      ccb.ccb_h.status, ccb.cdm.status);
7826 			retval = 1;
7827 			goto bailout;
7828 		}
7829 
7830 		for (i = 0; i < ccb.cdm.num_matches; i++) {
7831 			switch (ccb.cdm.matches[i].type) {
7832 			case DEV_MATCH_DEVICE: {
7833 				struct device_match_result *dev_result;
7834 
7835 				dev_result =
7836 				     &ccb.cdm.matches[i].result.device_result;
7837 
7838 				if (dev_result->flags &
7839 				    DEV_RESULT_UNCONFIGURED) {
7840 					skip_device = 1;
7841 					break;
7842 				} else
7843 					skip_device = 0;
7844 
7845 				item = malloc(sizeof(*item));
7846 				if (item == NULL) {
7847 					warn("%s: unable to allocate %zd bytes",
7848 					     __func__, sizeof(*item));
7849 					retval = 1;
7850 					goto bailout;
7851 				}
7852 				bzero(item, sizeof(*item));
7853 				bcopy(dev_result, &item->dev_match,
7854 				      sizeof(*dev_result));
7855 				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7856 						   links);
7857 
7858 				if (getdevid(item) != 0) {
7859 					retval = 1;
7860 					goto bailout;
7861 				}
7862 				break;
7863 			}
7864 			case DEV_MATCH_PERIPH: {
7865 				struct periph_match_result *periph_result;
7866 
7867 				periph_result =
7868 				      &ccb.cdm.matches[i].result.periph_result;
7869 
7870 				if (skip_device != 0)
7871 					break;
7872 				item->num_periphs++;
7873 				item->periph_matches = realloc(
7874 					item->periph_matches,
7875 					item->num_periphs *
7876 					sizeof(struct periph_match_result));
7877 				if (item->periph_matches == NULL) {
7878 					warn("%s: error allocating periph "
7879 					     "list", __func__);
7880 					retval = 1;
7881 					goto bailout;
7882 				}
7883 				bcopy(periph_result, &item->periph_matches[
7884 				      item->num_periphs - 1],
7885 				      sizeof(*periph_result));
7886 				break;
7887 			}
7888 			default:
7889 				fprintf(stderr, "%s: unexpected match "
7890 					"type %d\n", __func__,
7891 					ccb.cdm.matches[i].type);
7892 				retval = 1;
7893 				goto bailout;
7894 				break; /*NOTREACHED*/
7895 			}
7896 		}
7897 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
7898 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7899 bailout:
7900 
7901 	if (fd != -1)
7902 		close(fd);
7903 
7904 	free(patterns);
7905 
7906 	free(ccb.cdm.matches);
7907 
7908 	if (retval != 0)
7909 		freebusdevlist(devlist);
7910 
7911 	return (retval);
7912 }
7913 
7914 static void
7915 freebusdevlist(struct cam_devlist *devlist)
7916 {
7917 	struct cam_devitem *item, *item2;
7918 
7919 	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7920 		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7921 			      links);
7922 		free(item->device_id);
7923 		free(item->periph_matches);
7924 		free(item);
7925 	}
7926 }
7927 
7928 static struct cam_devitem *
7929 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7930 {
7931 	struct cam_devitem *item;
7932 
7933 	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7934 		struct scsi_vpd_id_descriptor *idd;
7935 
7936 		/*
7937 		 * XXX KDM look for LUN IDs as well?
7938 		 */
7939 		idd = scsi_get_devid(item->device_id,
7940 					   item->device_id_len,
7941 					   scsi_devid_is_sas_target);
7942 		if (idd == NULL)
7943 			continue;
7944 
7945 		if (scsi_8btou64(idd->identifier) == sasaddr)
7946 			return (item);
7947 	}
7948 
7949 	return (NULL);
7950 }
7951 
7952 static int
7953 smpphylist(struct cam_device *device, int argc, char **argv,
7954 	   char *combinedopt, int retry_count, int timeout)
7955 {
7956 	struct smp_report_general_request *rgrequest = NULL;
7957 	struct smp_report_general_response *rgresponse = NULL;
7958 	struct smp_discover_request *disrequest = NULL;
7959 	struct smp_discover_response *disresponse = NULL;
7960 	struct cam_devlist devlist;
7961 	union ccb *ccb;
7962 	int long_response = 0;
7963 	int num_phys = 0;
7964 	int quiet = 0;
7965 	int retval;
7966 	int i, c;
7967 
7968 	/*
7969 	 * Note that at the moment we don't support sending SMP CCBs to
7970 	 * devices that aren't probed by CAM.
7971 	 */
7972 	ccb = cam_getccb(device);
7973 	if (ccb == NULL) {
7974 		warnx("%s: error allocating CCB", __func__);
7975 		return (1);
7976 	}
7977 
7978 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7979 	STAILQ_INIT(&devlist.dev_queue);
7980 
7981 	rgrequest = malloc(sizeof(*rgrequest));
7982 	if (rgrequest == NULL) {
7983 		warn("%s: unable to allocate %zd bytes", __func__,
7984 		     sizeof(*rgrequest));
7985 		retval = 1;
7986 		goto bailout;
7987 	}
7988 
7989 	rgresponse = malloc(sizeof(*rgresponse));
7990 	if (rgresponse == NULL) {
7991 		warn("%s: unable to allocate %zd bytes", __func__,
7992 		     sizeof(*rgresponse));
7993 		retval = 1;
7994 		goto bailout;
7995 	}
7996 
7997 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7998 		switch (c) {
7999 		case 'l':
8000 			long_response = 1;
8001 			break;
8002 		case 'q':
8003 			quiet = 1;
8004 			break;
8005 		default:
8006 			break;
8007 		}
8008 	}
8009 
8010 	smp_report_general(&ccb->smpio,
8011 			   retry_count,
8012 			   /*cbfcnp*/ NULL,
8013 			   rgrequest,
8014 			   /*request_len*/ sizeof(*rgrequest),
8015 			   (uint8_t *)rgresponse,
8016 			   /*response_len*/ sizeof(*rgresponse),
8017 			   /*long_response*/ long_response,
8018 			   timeout);
8019 
8020 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8021 
8022 	if (((retval = cam_send_ccb(device, ccb)) < 0)
8023 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8024 		const char warnstr[] = "error sending command";
8025 
8026 		if (retval < 0)
8027 			warn(warnstr);
8028 		else
8029 			warnx(warnstr);
8030 
8031 		if (arglist & CAM_ARG_VERBOSE) {
8032 			cam_error_print(device, ccb, CAM_ESF_ALL,
8033 					CAM_EPF_ALL, stderr);
8034 		}
8035 		retval = 1;
8036 		goto bailout;
8037 	}
8038 
8039 	num_phys = rgresponse->num_phys;
8040 
8041 	if (num_phys == 0) {
8042 		if (quiet == 0)
8043 			fprintf(stdout, "%s: No Phys reported\n", __func__);
8044 		retval = 1;
8045 		goto bailout;
8046 	}
8047 
8048 	devlist.path_id = device->path_id;
8049 
8050 	retval = buildbusdevlist(&devlist);
8051 	if (retval != 0)
8052 		goto bailout;
8053 
8054 	if (quiet == 0) {
8055 		fprintf(stdout, "%d PHYs:\n", num_phys);
8056 		fprintf(stdout, "PHY  Attached SAS Address\n");
8057 	}
8058 
8059 	disrequest = malloc(sizeof(*disrequest));
8060 	if (disrequest == NULL) {
8061 		warn("%s: unable to allocate %zd bytes", __func__,
8062 		     sizeof(*disrequest));
8063 		retval = 1;
8064 		goto bailout;
8065 	}
8066 
8067 	disresponse = malloc(sizeof(*disresponse));
8068 	if (disresponse == NULL) {
8069 		warn("%s: unable to allocate %zd bytes", __func__,
8070 		     sizeof(*disresponse));
8071 		retval = 1;
8072 		goto bailout;
8073 	}
8074 
8075 	for (i = 0; i < num_phys; i++) {
8076 		struct cam_devitem *item;
8077 		struct device_match_result *dev_match;
8078 		char vendor[16], product[48], revision[16];
8079 		char tmpstr[256];
8080 		int j;
8081 
8082 		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8083 
8084 		ccb->ccb_h.status = CAM_REQ_INPROG;
8085 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8086 
8087 		smp_discover(&ccb->smpio,
8088 			     retry_count,
8089 			     /*cbfcnp*/ NULL,
8090 			     disrequest,
8091 			     sizeof(*disrequest),
8092 			     (uint8_t *)disresponse,
8093 			     sizeof(*disresponse),
8094 			     long_response,
8095 			     /*ignore_zone_group*/ 0,
8096 			     /*phy*/ i,
8097 			     timeout);
8098 
8099 		if (((retval = cam_send_ccb(device, ccb)) < 0)
8100 		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
8101 		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
8102 			const char warnstr[] = "error sending command";
8103 
8104 			if (retval < 0)
8105 				warn(warnstr);
8106 			else
8107 				warnx(warnstr);
8108 
8109 			if (arglist & CAM_ARG_VERBOSE) {
8110 				cam_error_print(device, ccb, CAM_ESF_ALL,
8111 						CAM_EPF_ALL, stderr);
8112 			}
8113 			retval = 1;
8114 			goto bailout;
8115 		}
8116 
8117 		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
8118 			if (quiet == 0)
8119 				fprintf(stdout, "%3d  <vacant>\n", i);
8120 			continue;
8121 		}
8122 
8123 		if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
8124 			item = NULL;
8125 		} else {
8126 			item = findsasdevice(&devlist,
8127 			    scsi_8btou64(disresponse->attached_sas_address));
8128 		}
8129 
8130 		if ((quiet == 0)
8131 		 || (item != NULL)) {
8132 			fprintf(stdout, "%3d  0x%016jx", i,
8133 				(uintmax_t)scsi_8btou64(
8134 				disresponse->attached_sas_address));
8135 			if (item == NULL) {
8136 				fprintf(stdout, "\n");
8137 				continue;
8138 			}
8139 		} else if (quiet != 0)
8140 			continue;
8141 
8142 		dev_match = &item->dev_match;
8143 
8144 		if (dev_match->protocol == PROTO_SCSI) {
8145 			cam_strvis(vendor, dev_match->inq_data.vendor,
8146 				   sizeof(dev_match->inq_data.vendor),
8147 				   sizeof(vendor));
8148 			cam_strvis(product, dev_match->inq_data.product,
8149 				   sizeof(dev_match->inq_data.product),
8150 				   sizeof(product));
8151 			cam_strvis(revision, dev_match->inq_data.revision,
8152 				   sizeof(dev_match->inq_data.revision),
8153 				   sizeof(revision));
8154 			sprintf(tmpstr, "<%s %s %s>", vendor, product,
8155 				revision);
8156 		} else if ((dev_match->protocol == PROTO_ATA)
8157 			|| (dev_match->protocol == PROTO_SATAPM)) {
8158 			cam_strvis(product, dev_match->ident_data.model,
8159 				   sizeof(dev_match->ident_data.model),
8160 				   sizeof(product));
8161 			cam_strvis(revision, dev_match->ident_data.revision,
8162 				   sizeof(dev_match->ident_data.revision),
8163 				   sizeof(revision));
8164 			sprintf(tmpstr, "<%s %s>", product, revision);
8165 		} else {
8166 			sprintf(tmpstr, "<>");
8167 		}
8168 		fprintf(stdout, "   %-33s ", tmpstr);
8169 
8170 		/*
8171 		 * If we have 0 periphs, that's a bug...
8172 		 */
8173 		if (item->num_periphs == 0) {
8174 			fprintf(stdout, "\n");
8175 			continue;
8176 		}
8177 
8178 		fprintf(stdout, "(");
8179 		for (j = 0; j < item->num_periphs; j++) {
8180 			if (j > 0)
8181 				fprintf(stdout, ",");
8182 
8183 			fprintf(stdout, "%s%d",
8184 				item->periph_matches[j].periph_name,
8185 				item->periph_matches[j].unit_number);
8186 
8187 		}
8188 		fprintf(stdout, ")\n");
8189 	}
8190 bailout:
8191 	if (ccb != NULL)
8192 		cam_freeccb(ccb);
8193 
8194 	free(rgrequest);
8195 
8196 	free(rgresponse);
8197 
8198 	free(disrequest);
8199 
8200 	free(disresponse);
8201 
8202 	freebusdevlist(&devlist);
8203 
8204 	return (retval);
8205 }
8206 
8207 static int
8208 atapm(struct cam_device *device, int argc, char **argv,
8209 		 char *combinedopt, int retry_count, int timeout)
8210 {
8211 	union ccb *ccb;
8212 	int retval = 0;
8213 	int t = -1;
8214 	int c;
8215 	u_char cmd, sc;
8216 
8217 	ccb = cam_getccb(device);
8218 
8219 	if (ccb == NULL) {
8220 		warnx("%s: error allocating ccb", __func__);
8221 		return (1);
8222 	}
8223 
8224 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8225 		switch (c) {
8226 		case 't':
8227 			t = atoi(optarg);
8228 			break;
8229 		default:
8230 			break;
8231 		}
8232 	}
8233 	if (strcmp(argv[1], "idle") == 0) {
8234 		if (t == -1)
8235 			cmd = ATA_IDLE_IMMEDIATE;
8236 		else
8237 			cmd = ATA_IDLE_CMD;
8238 	} else if (strcmp(argv[1], "standby") == 0) {
8239 		if (t == -1)
8240 			cmd = ATA_STANDBY_IMMEDIATE;
8241 		else
8242 			cmd = ATA_STANDBY_CMD;
8243 	} else {
8244 		cmd = ATA_SLEEP;
8245 		t = -1;
8246 	}
8247 
8248 	if (t < 0)
8249 		sc = 0;
8250 	else if (t <= (240 * 5))
8251 		sc = (t + 4) / 5;
8252 	else if (t <= (252 * 5))
8253 		/* special encoding for 21 minutes */
8254 		sc = 252;
8255 	else if (t <= (11 * 30 * 60))
8256 		sc = (t - 1) / (30 * 60) + 241;
8257 	else
8258 		sc = 253;
8259 
8260 	retval = ata_do_28bit_cmd(device,
8261 	    ccb,
8262 	    /*retries*/retry_count,
8263 	    /*flags*/CAM_DIR_NONE,
8264 	    /*protocol*/AP_PROTO_NON_DATA,
8265 	    /*tag_action*/MSG_SIMPLE_Q_TAG,
8266 	    /*command*/cmd,
8267 	    /*features*/0,
8268 	    /*lba*/0,
8269 	    /*sector_count*/sc,
8270 	    /*data_ptr*/NULL,
8271 	    /*dxfer_len*/0,
8272 	    /*timeout*/timeout ? timeout : 30 * 1000,
8273 	    /*quiet*/1);
8274 
8275 	cam_freeccb(ccb);
8276 	return (retval);
8277 }
8278 
8279 static int
8280 ataaxm(struct cam_device *device, int argc, char **argv,
8281 		 char *combinedopt, int retry_count, int timeout)
8282 {
8283 	union ccb *ccb;
8284 	int retval = 0;
8285 	int l = -1;
8286 	int c;
8287 	u_char cmd, sc;
8288 
8289 	ccb = cam_getccb(device);
8290 
8291 	if (ccb == NULL) {
8292 		warnx("%s: error allocating ccb", __func__);
8293 		return (1);
8294 	}
8295 
8296 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8297 		switch (c) {
8298 		case 'l':
8299 			l = atoi(optarg);
8300 			break;
8301 		default:
8302 			break;
8303 		}
8304 	}
8305 	sc = 0;
8306 	if (strcmp(argv[1], "apm") == 0) {
8307 		if (l == -1)
8308 			cmd = 0x85;
8309 		else {
8310 			cmd = 0x05;
8311 			sc = l;
8312 		}
8313 	} else /* aam */ {
8314 		if (l == -1)
8315 			cmd = 0xC2;
8316 		else {
8317 			cmd = 0x42;
8318 			sc = l;
8319 		}
8320 	}
8321 
8322 	retval = ata_do_28bit_cmd(device,
8323 	    ccb,
8324 	    /*retries*/retry_count,
8325 	    /*flags*/CAM_DIR_NONE,
8326 	    /*protocol*/AP_PROTO_NON_DATA,
8327 	    /*tag_action*/MSG_SIMPLE_Q_TAG,
8328 	    /*command*/ATA_SETFEATURES,
8329 	    /*features*/cmd,
8330 	    /*lba*/0,
8331 	    /*sector_count*/sc,
8332 	    /*data_ptr*/NULL,
8333 	    /*dxfer_len*/0,
8334 	    /*timeout*/timeout ? timeout : 30 * 1000,
8335 	    /*quiet*/1);
8336 
8337 	cam_freeccb(ccb);
8338 	return (retval);
8339 }
8340 
8341 int
8342 scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8343 	       int show_sa_errors, int sa_set, int service_action,
8344 	       int timeout_desc, int retry_count, int timeout, int verbosemode,
8345 	       uint32_t *fill_len, uint8_t **data_ptr)
8346 {
8347 	union ccb *ccb = NULL;
8348 	uint8_t *buf = NULL;
8349 	uint32_t alloc_len = 0, num_opcodes;
8350 	uint32_t valid_len = 0;
8351 	uint32_t avail_len = 0;
8352 	struct scsi_report_supported_opcodes_all *all_hdr;
8353 	struct scsi_report_supported_opcodes_one *one;
8354 	int options = 0;
8355 	int retval = 0;
8356 
8357 	/*
8358 	 * Make it clear that we haven't yet allocated or filled anything.
8359 	 */
8360 	*fill_len = 0;
8361 	*data_ptr = NULL;
8362 
8363 	ccb = cam_getccb(device);
8364 	if (ccb == NULL) {
8365 		warnx("couldn't allocate CCB");
8366 		retval = 1;
8367 		goto bailout;
8368 	}
8369 
8370 	/* cam_getccb cleans up the header, caller has to zero the payload */
8371 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8372 
8373 	if (opcode_set != 0) {
8374 		options |= RSO_OPTIONS_OC;
8375 		num_opcodes = 1;
8376 		alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8377 	} else {
8378 		num_opcodes = 256;
8379 		alloc_len = sizeof(*all_hdr) + (num_opcodes *
8380 		    sizeof(struct scsi_report_supported_opcodes_descr));
8381 	}
8382 
8383 	if (timeout_desc != 0) {
8384 		options |= RSO_RCTD;
8385 		alloc_len += num_opcodes *
8386 		    sizeof(struct scsi_report_supported_opcodes_timeout);
8387 	}
8388 
8389 	if (sa_set != 0) {
8390 		options |= RSO_OPTIONS_OC_SA;
8391 		if (show_sa_errors != 0)
8392 			options &= ~RSO_OPTIONS_OC;
8393 	}
8394 
8395 retry_alloc:
8396 	if (buf != NULL) {
8397 		free(buf);
8398 		buf = NULL;
8399 	}
8400 
8401 	buf = malloc(alloc_len);
8402 	if (buf == NULL) {
8403 		warn("Unable to allocate %u bytes", alloc_len);
8404 		retval = 1;
8405 		goto bailout;
8406 	}
8407 	bzero(buf, alloc_len);
8408 
8409 	scsi_report_supported_opcodes(&ccb->csio,
8410 				      /*retries*/ retry_count,
8411 				      /*cbfcnp*/ NULL,
8412 				      /*tag_action*/ MSG_SIMPLE_Q_TAG,
8413 				      /*options*/ options,
8414 				      /*req_opcode*/ opcode,
8415 				      /*req_service_action*/ service_action,
8416 				      /*data_ptr*/ buf,
8417 				      /*dxfer_len*/ alloc_len,
8418 				      /*sense_len*/ SSD_FULL_SIZE,
8419 				      /*timeout*/ timeout ? timeout : 10000);
8420 
8421 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8422 
8423 	if (retry_count != 0)
8424 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
8425 
8426 	if (cam_send_ccb(device, ccb) < 0) {
8427 		perror("error sending REPORT SUPPORTED OPERATION CODES");
8428 		retval = 1;
8429 		goto bailout;
8430 	}
8431 
8432 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8433 		if (verbosemode != 0)
8434 			cam_error_print(device, ccb, CAM_ESF_ALL,
8435 					CAM_EPF_ALL, stderr);
8436 
8437 		retval = 1;
8438 		goto bailout;
8439 	}
8440 
8441 	valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
8442 
8443 	if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
8444 	 && (valid_len >= sizeof(*all_hdr))) {
8445 		all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
8446 		avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
8447 	} else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
8448 		&& (valid_len >= sizeof(*one))) {
8449 		uint32_t cdb_length;
8450 
8451 		one = (struct scsi_report_supported_opcodes_one *)buf;
8452 		cdb_length = scsi_2btoul(one->cdb_length);
8453 		avail_len = sizeof(*one) + cdb_length;
8454 		if (one->support & RSO_ONE_CTDP) {
8455 			struct scsi_report_supported_opcodes_timeout *td;
8456 
8457 			td = (struct scsi_report_supported_opcodes_timeout *)
8458 			    &buf[avail_len];
8459 			if (valid_len >= (avail_len + sizeof(td->length))) {
8460 				avail_len += scsi_2btoul(td->length) +
8461 				    sizeof(td->length);
8462 			} else {
8463 				avail_len += sizeof(*td);
8464 			}
8465 		}
8466 	}
8467 
8468 	/*
8469 	 * avail_len could be zero if we didn't get enough data back from
8470 	 * thet target to determine
8471 	 */
8472 	if ((avail_len != 0)
8473 	 && (avail_len > valid_len)) {
8474 		alloc_len = avail_len;
8475 		goto retry_alloc;
8476 	}
8477 
8478 	*fill_len = valid_len;
8479 	*data_ptr = buf;
8480 bailout:
8481 	if (retval != 0)
8482 		free(buf);
8483 
8484 	cam_freeccb(ccb);
8485 
8486 	return (retval);
8487 }
8488 
8489 static int
8490 scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
8491 		   int req_sa, uint8_t *buf, uint32_t valid_len)
8492 {
8493 	struct scsi_report_supported_opcodes_one *one;
8494 	struct scsi_report_supported_opcodes_timeout *td;
8495 	uint32_t cdb_len = 0, td_len = 0;
8496 	const char *op_desc = NULL;
8497 	unsigned int i;
8498 	int retval = 0;
8499 
8500 	one = (struct scsi_report_supported_opcodes_one *)buf;
8501 
8502 	/*
8503 	 * If we don't have the full single opcode descriptor, no point in
8504 	 * continuing.
8505 	 */
8506 	if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8507 	    cdb_length)) {
8508 		warnx("Only %u bytes returned, not enough to verify support",
8509 		      valid_len);
8510 		retval = 1;
8511 		goto bailout;
8512 	}
8513 
8514 	op_desc = scsi_op_desc(req_opcode, &device->inq_data);
8515 
8516 	printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
8517 	       req_opcode);
8518 	if (sa_set != 0)
8519 		printf(", SA 0x%x", req_sa);
8520 	printf(": ");
8521 
8522 	switch (one->support & RSO_ONE_SUP_MASK) {
8523 	case RSO_ONE_SUP_UNAVAIL:
8524 		printf("No command support information currently available\n");
8525 		break;
8526 	case RSO_ONE_SUP_NOT_SUP:
8527 		printf("Command not supported\n");
8528 		retval = 1;
8529 		goto bailout;
8530 		break; /*NOTREACHED*/
8531 	case RSO_ONE_SUP_AVAIL:
8532 		printf("Command is supported, complies with a SCSI standard\n");
8533 		break;
8534 	case RSO_ONE_SUP_VENDOR:
8535 		printf("Command is supported, vendor-specific "
8536 		       "implementation\n");
8537 		break;
8538 	default:
8539 		printf("Unknown command support flags 0x%#x\n",
8540 		       one->support & RSO_ONE_SUP_MASK);
8541 		break;
8542 	}
8543 
8544 	/*
8545 	 * If we don't have the CDB length, it isn't exactly an error, the
8546 	 * command probably isn't supported.
8547 	 */
8548 	if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8549 	    cdb_usage))
8550 		goto bailout;
8551 
8552 	cdb_len = scsi_2btoul(one->cdb_length);
8553 
8554 	/*
8555 	 * If our valid data doesn't include the full reported length,
8556 	 * return.  The caller should have detected this and adjusted his
8557 	 * allocation length to get all of the available data.
8558 	 */
8559 	if (valid_len < sizeof(*one) + cdb_len) {
8560 		retval = 1;
8561 		goto bailout;
8562 	}
8563 
8564 	/*
8565 	 * If all we have is the opcode, there is no point in printing out
8566 	 * the usage bitmap.
8567 	 */
8568 	if (cdb_len <= 1) {
8569 		retval = 1;
8570 		goto bailout;
8571 	}
8572 
8573 	printf("CDB usage bitmap:");
8574 	for (i = 0; i < cdb_len; i++) {
8575 		printf(" %02x", one->cdb_usage[i]);
8576 	}
8577 	printf("\n");
8578 
8579 	/*
8580 	 * If we don't have a timeout descriptor, we're done.
8581 	 */
8582 	if ((one->support & RSO_ONE_CTDP) == 0)
8583 		goto bailout;
8584 
8585 	/*
8586 	 * If we don't have enough valid length to include the timeout
8587 	 * descriptor length, we're done.
8588 	 */
8589 	if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
8590 		goto bailout;
8591 
8592 	td = (struct scsi_report_supported_opcodes_timeout *)
8593 	    &buf[sizeof(*one) + cdb_len];
8594 	td_len = scsi_2btoul(td->length);
8595 	td_len += sizeof(td->length);
8596 
8597 	/*
8598 	 * If we don't have the full timeout descriptor, we're done.
8599 	 */
8600 	if (td_len < sizeof(*td))
8601 		goto bailout;
8602 
8603 	/*
8604 	 * If we don't have enough valid length to contain the full timeout
8605 	 * descriptor, we're done.
8606 	 */
8607 	if (valid_len < (sizeof(*one) + cdb_len + td_len))
8608 		goto bailout;
8609 
8610 	printf("Timeout information:\n");
8611 	printf("Command-specific:    0x%02x\n", td->cmd_specific);
8612 	printf("Nominal timeout:     %u seconds\n",
8613 	       scsi_4btoul(td->nominal_time));
8614 	printf("Recommended timeout: %u seconds\n",
8615 	       scsi_4btoul(td->recommended_time));
8616 
8617 bailout:
8618 	return (retval);
8619 }
8620 
8621 static int
8622 scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
8623 		 uint32_t valid_len)
8624 {
8625 	struct scsi_report_supported_opcodes_all *hdr;
8626 	struct scsi_report_supported_opcodes_descr *desc;
8627 	uint32_t avail_len = 0, used_len = 0;
8628 	uint8_t *cur_ptr;
8629 	int retval = 0;
8630 
8631 	if (valid_len < sizeof(*hdr)) {
8632 		warnx("%s: not enough returned data (%u bytes) opcode list",
8633 		      __func__, valid_len);
8634 		retval = 1;
8635 		goto bailout;
8636 	}
8637 	hdr = (struct scsi_report_supported_opcodes_all *)buf;
8638 	avail_len = scsi_4btoul(hdr->length);
8639 	avail_len += sizeof(hdr->length);
8640 	/*
8641 	 * Take the lesser of the amount of data the drive claims is
8642 	 * available, and the amount of data the HBA says was returned.
8643 	 */
8644 	avail_len = MIN(avail_len, valid_len);
8645 
8646 	used_len = sizeof(hdr->length);
8647 
8648 	printf("%-6s %4s %8s ",
8649 	       "Opcode", "SA", "CDB len" );
8650 
8651 	if (td_req != 0)
8652 		printf("%5s %6s %6s ", "CS", "Nom", "Rec");
8653 	printf(" Description\n");
8654 
8655 	while ((avail_len - used_len) > sizeof(*desc)) {
8656 		struct scsi_report_supported_opcodes_timeout *td;
8657 		uint32_t td_len;
8658 		const char *op_desc = NULL;
8659 
8660 		cur_ptr = &buf[used_len];
8661 		desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
8662 
8663 		op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
8664 		if (op_desc == NULL)
8665 			op_desc = "UNKNOWN";
8666 
8667 		printf("0x%02x   %#4x %8u ", desc->opcode,
8668 		       scsi_2btoul(desc->service_action),
8669 		       scsi_2btoul(desc->cdb_length));
8670 
8671 		used_len += sizeof(*desc);
8672 
8673 		if ((desc->flags & RSO_CTDP) == 0) {
8674 			printf(" %s\n", op_desc);
8675 			continue;
8676 		}
8677 
8678 		/*
8679 		 * If we don't have enough space to fit a timeout
8680 		 * descriptor, then we're done.
8681 		 */
8682 		if (avail_len - used_len < sizeof(*td)) {
8683 			used_len = avail_len;
8684 			printf(" %s\n", op_desc);
8685 			continue;
8686 		}
8687 		cur_ptr = &buf[used_len];
8688 		td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
8689 		td_len = scsi_2btoul(td->length);
8690 		td_len += sizeof(td->length);
8691 
8692 		used_len += td_len;
8693 		/*
8694 		 * If the given timeout descriptor length is less than what
8695 		 * we understand, skip it.
8696 		 */
8697 		if (td_len < sizeof(*td)) {
8698 			printf(" %s\n", op_desc);
8699 			continue;
8700 		}
8701 
8702 		printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
8703 		       scsi_4btoul(td->nominal_time),
8704 		       scsi_4btoul(td->recommended_time), op_desc);
8705 	}
8706 bailout:
8707 	return (retval);
8708 }
8709 
8710 static int
8711 scsiopcodes(struct cam_device *device, int argc, char **argv,
8712 	    char *combinedopt, int retry_count, int timeout, int verbosemode)
8713 {
8714 	int c;
8715 	uint32_t opcode = 0, service_action = 0;
8716 	int td_set = 0, opcode_set = 0, sa_set = 0;
8717 	int show_sa_errors = 1;
8718 	uint32_t valid_len = 0;
8719 	uint8_t *buf = NULL;
8720 	char *endptr;
8721 	int retval = 0;
8722 
8723 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8724 		switch (c) {
8725 		case 'N':
8726 			show_sa_errors = 0;
8727 			break;
8728 		case 'o':
8729 			opcode = strtoul(optarg, &endptr, 0);
8730 			if (*endptr != '\0') {
8731 				warnx("Invalid opcode \"%s\", must be a number",
8732 				      optarg);
8733 				retval = 1;
8734 				goto bailout;
8735 			}
8736 			if (opcode > 0xff) {
8737 				warnx("Invalid opcode 0x%#x, must be between"
8738 				      "0 and 0xff inclusive", opcode);
8739 				retval = 1;
8740 				goto bailout;
8741 			}
8742 			opcode_set = 1;
8743 			break;
8744 		case 's':
8745 			service_action = strtoul(optarg, &endptr, 0);
8746 			if (*endptr != '\0') {
8747 				warnx("Invalid service action \"%s\", must "
8748 				      "be a number", optarg);
8749 				retval = 1;
8750 				goto bailout;
8751 			}
8752 			if (service_action > 0xffff) {
8753 				warnx("Invalid service action 0x%#x, must "
8754 				      "be between 0 and 0xffff inclusive",
8755 				      service_action);
8756 				retval = 1;
8757 			}
8758 			sa_set = 1;
8759 			break;
8760 		case 'T':
8761 			td_set = 1;
8762 			break;
8763 		default:
8764 			break;
8765 		}
8766 	}
8767 
8768 	if ((sa_set != 0)
8769 	 && (opcode_set == 0)) {
8770 		warnx("You must specify an opcode with -o if a service "
8771 		      "action is given");
8772 		retval = 1;
8773 		goto bailout;
8774 	}
8775 	retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
8776 				sa_set, service_action, td_set, retry_count,
8777 				timeout, verbosemode, &valid_len, &buf);
8778 	if (retval != 0)
8779 		goto bailout;
8780 
8781 	if ((opcode_set != 0)
8782 	 || (sa_set != 0)) {
8783 		retval = scsiprintoneopcode(device, opcode, sa_set,
8784 					    service_action, buf, valid_len);
8785 	} else {
8786 		retval = scsiprintopcodes(device, td_set, buf, valid_len);
8787 	}
8788 
8789 bailout:
8790 	free(buf);
8791 
8792 	return (retval);
8793 }
8794 
8795 #endif /* MINIMALISTIC */
8796 
8797 static int
8798 scsireprobe(struct cam_device *device)
8799 {
8800 	union ccb *ccb;
8801 	int retval = 0;
8802 
8803 	ccb = cam_getccb(device);
8804 
8805 	if (ccb == NULL) {
8806 		warnx("%s: error allocating ccb", __func__);
8807 		return (1);
8808 	}
8809 
8810 	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8811 
8812 	ccb->ccb_h.func_code = XPT_REPROBE_LUN;
8813 
8814 	if (cam_send_ccb(device, ccb) < 0) {
8815 		warn("error sending XPT_REPROBE_LUN CCB");
8816 		retval = 1;
8817 		goto bailout;
8818 	}
8819 
8820 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8821 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
8822 		retval = 1;
8823 		goto bailout;
8824 	}
8825 
8826 bailout:
8827 	cam_freeccb(ccb);
8828 
8829 	return (retval);
8830 }
8831 
8832 void
8833 usage(int printlong)
8834 {
8835 
8836 	fprintf(printlong ? stdout : stderr,
8837 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
8838 "        camcontrol devlist    [-b] [-v]\n"
8839 #ifndef MINIMALISTIC
8840 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8841 "        camcontrol tur        [dev_id][generic args]\n"
8842 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
8843 "        camcontrol identify   [dev_id][generic args] [-v]\n"
8844 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8845 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8846 "                              [-q] [-s]\n"
8847 "        camcontrol start      [dev_id][generic args]\n"
8848 "        camcontrol stop       [dev_id][generic args]\n"
8849 "        camcontrol load       [dev_id][generic args]\n"
8850 "        camcontrol eject      [dev_id][generic args]\n"
8851 "        camcontrol reprobe    [dev_id][generic args]\n"
8852 #endif /* MINIMALISTIC */
8853 "        camcontrol rescan     <all | bus[:target:lun]>\n"
8854 "        camcontrol reset      <all | bus[:target:lun]>\n"
8855 #ifndef MINIMALISTIC
8856 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
8857 "                              [-q][-s][-S offset][-X]\n"
8858 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
8859 "                              [-P pagectl][-e | -b][-d]\n"
8860 "        camcontrol cmd        [dev_id][generic args]\n"
8861 "                              <-a cmd [args] | -c cmd [args]>\n"
8862 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8863 "        camcontrol smpcmd     [dev_id][generic args]\n"
8864 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
8865 "        camcontrol smprg      [dev_id][generic args][-l]\n"
8866 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
8867 "                              [-o operation][-d name][-m rate][-M rate]\n"
8868 "                              [-T pp_timeout][-a enable|disable]\n"
8869 "                              [-A enable|disable][-s enable|disable]\n"
8870 "                              [-S enable|disable]\n"
8871 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8872 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8873 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
8874 "                              <all|bus[:target[:lun]]|off>\n"
8875 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
8876 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
8877 "                              [-D <enable|disable>][-M mode][-O offset]\n"
8878 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
8879 "                              [-U][-W bus_width]\n"
8880 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
8881 "        camcontrol sanitize   [dev_id][generic args]\n"
8882 "                              [-a overwrite|block|crypto|exitfailure]\n"
8883 "                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8884 "                              [-y]\n"
8885 "        camcontrol idle       [dev_id][generic args][-t time]\n"
8886 "        camcontrol standby    [dev_id][generic args][-t time]\n"
8887 "        camcontrol sleep      [dev_id][generic args]\n"
8888 "        camcontrol apm        [dev_id][generic args][-l level]\n"
8889 "        camcontrol aam        [dev_id][generic args][-l level]\n"
8890 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
8891 "                              [-s][-y]\n"
8892 "        camcontrol security   [dev_id][generic args]\n"
8893 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8894 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8895 "                              [-U <user|master>] [-y]\n"
8896 "        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8897 "                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
8898 "        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
8899 "                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8900 "                              [-s scope][-S][-T type][-U]\n"
8901 "        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
8902 "                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
8903 "                              [-p part][-s start][-T type][-V vol]\n"
8904 "        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
8905 "                              [-N][-T]\n"
8906 "        camcontrol zone       [dev_id][generic args]<-c cmd> [-a] [-l LBA]\n"
8907 "                              [-o rep_opts] [-P print_opts]\n"
8908 "        camcontrol epc        [dev_id][generic_args]<-c cmd> [-d] [-D] [-e]\n"
8909 "                              [-H] [-p power_cond] [-P] [-r rst_src] [-s]\n"
8910 "                              [-S power_src] [-T timer]\n"
8911 #endif /* MINIMALISTIC */
8912 "        camcontrol help\n");
8913 	if (!printlong)
8914 		return;
8915 #ifndef MINIMALISTIC
8916 	fprintf(stdout,
8917 "Specify one of the following options:\n"
8918 "devlist     list all CAM devices\n"
8919 "periphlist  list all CAM peripheral drivers attached to a device\n"
8920 "tur         send a test unit ready to the named device\n"
8921 "inquiry     send a SCSI inquiry command to the named device\n"
8922 "identify    send a ATA identify command to the named device\n"
8923 "reportluns  send a SCSI report luns command to the device\n"
8924 "readcap     send a SCSI read capacity command to the device\n"
8925 "start       send a Start Unit command to the device\n"
8926 "stop        send a Stop Unit command to the device\n"
8927 "load        send a Start Unit command to the device with the load bit set\n"
8928 "eject       send a Stop Unit command to the device with the eject bit set\n"
8929 "reprobe     update capacity information of the given device\n"
8930 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
8931 "reset       reset all busses, the given bus, or bus:target:lun\n"
8932 "defects     read the defect list of the specified device\n"
8933 "modepage    display or edit (-e) the given mode page\n"
8934 "cmd         send the given SCSI command, may need -i or -o as well\n"
8935 "smpcmd      send the given SMP command, requires -o and -i\n"
8936 "smprg       send the SMP Report General command\n"
8937 "smppc       send the SMP PHY Control command, requires -p\n"
8938 "smpphylist  display phys attached to a SAS expander\n"
8939 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
8940 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
8941 "tags        report or set the number of transaction slots for a device\n"
8942 "negotiate   report or set device negotiation parameters\n"
8943 "format      send the SCSI FORMAT UNIT command to the named device\n"
8944 "sanitize    send the SCSI SANITIZE command to the named device\n"
8945 "idle        send the ATA IDLE command to the named device\n"
8946 "standby     send the ATA STANDBY command to the named device\n"
8947 "sleep       send the ATA SLEEP command to the named device\n"
8948 "fwdownload  program firmware of the named device with the given image\n"
8949 "security    report or send ATA security commands to the named device\n"
8950 "persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8951 "attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
8952 "opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
8953 "zone        manage Zoned Block (Shingled) devices\n"
8954 "epc         send ATA Extended Power Conditions commands\n"
8955 "help        this message\n"
8956 "Device Identifiers:\n"
8957 "bus:target        specify the bus and target, lun defaults to 0\n"
8958 "bus:target:lun    specify the bus, target and lun\n"
8959 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
8960 "Generic arguments:\n"
8961 "-v                be verbose, print out sense information\n"
8962 "-t timeout        command timeout in seconds, overrides default timeout\n"
8963 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
8964 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
8965 "-E                have the kernel attempt to perform SCSI error recovery\n"
8966 "-C count          specify the SCSI command retry count (needs -E to work)\n"
8967 "modepage arguments:\n"
8968 "-l                list all available mode pages\n"
8969 "-m page           specify the mode page to view or edit\n"
8970 "-e                edit the specified mode page\n"
8971 "-b                force view to binary mode\n"
8972 "-d                disable block descriptors for mode sense\n"
8973 "-P pgctl          page control field 0-3\n"
8974 "defects arguments:\n"
8975 "-f format         specify defect list format (block, bfi or phys)\n"
8976 "-G                get the grown defect list\n"
8977 "-P                get the permanent defect list\n"
8978 "inquiry arguments:\n"
8979 "-D                get the standard inquiry data\n"
8980 "-S                get the serial number\n"
8981 "-R                get the transfer rate, etc.\n"
8982 "reportluns arguments:\n"
8983 "-c                only report a count of available LUNs\n"
8984 "-l                only print out luns, and not a count\n"
8985 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
8986 "readcap arguments\n"
8987 "-b                only report the blocksize\n"
8988 "-h                human readable device size, base 2\n"
8989 "-H                human readable device size, base 10\n"
8990 "-N                print the number of blocks instead of last block\n"
8991 "-q                quiet, print numbers only\n"
8992 "-s                only report the last block/device size\n"
8993 "cmd arguments:\n"
8994 "-c cdb [args]     specify the SCSI CDB\n"
8995 "-i len fmt        specify input data and input data format\n"
8996 "-o len fmt [args] specify output data and output data fmt\n"
8997 "smpcmd arguments:\n"
8998 "-r len fmt [args] specify the SMP command to be sent\n"
8999 "-R len fmt [args] specify SMP response format\n"
9000 "smprg arguments:\n"
9001 "-l                specify the long response format\n"
9002 "smppc arguments:\n"
9003 "-p phy            specify the PHY to operate on\n"
9004 "-l                specify the long request/response format\n"
9005 "-o operation      specify the phy control operation\n"
9006 "-d name           set the attached device name\n"
9007 "-m rate           set the minimum physical link rate\n"
9008 "-M rate           set the maximum physical link rate\n"
9009 "-T pp_timeout     set the partial pathway timeout value\n"
9010 "-a enable|disable enable or disable SATA slumber\n"
9011 "-A enable|disable enable or disable SATA partial phy power\n"
9012 "-s enable|disable enable or disable SAS slumber\n"
9013 "-S enable|disable enable or disable SAS partial phy power\n"
9014 "smpphylist arguments:\n"
9015 "-l                specify the long response format\n"
9016 "-q                only print phys with attached devices\n"
9017 "smpmaninfo arguments:\n"
9018 "-l                specify the long response format\n"
9019 "debug arguments:\n"
9020 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
9021 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
9022 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
9023 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
9024 "tags arguments:\n"
9025 "-N tags           specify the number of tags to use for this device\n"
9026 "-q                be quiet, don't report the number of tags\n"
9027 "-v                report a number of tag-related parameters\n"
9028 "negotiate arguments:\n"
9029 "-a                send a test unit ready after negotiation\n"
9030 "-c                report/set current negotiation settings\n"
9031 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
9032 "-M mode           set ATA mode\n"
9033 "-O offset         set command delay offset\n"
9034 "-q                be quiet, don't report anything\n"
9035 "-R syncrate       synchronization rate in MHz\n"
9036 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
9037 "-U                report/set user negotiation settings\n"
9038 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
9039 "-v                also print a Path Inquiry CCB for the controller\n"
9040 "format arguments:\n"
9041 "-q                be quiet, don't print status messages\n"
9042 "-r                run in report only mode\n"
9043 "-w                don't send immediate format command\n"
9044 "-y                don't ask any questions\n"
9045 "sanitize arguments:\n"
9046 "-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
9047 "-c passes         overwrite passes to perform (1 to 31)\n"
9048 "-I                invert overwrite pattern after each pass\n"
9049 "-P pattern        path to overwrite pattern file\n"
9050 "-q                be quiet, don't print status messages\n"
9051 "-r                run in report only mode\n"
9052 "-U                run operation in unrestricted completion exit mode\n"
9053 "-w                don't send immediate sanitize command\n"
9054 "-y                don't ask any questions\n"
9055 "idle/standby arguments:\n"
9056 "-t <arg>          number of seconds before respective state.\n"
9057 "fwdownload arguments:\n"
9058 "-f fw_image       path to firmware image file\n"
9059 "-q                don't print informational messages, only errors\n"
9060 "-s                run in simulation mode\n"
9061 "-v                print info for every firmware segment sent to device\n"
9062 "-y                don't ask any questions\n"
9063 "security arguments:\n"
9064 "-d pwd            disable security using the given password for the selected\n"
9065 "                  user\n"
9066 "-e pwd            erase the device using the given pwd for the selected user\n"
9067 "-f                freeze the security configuration of the specified device\n"
9068 "-h pwd            enhanced erase the device using the given pwd for the\n"
9069 "                  selected user\n"
9070 "-k pwd            unlock the device using the given pwd for the selected\n"
9071 "                  user\n"
9072 "-l <high|maximum> specifies which security level to set: high or maximum\n"
9073 "-q                be quiet, do not print any status messages\n"
9074 "-s pwd            password the device (enable security) using the given\n"
9075 "                  pwd for the selected user\n"
9076 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
9077 "-U <user|master>  specifies which user to set: user or master\n"
9078 "-y                don't ask any questions\n"
9079 "hpa arguments:\n"
9080 "-f                freeze the HPA configuration of the device\n"
9081 "-l                lock the HPA configuration of the device\n"
9082 "-P                make the HPA max sectors persist\n"
9083 "-p pwd            Set the HPA configuration password required for unlock\n"
9084 "                  calls\n"
9085 "-q                be quiet, do not print any status messages\n"
9086 "-s sectors        configures the maximum user accessible sectors of the\n"
9087 "                  device\n"
9088 "-U pwd            unlock the HPA configuration of the device\n"
9089 "-y                don't ask any questions\n"
9090 "persist arguments:\n"
9091 "-i action         specify read_keys, read_reservation, report_cap, or\n"
9092 "                  read_full_status\n"
9093 "-o action         specify register, register_ignore, reserve, release,\n"
9094 "                  clear, preempt, preempt_abort, register_move, replace_lost\n"
9095 "-a                set the All Target Ports (ALL_TG_PT) bit\n"
9096 "-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
9097 "-k key            specify the Reservation Key\n"
9098 "-K sa_key         specify the Service Action Reservation Key\n"
9099 "-p                set the Activate Persist Through Power Loss bit\n"
9100 "-R rtp            specify the Relative Target Port\n"
9101 "-s scope          specify the scope: lun, extent, element or a number\n"
9102 "-S                specify Transport ID for register, requires -I\n"
9103 "-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
9104 "                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
9105 "-U                unregister the current initiator for register_move\n"
9106 "attrib arguments:\n"
9107 "-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
9108 "                  supp_attr\n"
9109 "-w attr           specify an attribute to write, one -w argument per attr\n"
9110 "-a attr_num       only display this attribute number\n"
9111 "-c                get cached attributes\n"
9112 "-e elem_addr      request attributes for the given element in a changer\n"
9113 "-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
9114 "                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
9115 "                  field_none, field_desc, field_num, field_size, field_rw\n"
9116 "-p partition      request attributes for the given partition\n"
9117 "-s start_attr     request attributes starting at the given number\n"
9118 "-T elem_type      specify the element type (used with -e)\n"
9119 "-V logical_vol    specify the logical volume ID\n"
9120 "opcodes arguments:\n"
9121 "-o opcode         specify the individual opcode to list\n"
9122 "-s service_action specify the service action for the opcode\n"
9123 "-N                do not return SCSI error for unsupported SA\n"
9124 "-T                request nominal and recommended timeout values\n"
9125 "zone arguments:\n"
9126 "-c cmd            required: rz, open, close, finish, or rwp\n"
9127 "-a                apply the action to all zones\n"
9128 "-l LBA            specify the zone starting LBA\n"
9129 "-o rep_opts       report zones options: all, empty, imp_open, exp_open,\n"
9130 "                  closed, full, ro, offline, reset, nonseq, nonwp\n"
9131 "-P print_opt      report zones printing:  normal, summary, script\n"
9132 "epc arguments:\n"
9133 "-c cmd            required: restore, goto, timer, state, enable, disable,\n"
9134 "                  source, status, list\n"
9135 "-d                disable power mode (timer, state)\n"
9136 "-D                delayed entry (goto)\n"
9137 "-e                enable power mode (timer, state)\n"
9138 "-H                hold power mode (goto)\n"
9139 "-p power_cond     Idle_a, Idle_b, Idle_c, Standby_y, Standby_z (timer,\n"
9140 "                  state, goto)\n"
9141 "-P                only display power mode (status)\n"
9142 "-r rst_src        restore settings from: default, saved (restore)\n"
9143 "-s                save mode (timer, state, restore)\n"
9144 "-S power_src      set power source: battery, nonbattery (source)\n"
9145 "-T timer          set timer, seconds, .1 sec resolution (timer)\n"
9146 );
9147 #endif /* MINIMALISTIC */
9148 }
9149 
9150 int
9151 main(int argc, char **argv)
9152 {
9153 	int c;
9154 	char *device = NULL;
9155 	int unit = 0;
9156 	struct cam_device *cam_dev = NULL;
9157 	int timeout = 0, retry_count = 1;
9158 	camcontrol_optret optreturn;
9159 	char *tstr;
9160 	const char *mainopt = "C:En:t:u:v";
9161 	const char *subopt = NULL;
9162 	char combinedopt[256];
9163 	int error = 0, optstart = 2;
9164 	int devopen = 1;
9165 #ifndef MINIMALISTIC
9166 	path_id_t bus;
9167 	target_id_t target;
9168 	lun_id_t lun;
9169 #endif /* MINIMALISTIC */
9170 
9171 	cmdlist = CAM_CMD_NONE;
9172 	arglist = CAM_ARG_NONE;
9173 
9174 	if (argc < 2) {
9175 		usage(0);
9176 		exit(1);
9177 	}
9178 
9179 	/*
9180 	 * Get the base option.
9181 	 */
9182 	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
9183 
9184 	if (optreturn == CC_OR_AMBIGUOUS) {
9185 		warnx("ambiguous option %s", argv[1]);
9186 		usage(0);
9187 		exit(1);
9188 	} else if (optreturn == CC_OR_NOT_FOUND) {
9189 		warnx("option %s not found", argv[1]);
9190 		usage(0);
9191 		exit(1);
9192 	}
9193 
9194 	/*
9195 	 * Ahh, getopt(3) is a pain.
9196 	 *
9197 	 * This is a gross hack.  There really aren't many other good
9198 	 * options (excuse the pun) for parsing options in a situation like
9199 	 * this.  getopt is kinda braindead, so you end up having to run
9200 	 * through the options twice, and give each invocation of getopt
9201 	 * the option string for the other invocation.
9202 	 *
9203 	 * You would think that you could just have two groups of options.
9204 	 * The first group would get parsed by the first invocation of
9205 	 * getopt, and the second group would get parsed by the second
9206 	 * invocation of getopt.  It doesn't quite work out that way.  When
9207 	 * the first invocation of getopt finishes, it leaves optind pointing
9208 	 * to the argument _after_ the first argument in the second group.
9209 	 * So when the second invocation of getopt comes around, it doesn't
9210 	 * recognize the first argument it gets and then bails out.
9211 	 *
9212 	 * A nice alternative would be to have a flag for getopt that says
9213 	 * "just keep parsing arguments even when you encounter an unknown
9214 	 * argument", but there isn't one.  So there's no real clean way to
9215 	 * easily parse two sets of arguments without having one invocation
9216 	 * of getopt know about the other.
9217 	 *
9218 	 * Without this hack, the first invocation of getopt would work as
9219 	 * long as the generic arguments are first, but the second invocation
9220 	 * (in the subfunction) would fail in one of two ways.  In the case
9221 	 * where you don't set optreset, it would fail because optind may be
9222 	 * pointing to the argument after the one it should be pointing at.
9223 	 * In the case where you do set optreset, and reset optind, it would
9224 	 * fail because getopt would run into the first set of options, which
9225 	 * it doesn't understand.
9226 	 *
9227 	 * All of this would "sort of" work if you could somehow figure out
9228 	 * whether optind had been incremented one option too far.  The
9229 	 * mechanics of that, however, are more daunting than just giving
9230 	 * both invocations all of the expect options for either invocation.
9231 	 *
9232 	 * Needless to say, I wouldn't mind if someone invented a better
9233 	 * (non-GPL!) command line parsing interface than getopt.  I
9234 	 * wouldn't mind if someone added more knobs to getopt to make it
9235 	 * work better.  Who knows, I may talk myself into doing it someday,
9236 	 * if the standards weenies let me.  As it is, it just leads to
9237 	 * hackery like this and causes people to avoid it in some cases.
9238 	 *
9239 	 * KDM, September 8th, 1998
9240 	 */
9241 	if (subopt != NULL)
9242 		sprintf(combinedopt, "%s%s", mainopt, subopt);
9243 	else
9244 		sprintf(combinedopt, "%s", mainopt);
9245 
9246 	/*
9247 	 * For these options we do not parse optional device arguments and
9248 	 * we do not open a passthrough device.
9249 	 */
9250 	if ((cmdlist == CAM_CMD_RESCAN)
9251 	 || (cmdlist == CAM_CMD_RESET)
9252 	 || (cmdlist == CAM_CMD_DEVTREE)
9253 	 || (cmdlist == CAM_CMD_USAGE)
9254 	 || (cmdlist == CAM_CMD_DEBUG))
9255 		devopen = 0;
9256 
9257 #ifndef MINIMALISTIC
9258 	if ((devopen == 1)
9259 	 && (argc > 2 && argv[2][0] != '-')) {
9260 		char name[30];
9261 		int rv;
9262 
9263 		if (isdigit(argv[2][0])) {
9264 			/* device specified as bus:target[:lun] */
9265 			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9266 			if (rv < 2)
9267 				errx(1, "numeric device specification must "
9268 				     "be either bus:target, or "
9269 				     "bus:target:lun");
9270 			/* default to 0 if lun was not specified */
9271 			if ((arglist & CAM_ARG_LUN) == 0) {
9272 				lun = 0;
9273 				arglist |= CAM_ARG_LUN;
9274 			}
9275 			optstart++;
9276 		} else {
9277 			if (cam_get_device(argv[2], name, sizeof name, &unit)
9278 			    == -1)
9279 				errx(1, "%s", cam_errbuf);
9280 			device = strdup(name);
9281 			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9282 			optstart++;
9283 		}
9284 	}
9285 #endif /* MINIMALISTIC */
9286 	/*
9287 	 * Start getopt processing at argv[2/3], since we've already
9288 	 * accepted argv[1..2] as the command name, and as a possible
9289 	 * device name.
9290 	 */
9291 	optind = optstart;
9292 
9293 	/*
9294 	 * Now we run through the argument list looking for generic
9295 	 * options, and ignoring options that possibly belong to
9296 	 * subfunctions.
9297 	 */
9298 	while ((c = getopt(argc, argv, combinedopt))!= -1){
9299 		switch(c) {
9300 			case 'C':
9301 				retry_count = strtol(optarg, NULL, 0);
9302 				if (retry_count < 0)
9303 					errx(1, "retry count %d is < 0",
9304 					     retry_count);
9305 				arglist |= CAM_ARG_RETRIES;
9306 				break;
9307 			case 'E':
9308 				arglist |= CAM_ARG_ERR_RECOVER;
9309 				break;
9310 			case 'n':
9311 				arglist |= CAM_ARG_DEVICE;
9312 				tstr = optarg;
9313 				while (isspace(*tstr) && (*tstr != '\0'))
9314 					tstr++;
9315 				device = (char *)strdup(tstr);
9316 				break;
9317 			case 't':
9318 				timeout = strtol(optarg, NULL, 0);
9319 				if (timeout < 0)
9320 					errx(1, "invalid timeout %d", timeout);
9321 				/* Convert the timeout from seconds to ms */
9322 				timeout *= 1000;
9323 				arglist |= CAM_ARG_TIMEOUT;
9324 				break;
9325 			case 'u':
9326 				arglist |= CAM_ARG_UNIT;
9327 				unit = strtol(optarg, NULL, 0);
9328 				break;
9329 			case 'v':
9330 				arglist |= CAM_ARG_VERBOSE;
9331 				break;
9332 			default:
9333 				break;
9334 		}
9335 	}
9336 
9337 #ifndef MINIMALISTIC
9338 	/*
9339 	 * For most commands we'll want to open the passthrough device
9340 	 * associated with the specified device.  In the case of the rescan
9341 	 * commands, we don't use a passthrough device at all, just the
9342 	 * transport layer device.
9343 	 */
9344 	if (devopen == 1) {
9345 		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
9346 		 && (((arglist & CAM_ARG_DEVICE) == 0)
9347 		  || ((arglist & CAM_ARG_UNIT) == 0))) {
9348 			errx(1, "subcommand \"%s\" requires a valid device "
9349 			     "identifier", argv[1]);
9350 		}
9351 
9352 		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
9353 				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
9354 				cam_open_spec_device(device,unit,O_RDWR,NULL)))
9355 		     == NULL)
9356 			errx(1,"%s", cam_errbuf);
9357 	}
9358 #endif /* MINIMALISTIC */
9359 
9360 	/*
9361 	 * Reset optind to 2, and reset getopt, so these routines can parse
9362 	 * the arguments again.
9363 	 */
9364 	optind = optstart;
9365 	optreset = 1;
9366 
9367 	switch(cmdlist) {
9368 #ifndef MINIMALISTIC
9369 		case CAM_CMD_DEVLIST:
9370 			error = getdevlist(cam_dev);
9371 			break;
9372 		case CAM_CMD_HPA:
9373 			error = atahpa(cam_dev, retry_count, timeout,
9374 				       argc, argv, combinedopt);
9375 			break;
9376 #endif /* MINIMALISTIC */
9377 		case CAM_CMD_DEVTREE:
9378 			error = getdevtree(argc, argv, combinedopt);
9379 			break;
9380 #ifndef MINIMALISTIC
9381 		case CAM_CMD_TUR:
9382 			error = testunitready(cam_dev, retry_count, timeout, 0);
9383 			break;
9384 		case CAM_CMD_INQUIRY:
9385 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
9386 					      retry_count, timeout);
9387 			break;
9388 		case CAM_CMD_IDENTIFY:
9389 			error = ataidentify(cam_dev, retry_count, timeout);
9390 			break;
9391 		case CAM_CMD_STARTSTOP:
9392 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
9393 					  arglist & CAM_ARG_EJECT, retry_count,
9394 					  timeout);
9395 			break;
9396 #endif /* MINIMALISTIC */
9397 		case CAM_CMD_RESCAN:
9398 			error = dorescan_or_reset(argc, argv, 1);
9399 			break;
9400 		case CAM_CMD_RESET:
9401 			error = dorescan_or_reset(argc, argv, 0);
9402 			break;
9403 #ifndef MINIMALISTIC
9404 		case CAM_CMD_READ_DEFECTS:
9405 			error = readdefects(cam_dev, argc, argv, combinedopt,
9406 					    retry_count, timeout);
9407 			break;
9408 		case CAM_CMD_MODE_PAGE:
9409 			modepage(cam_dev, argc, argv, combinedopt,
9410 				 retry_count, timeout);
9411 			break;
9412 		case CAM_CMD_SCSI_CMD:
9413 			error = scsicmd(cam_dev, argc, argv, combinedopt,
9414 					retry_count, timeout);
9415 			break;
9416 		case CAM_CMD_SMP_CMD:
9417 			error = smpcmd(cam_dev, argc, argv, combinedopt,
9418 				       retry_count, timeout);
9419 			break;
9420 		case CAM_CMD_SMP_RG:
9421 			error = smpreportgeneral(cam_dev, argc, argv,
9422 						 combinedopt, retry_count,
9423 						 timeout);
9424 			break;
9425 		case CAM_CMD_SMP_PC:
9426 			error = smpphycontrol(cam_dev, argc, argv, combinedopt,
9427 					      retry_count, timeout);
9428 			break;
9429 		case CAM_CMD_SMP_PHYLIST:
9430 			error = smpphylist(cam_dev, argc, argv, combinedopt,
9431 					   retry_count, timeout);
9432 			break;
9433 		case CAM_CMD_SMP_MANINFO:
9434 			error = smpmaninfo(cam_dev, argc, argv, combinedopt,
9435 					   retry_count, timeout);
9436 			break;
9437 		case CAM_CMD_DEBUG:
9438 			error = camdebug(argc, argv, combinedopt);
9439 			break;
9440 		case CAM_CMD_TAG:
9441 			error = tagcontrol(cam_dev, argc, argv, combinedopt);
9442 			break;
9443 		case CAM_CMD_RATE:
9444 			error = ratecontrol(cam_dev, retry_count, timeout,
9445 					    argc, argv, combinedopt);
9446 			break;
9447 		case CAM_CMD_FORMAT:
9448 			error = scsiformat(cam_dev, argc, argv,
9449 					   combinedopt, retry_count, timeout);
9450 			break;
9451 		case CAM_CMD_REPORTLUNS:
9452 			error = scsireportluns(cam_dev, argc, argv,
9453 					       combinedopt, retry_count,
9454 					       timeout);
9455 			break;
9456 		case CAM_CMD_READCAP:
9457 			error = scsireadcapacity(cam_dev, argc, argv,
9458 						 combinedopt, retry_count,
9459 						 timeout);
9460 			break;
9461 		case CAM_CMD_IDLE:
9462 		case CAM_CMD_STANDBY:
9463 		case CAM_CMD_SLEEP:
9464 			error = atapm(cam_dev, argc, argv,
9465 				      combinedopt, retry_count, timeout);
9466 			break;
9467 		case CAM_CMD_APM:
9468 		case CAM_CMD_AAM:
9469 			error = ataaxm(cam_dev, argc, argv,
9470 				      combinedopt, retry_count, timeout);
9471 			break;
9472 		case CAM_CMD_SECURITY:
9473 			error = atasecurity(cam_dev, retry_count, timeout,
9474 					    argc, argv, combinedopt);
9475 			break;
9476 		case CAM_CMD_DOWNLOAD_FW:
9477 			error = fwdownload(cam_dev, argc, argv, combinedopt,
9478 			    arglist & CAM_ARG_VERBOSE, retry_count, timeout);
9479 			break;
9480 		case CAM_CMD_SANITIZE:
9481 			error = scsisanitize(cam_dev, argc, argv,
9482 					     combinedopt, retry_count, timeout);
9483 			break;
9484 		case CAM_CMD_PERSIST:
9485 			error = scsipersist(cam_dev, argc, argv, combinedopt,
9486 			    retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9487 			    arglist & CAM_ARG_ERR_RECOVER);
9488 			break;
9489 		case CAM_CMD_ATTRIB:
9490 			error = scsiattrib(cam_dev, argc, argv, combinedopt,
9491 			    retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9492 			    arglist & CAM_ARG_ERR_RECOVER);
9493 			break;
9494 		case CAM_CMD_OPCODES:
9495 			error = scsiopcodes(cam_dev, argc, argv, combinedopt,
9496 			    retry_count, timeout, arglist & CAM_ARG_VERBOSE);
9497 			break;
9498 		case CAM_CMD_REPROBE:
9499 			error = scsireprobe(cam_dev);
9500 			break;
9501 		case CAM_CMD_ZONE:
9502 			error = zone(cam_dev, argc, argv, combinedopt,
9503 			    retry_count, timeout, arglist & CAM_ARG_VERBOSE);
9504 			break;
9505 		case CAM_CMD_EPC:
9506 			error = epc(cam_dev, argc, argv, combinedopt,
9507 			    retry_count, timeout, arglist & CAM_ARG_VERBOSE);
9508 			break;
9509 #endif /* MINIMALISTIC */
9510 		case CAM_CMD_USAGE:
9511 			usage(1);
9512 			break;
9513 		default:
9514 			usage(0);
9515 			error = 1;
9516 			break;
9517 	}
9518 
9519 	if (cam_dev != NULL)
9520 		cam_close_device(cam_dev);
9521 
9522 	exit(error);
9523 }
9524