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