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