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