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