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