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