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