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