xref: /freebsd/sbin/camcontrol/camcontrol.c (revision e14ddd1f16e7e5788392c50de21ea7c927e0690c)
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/endian.h>
36 #include <sys/sbuf.h>
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <inttypes.h>
43 #include <limits.h>
44 #include <fcntl.h>
45 #include <ctype.h>
46 #include <err.h>
47 #include <libutil.h>
48 
49 #include <cam/cam.h>
50 #include <cam/cam_debug.h>
51 #include <cam/cam_ccb.h>
52 #include <cam/scsi/scsi_all.h>
53 #include <cam/scsi/scsi_da.h>
54 #include <cam/scsi/scsi_pass.h>
55 #include <cam/scsi/scsi_message.h>
56 #include <cam/scsi/smp_all.h>
57 #include <cam/ata/ata_all.h>
58 #include <camlib.h>
59 #include "camcontrol.h"
60 
61 typedef enum {
62 	CAM_CMD_NONE		= 0x00000000,
63 	CAM_CMD_DEVLIST		= 0x00000001,
64 	CAM_CMD_TUR		= 0x00000002,
65 	CAM_CMD_INQUIRY		= 0x00000003,
66 	CAM_CMD_STARTSTOP	= 0x00000004,
67 	CAM_CMD_RESCAN		= 0x00000005,
68 	CAM_CMD_READ_DEFECTS	= 0x00000006,
69 	CAM_CMD_MODE_PAGE	= 0x00000007,
70 	CAM_CMD_SCSI_CMD	= 0x00000008,
71 	CAM_CMD_DEVTREE		= 0x00000009,
72 	CAM_CMD_USAGE		= 0x0000000a,
73 	CAM_CMD_DEBUG		= 0x0000000b,
74 	CAM_CMD_RESET		= 0x0000000c,
75 	CAM_CMD_FORMAT		= 0x0000000d,
76 	CAM_CMD_TAG		= 0x0000000e,
77 	CAM_CMD_RATE		= 0x0000000f,
78 	CAM_CMD_DETACH		= 0x00000010,
79 	CAM_CMD_REPORTLUNS	= 0x00000011,
80 	CAM_CMD_READCAP		= 0x00000012,
81 	CAM_CMD_IDENTIFY	= 0x00000013,
82 	CAM_CMD_IDLE		= 0x00000014,
83 	CAM_CMD_STANDBY		= 0x00000015,
84 	CAM_CMD_SLEEP		= 0x00000016,
85 	CAM_CMD_SMP_CMD		= 0x00000017,
86 	CAM_CMD_SMP_RG		= 0x00000018,
87 	CAM_CMD_SMP_PC		= 0x00000019,
88 	CAM_CMD_SMP_PHYLIST	= 0x0000001a,
89 	CAM_CMD_SMP_MANINFO	= 0x0000001b,
90 	CAM_CMD_DOWNLOAD_FW	= 0x0000001c,
91 	CAM_CMD_SECURITY	= 0x0000001d
92 } cam_cmdmask;
93 
94 typedef enum {
95 	CAM_ARG_NONE		= 0x00000000,
96 	CAM_ARG_VERBOSE		= 0x00000001,
97 	CAM_ARG_DEVICE		= 0x00000002,
98 	CAM_ARG_BUS		= 0x00000004,
99 	CAM_ARG_TARGET		= 0x00000008,
100 	CAM_ARG_LUN		= 0x00000010,
101 	CAM_ARG_EJECT		= 0x00000020,
102 	CAM_ARG_UNIT		= 0x00000040,
103 	CAM_ARG_FORMAT_BLOCK	= 0x00000080,
104 	CAM_ARG_FORMAT_BFI	= 0x00000100,
105 	CAM_ARG_FORMAT_PHYS	= 0x00000200,
106 	CAM_ARG_PLIST		= 0x00000400,
107 	CAM_ARG_GLIST		= 0x00000800,
108 	CAM_ARG_GET_SERIAL	= 0x00001000,
109 	CAM_ARG_GET_STDINQ	= 0x00002000,
110 	CAM_ARG_GET_XFERRATE	= 0x00004000,
111 	CAM_ARG_INQ_MASK	= 0x00007000,
112 	CAM_ARG_MODE_EDIT	= 0x00008000,
113 	CAM_ARG_PAGE_CNTL	= 0x00010000,
114 	CAM_ARG_TIMEOUT		= 0x00020000,
115 	CAM_ARG_CMD_IN		= 0x00040000,
116 	CAM_ARG_CMD_OUT		= 0x00080000,
117 	CAM_ARG_DBD		= 0x00100000,
118 	CAM_ARG_ERR_RECOVER	= 0x00200000,
119 	CAM_ARG_RETRIES		= 0x00400000,
120 	CAM_ARG_START_UNIT	= 0x00800000,
121 	CAM_ARG_DEBUG_INFO	= 0x01000000,
122 	CAM_ARG_DEBUG_TRACE	= 0x02000000,
123 	CAM_ARG_DEBUG_SUBTRACE	= 0x04000000,
124 	CAM_ARG_DEBUG_CDB	= 0x08000000,
125 	CAM_ARG_DEBUG_XPT	= 0x10000000,
126 	CAM_ARG_DEBUG_PERIPH	= 0x20000000,
127 	CAM_ARG_DEBUG_PROBE	= 0x40000000,
128 } cam_argmask;
129 
130 struct camcontrol_opts {
131 	const char	*optname;
132 	uint32_t	cmdnum;
133 	cam_argmask	argnum;
134 	const char	*subopt;
135 };
136 
137 #ifndef MINIMALISTIC
138 static const char scsicmd_opts[] = "a:c:dfi:o:r";
139 static const char readdefect_opts[] = "f:GP";
140 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
141 static const char smprg_opts[] = "l";
142 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
143 static const char smpphylist_opts[] = "lq";
144 static char pwd_opt;
145 #endif
146 
147 static struct camcontrol_opts option_table[] = {
148 #ifndef MINIMALISTIC
149 	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
150 	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
151 	{"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
152 	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
153 	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
154 	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
155 	{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
156 	{"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
157 	{"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
158 #endif /* MINIMALISTIC */
159 	{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
160 	{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
161 #ifndef MINIMALISTIC
162 	{"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
163 	{"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
164 	{"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
165 	{"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
166 	{"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
167 	{"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
168 	{"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
169 	{"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
170 	{"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
171 	{"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
172 	{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
173 	{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
174 #endif /* MINIMALISTIC */
175 	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
176 #ifndef MINIMALISTIC
177 	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
178 	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
179 	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
180 	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
181 	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
182 	{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
183 	{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
184 	{"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
185 	{"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
186 	{"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
187 	{"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:ys"},
188 	{"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"},
189 #endif /* MINIMALISTIC */
190 	{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
191 	{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
192 	{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
193 	{NULL, 0, 0, NULL}
194 };
195 
196 typedef enum {
197 	CC_OR_NOT_FOUND,
198 	CC_OR_AMBIGUOUS,
199 	CC_OR_FOUND
200 } camcontrol_optret;
201 
202 struct cam_devitem {
203 	struct device_match_result dev_match;
204 	int num_periphs;
205 	struct periph_match_result *periph_matches;
206 	struct scsi_vpd_device_id *device_id;
207 	int device_id_len;
208 	STAILQ_ENTRY(cam_devitem) links;
209 };
210 
211 struct cam_devlist {
212 	STAILQ_HEAD(, cam_devitem) dev_queue;
213 	path_id_t path_id;
214 };
215 
216 static cam_cmdmask cmdlist;
217 static cam_argmask arglist;
218 
219 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
220 			    uint32_t *cmdnum, cam_argmask *argnum,
221 			    const char **subopt);
222 #ifndef MINIMALISTIC
223 static int getdevlist(struct cam_device *device);
224 #endif /* MINIMALISTIC */
225 static int getdevtree(void);
226 #ifndef MINIMALISTIC
227 static int testunitready(struct cam_device *device, int retry_count,
228 			 int timeout, int quiet);
229 static int scsistart(struct cam_device *device, int startstop, int loadeject,
230 		     int retry_count, int timeout);
231 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
232 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
233 static int camxferrate(struct cam_device *device);
234 #endif /* MINIMALISTIC */
235 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
236 		     cam_argmask *arglst);
237 static int dorescan_or_reset(int argc, char **argv, int rescan);
238 static int rescan_or_reset_bus(int bus, int rescan);
239 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
240 #ifndef MINIMALISTIC
241 static int readdefects(struct cam_device *device, int argc, char **argv,
242 		       char *combinedopt, int retry_count, int timeout);
243 static void modepage(struct cam_device *device, int argc, char **argv,
244 		     char *combinedopt, int retry_count, int timeout);
245 static int scsicmd(struct cam_device *device, int argc, char **argv,
246 		   char *combinedopt, int retry_count, int timeout);
247 static int smpcmd(struct cam_device *device, int argc, char **argv,
248 		  char *combinedopt, int retry_count, int timeout);
249 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
250 			    char *combinedopt, int retry_count, int timeout);
251 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
252 			 char *combinedopt, int retry_count, int timeout);
253 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
254 		      char *combinedopt, int retry_count, int timeout);
255 static int getdevid(struct cam_devitem *item);
256 static int buildbusdevlist(struct cam_devlist *devlist);
257 static void freebusdevlist(struct cam_devlist *devlist);
258 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
259 					 uint64_t sasaddr);
260 static int smpphylist(struct cam_device *device, int argc, char **argv,
261 		      char *combinedopt, int retry_count, int timeout);
262 static int tagcontrol(struct cam_device *device, int argc, char **argv,
263 		      char *combinedopt);
264 static void cts_print(struct cam_device *device,
265 		      struct ccb_trans_settings *cts);
266 static void cpi_print(struct ccb_pathinq *cpi);
267 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
268 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
269 static int get_print_cts(struct cam_device *device, int user_settings,
270 			 int quiet, struct ccb_trans_settings *cts);
271 static int ratecontrol(struct cam_device *device, int retry_count,
272 		       int timeout, int argc, char **argv, char *combinedopt);
273 static int scsiformat(struct cam_device *device, int argc, char **argv,
274 		      char *combinedopt, int retry_count, int timeout);
275 static int scsireportluns(struct cam_device *device, int argc, char **argv,
276 			  char *combinedopt, int retry_count, int timeout);
277 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
278 			    char *combinedopt, int retry_count, int timeout);
279 static int atapm(struct cam_device *device, int argc, char **argv,
280 		 char *combinedopt, int retry_count, int timeout);
281 static int atasecurity(struct cam_device *device, int retry_count, int timeout,
282 		       int argc, char **argv, char *combinedopt);
283 
284 #endif /* MINIMALISTIC */
285 #ifndef min
286 #define min(a,b) (((a)<(b))?(a):(b))
287 #endif
288 #ifndef max
289 #define max(a,b) (((a)>(b))?(a):(b))
290 #endif
291 
292 camcontrol_optret
293 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
294 	  cam_argmask *argnum, const char **subopt)
295 {
296 	struct camcontrol_opts *opts;
297 	int num_matches = 0;
298 
299 	for (opts = table; (opts != NULL) && (opts->optname != NULL);
300 	     opts++) {
301 		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
302 			*cmdnum = opts->cmdnum;
303 			*argnum = opts->argnum;
304 			*subopt = opts->subopt;
305 			if (++num_matches > 1)
306 				return(CC_OR_AMBIGUOUS);
307 		}
308 	}
309 
310 	if (num_matches > 0)
311 		return(CC_OR_FOUND);
312 	else
313 		return(CC_OR_NOT_FOUND);
314 }
315 
316 #ifndef MINIMALISTIC
317 static int
318 getdevlist(struct cam_device *device)
319 {
320 	union ccb *ccb;
321 	char status[32];
322 	int error = 0;
323 
324 	ccb = cam_getccb(device);
325 
326 	ccb->ccb_h.func_code = XPT_GDEVLIST;
327 	ccb->ccb_h.flags = CAM_DIR_NONE;
328 	ccb->ccb_h.retry_count = 1;
329 	ccb->cgdl.index = 0;
330 	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
331 	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
332 		if (cam_send_ccb(device, ccb) < 0) {
333 			perror("error getting device list");
334 			cam_freeccb(ccb);
335 			return(1);
336 		}
337 
338 		status[0] = '\0';
339 
340 		switch (ccb->cgdl.status) {
341 			case CAM_GDEVLIST_MORE_DEVS:
342 				strcpy(status, "MORE");
343 				break;
344 			case CAM_GDEVLIST_LAST_DEVICE:
345 				strcpy(status, "LAST");
346 				break;
347 			case CAM_GDEVLIST_LIST_CHANGED:
348 				strcpy(status, "CHANGED");
349 				break;
350 			case CAM_GDEVLIST_ERROR:
351 				strcpy(status, "ERROR");
352 				error = 1;
353 				break;
354 		}
355 
356 		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
357 			ccb->cgdl.periph_name,
358 			ccb->cgdl.unit_number,
359 			ccb->cgdl.generation,
360 			ccb->cgdl.index,
361 			status);
362 
363 		/*
364 		 * If the list has changed, we need to start over from the
365 		 * beginning.
366 		 */
367 		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
368 			ccb->cgdl.index = 0;
369 	}
370 
371 	cam_freeccb(ccb);
372 
373 	return(error);
374 }
375 #endif /* MINIMALISTIC */
376 
377 static int
378 getdevtree(void)
379 {
380 	union ccb ccb;
381 	int bufsize, fd;
382 	unsigned int i;
383 	int need_close = 0;
384 	int error = 0;
385 	int skip_device = 0;
386 
387 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
388 		warn("couldn't open %s", XPT_DEVICE);
389 		return(1);
390 	}
391 
392 	bzero(&ccb, sizeof(union ccb));
393 
394 	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
395 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
396 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
397 
398 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
399 	bufsize = sizeof(struct dev_match_result) * 100;
400 	ccb.cdm.match_buf_len = bufsize;
401 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
402 	if (ccb.cdm.matches == NULL) {
403 		warnx("can't malloc memory for matches");
404 		close(fd);
405 		return(1);
406 	}
407 	ccb.cdm.num_matches = 0;
408 
409 	/*
410 	 * We fetch all nodes, since we display most of them in the default
411 	 * case, and all in the verbose case.
412 	 */
413 	ccb.cdm.num_patterns = 0;
414 	ccb.cdm.pattern_buf_len = 0;
415 
416 	/*
417 	 * We do the ioctl multiple times if necessary, in case there are
418 	 * more than 100 nodes in the EDT.
419 	 */
420 	do {
421 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
422 			warn("error sending CAMIOCOMMAND ioctl");
423 			error = 1;
424 			break;
425 		}
426 
427 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
428 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
429 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
430 			warnx("got CAM error %#x, CDM error %d\n",
431 			      ccb.ccb_h.status, ccb.cdm.status);
432 			error = 1;
433 			break;
434 		}
435 
436 		for (i = 0; i < ccb.cdm.num_matches; i++) {
437 			switch (ccb.cdm.matches[i].type) {
438 			case DEV_MATCH_BUS: {
439 				struct bus_match_result *bus_result;
440 
441 				/*
442 				 * Only print the bus information if the
443 				 * user turns on the verbose flag.
444 				 */
445 				if ((arglist & CAM_ARG_VERBOSE) == 0)
446 					break;
447 
448 				bus_result =
449 					&ccb.cdm.matches[i].result.bus_result;
450 
451 				if (need_close) {
452 					fprintf(stdout, ")\n");
453 					need_close = 0;
454 				}
455 
456 				fprintf(stdout, "scbus%d on %s%d bus %d:\n",
457 					bus_result->path_id,
458 					bus_result->dev_name,
459 					bus_result->unit_number,
460 					bus_result->bus_id);
461 				break;
462 			}
463 			case DEV_MATCH_DEVICE: {
464 				struct device_match_result *dev_result;
465 				char vendor[16], product[48], revision[16];
466 				char fw[5], tmpstr[256];
467 
468 				dev_result =
469 				     &ccb.cdm.matches[i].result.device_result;
470 
471 				if ((dev_result->flags
472 				     & DEV_RESULT_UNCONFIGURED)
473 				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
474 					skip_device = 1;
475 					break;
476 				} else
477 					skip_device = 0;
478 
479 				if (dev_result->protocol == PROTO_SCSI) {
480 				    cam_strvis(vendor, dev_result->inq_data.vendor,
481 					   sizeof(dev_result->inq_data.vendor),
482 					   sizeof(vendor));
483 				    cam_strvis(product,
484 					   dev_result->inq_data.product,
485 					   sizeof(dev_result->inq_data.product),
486 					   sizeof(product));
487 				    cam_strvis(revision,
488 					   dev_result->inq_data.revision,
489 					  sizeof(dev_result->inq_data.revision),
490 					   sizeof(revision));
491 				    sprintf(tmpstr, "<%s %s %s>", vendor, product,
492 					revision);
493 				} else if (dev_result->protocol == PROTO_ATA ||
494 				    dev_result->protocol == PROTO_SATAPM) {
495 				    cam_strvis(product,
496 					   dev_result->ident_data.model,
497 					   sizeof(dev_result->ident_data.model),
498 					   sizeof(product));
499 				    cam_strvis(revision,
500 					   dev_result->ident_data.revision,
501 					  sizeof(dev_result->ident_data.revision),
502 					   sizeof(revision));
503 				    sprintf(tmpstr, "<%s %s>", product,
504 					revision);
505 				} else if (dev_result->protocol == PROTO_SEMB) {
506 					struct sep_identify_data *sid;
507 
508 					sid = (struct sep_identify_data *)
509 					    &dev_result->ident_data;
510 					cam_strvis(vendor, sid->vendor_id,
511 					    sizeof(sid->vendor_id),
512 					    sizeof(vendor));
513 					cam_strvis(product, sid->product_id,
514 					    sizeof(sid->product_id),
515 					    sizeof(product));
516 					cam_strvis(revision, sid->product_rev,
517 					    sizeof(sid->product_rev),
518 					    sizeof(revision));
519 					cam_strvis(fw, sid->firmware_rev,
520 					    sizeof(sid->firmware_rev),
521 					    sizeof(fw));
522 					sprintf(tmpstr, "<%s %s %s %s>",
523 					    vendor, product, revision, fw);
524 				} else {
525 				    sprintf(tmpstr, "<>");
526 				}
527 				if (need_close) {
528 					fprintf(stdout, ")\n");
529 					need_close = 0;
530 				}
531 
532 				fprintf(stdout, "%-33s  at scbus%d "
533 					"target %d lun %d (",
534 					tmpstr,
535 					dev_result->path_id,
536 					dev_result->target_id,
537 					dev_result->target_lun);
538 
539 				need_close = 1;
540 
541 				break;
542 			}
543 			case DEV_MATCH_PERIPH: {
544 				struct periph_match_result *periph_result;
545 
546 				periph_result =
547 				      &ccb.cdm.matches[i].result.periph_result;
548 
549 				if (skip_device != 0)
550 					break;
551 
552 				if (need_close > 1)
553 					fprintf(stdout, ",");
554 
555 				fprintf(stdout, "%s%d",
556 					periph_result->periph_name,
557 					periph_result->unit_number);
558 
559 				need_close++;
560 				break;
561 			}
562 			default:
563 				fprintf(stdout, "unknown match type\n");
564 				break;
565 			}
566 		}
567 
568 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
569 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
570 
571 	if (need_close)
572 		fprintf(stdout, ")\n");
573 
574 	close(fd);
575 
576 	return(error);
577 }
578 
579 #ifndef MINIMALISTIC
580 static int
581 testunitready(struct cam_device *device, int retry_count, int timeout,
582 	      int quiet)
583 {
584 	int error = 0;
585 	union ccb *ccb;
586 
587 	ccb = cam_getccb(device);
588 
589 	scsi_test_unit_ready(&ccb->csio,
590 			     /* retries */ retry_count,
591 			     /* cbfcnp */ NULL,
592 			     /* tag_action */ MSG_SIMPLE_Q_TAG,
593 			     /* sense_len */ SSD_FULL_SIZE,
594 			     /* timeout */ timeout ? timeout : 5000);
595 
596 	/* Disable freezing the device queue */
597 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
598 
599 	if (arglist & CAM_ARG_ERR_RECOVER)
600 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
601 
602 	if (cam_send_ccb(device, ccb) < 0) {
603 		if (quiet == 0)
604 			perror("error sending test unit ready");
605 
606 		if (arglist & CAM_ARG_VERBOSE) {
607 			cam_error_print(device, ccb, CAM_ESF_ALL,
608 					CAM_EPF_ALL, stderr);
609 		}
610 
611 		cam_freeccb(ccb);
612 		return(1);
613 	}
614 
615 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
616 		if (quiet == 0)
617 			fprintf(stdout, "Unit is ready\n");
618 	} else {
619 		if (quiet == 0)
620 			fprintf(stdout, "Unit is not ready\n");
621 		error = 1;
622 
623 		if (arglist & CAM_ARG_VERBOSE) {
624 			cam_error_print(device, ccb, CAM_ESF_ALL,
625 					CAM_EPF_ALL, stderr);
626 		}
627 	}
628 
629 	cam_freeccb(ccb);
630 
631 	return(error);
632 }
633 
634 static int
635 scsistart(struct cam_device *device, int startstop, int loadeject,
636 	  int retry_count, int timeout)
637 {
638 	union ccb *ccb;
639 	int error = 0;
640 
641 	ccb = cam_getccb(device);
642 
643 	/*
644 	 * If we're stopping, send an ordered tag so the drive in question
645 	 * will finish any previously queued writes before stopping.  If
646 	 * the device isn't capable of tagged queueing, or if tagged
647 	 * queueing is turned off, the tag action is a no-op.
648 	 */
649 	scsi_start_stop(&ccb->csio,
650 			/* retries */ retry_count,
651 			/* cbfcnp */ NULL,
652 			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
653 						     MSG_ORDERED_Q_TAG,
654 			/* start/stop */ startstop,
655 			/* load_eject */ loadeject,
656 			/* immediate */ 0,
657 			/* sense_len */ SSD_FULL_SIZE,
658 			/* timeout */ timeout ? timeout : 120000);
659 
660 	/* Disable freezing the device queue */
661 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
662 
663 	if (arglist & CAM_ARG_ERR_RECOVER)
664 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
665 
666 	if (cam_send_ccb(device, ccb) < 0) {
667 		perror("error sending start unit");
668 
669 		if (arglist & CAM_ARG_VERBOSE) {
670 			cam_error_print(device, ccb, CAM_ESF_ALL,
671 					CAM_EPF_ALL, stderr);
672 		}
673 
674 		cam_freeccb(ccb);
675 		return(1);
676 	}
677 
678 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
679 		if (startstop) {
680 			fprintf(stdout, "Unit started successfully");
681 			if (loadeject)
682 				fprintf(stdout,", Media loaded\n");
683 			else
684 				fprintf(stdout,"\n");
685 		} else {
686 			fprintf(stdout, "Unit stopped successfully");
687 			if (loadeject)
688 				fprintf(stdout, ", Media ejected\n");
689 			else
690 				fprintf(stdout, "\n");
691 		}
692 	else {
693 		error = 1;
694 		if (startstop)
695 			fprintf(stdout,
696 				"Error received from start unit command\n");
697 		else
698 			fprintf(stdout,
699 				"Error received from stop unit command\n");
700 
701 		if (arglist & CAM_ARG_VERBOSE) {
702 			cam_error_print(device, ccb, CAM_ESF_ALL,
703 					CAM_EPF_ALL, stderr);
704 		}
705 	}
706 
707 	cam_freeccb(ccb);
708 
709 	return(error);
710 }
711 
712 int
713 scsidoinquiry(struct cam_device *device, int argc, char **argv,
714 	      char *combinedopt, int retry_count, int timeout)
715 {
716 	int c;
717 	int error = 0;
718 
719 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
720 		switch(c) {
721 		case 'D':
722 			arglist |= CAM_ARG_GET_STDINQ;
723 			break;
724 		case 'R':
725 			arglist |= CAM_ARG_GET_XFERRATE;
726 			break;
727 		case 'S':
728 			arglist |= CAM_ARG_GET_SERIAL;
729 			break;
730 		default:
731 			break;
732 		}
733 	}
734 
735 	/*
736 	 * If the user didn't specify any inquiry options, he wants all of
737 	 * them.
738 	 */
739 	if ((arglist & CAM_ARG_INQ_MASK) == 0)
740 		arglist |= CAM_ARG_INQ_MASK;
741 
742 	if (arglist & CAM_ARG_GET_STDINQ)
743 		error = scsiinquiry(device, retry_count, timeout);
744 
745 	if (error != 0)
746 		return(error);
747 
748 	if (arglist & CAM_ARG_GET_SERIAL)
749 		scsiserial(device, retry_count, timeout);
750 
751 	if (error != 0)
752 		return(error);
753 
754 	if (arglist & CAM_ARG_GET_XFERRATE)
755 		error = camxferrate(device);
756 
757 	return(error);
758 }
759 
760 static int
761 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
762 {
763 	union ccb *ccb;
764 	struct scsi_inquiry_data *inq_buf;
765 	int error = 0;
766 
767 	ccb = cam_getccb(device);
768 
769 	if (ccb == NULL) {
770 		warnx("couldn't allocate CCB");
771 		return(1);
772 	}
773 
774 	/* cam_getccb cleans up the header, caller has to zero the payload */
775 	bzero(&(&ccb->ccb_h)[1],
776 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
777 
778 	inq_buf = (struct scsi_inquiry_data *)malloc(
779 		sizeof(struct scsi_inquiry_data));
780 
781 	if (inq_buf == NULL) {
782 		cam_freeccb(ccb);
783 		warnx("can't malloc memory for inquiry\n");
784 		return(1);
785 	}
786 	bzero(inq_buf, sizeof(*inq_buf));
787 
788 	/*
789 	 * Note that although the size of the inquiry buffer is the full
790 	 * 256 bytes specified in the SCSI spec, we only tell the device
791 	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
792 	 * two reasons for this:
793 	 *
794 	 *  - The SCSI spec says that when a length field is only 1 byte,
795 	 *    a value of 0 will be interpreted as 256.  Therefore
796 	 *    scsi_inquiry() will convert an inq_len (which is passed in as
797 	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
798 	 *    to 0.  Evidently, very few devices meet the spec in that
799 	 *    regard.  Some devices, like many Seagate disks, take the 0 as
800 	 *    0, and don't return any data.  One Pioneer DVD-R drive
801 	 *    returns more data than the command asked for.
802 	 *
803 	 *    So, since there are numerous devices that just don't work
804 	 *    right with the full inquiry size, we don't send the full size.
805 	 *
806 	 *  - The second reason not to use the full inquiry data length is
807 	 *    that we don't need it here.  The only reason we issue a
808 	 *    standard inquiry is to get the vendor name, device name,
809 	 *    and revision so scsi_print_inquiry() can print them.
810 	 *
811 	 * If, at some point in the future, more inquiry data is needed for
812 	 * some reason, this code should use a procedure similar to the
813 	 * probe code.  i.e., issue a short inquiry, and determine from
814 	 * the additional length passed back from the device how much
815 	 * inquiry data the device supports.  Once the amount the device
816 	 * supports is determined, issue an inquiry for that amount and no
817 	 * more.
818 	 *
819 	 * KDM, 2/18/2000
820 	 */
821 	scsi_inquiry(&ccb->csio,
822 		     /* retries */ retry_count,
823 		     /* cbfcnp */ NULL,
824 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
825 		     /* inq_buf */ (u_int8_t *)inq_buf,
826 		     /* inq_len */ SHORT_INQUIRY_LENGTH,
827 		     /* evpd */ 0,
828 		     /* page_code */ 0,
829 		     /* sense_len */ SSD_FULL_SIZE,
830 		     /* timeout */ timeout ? timeout : 5000);
831 
832 	/* Disable freezing the device queue */
833 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
834 
835 	if (arglist & CAM_ARG_ERR_RECOVER)
836 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
837 
838 	if (cam_send_ccb(device, ccb) < 0) {
839 		perror("error sending SCSI inquiry");
840 
841 		if (arglist & CAM_ARG_VERBOSE) {
842 			cam_error_print(device, ccb, CAM_ESF_ALL,
843 					CAM_EPF_ALL, stderr);
844 		}
845 
846 		cam_freeccb(ccb);
847 		return(1);
848 	}
849 
850 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
851 		error = 1;
852 
853 		if (arglist & CAM_ARG_VERBOSE) {
854 			cam_error_print(device, ccb, CAM_ESF_ALL,
855 					CAM_EPF_ALL, stderr);
856 		}
857 	}
858 
859 	cam_freeccb(ccb);
860 
861 	if (error != 0) {
862 		free(inq_buf);
863 		return(error);
864 	}
865 
866 	fprintf(stdout, "%s%d: ", device->device_name,
867 		device->dev_unit_num);
868 	scsi_print_inquiry(inq_buf);
869 
870 	free(inq_buf);
871 
872 	return(0);
873 }
874 
875 static int
876 scsiserial(struct cam_device *device, int retry_count, int timeout)
877 {
878 	union ccb *ccb;
879 	struct scsi_vpd_unit_serial_number *serial_buf;
880 	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
881 	int error = 0;
882 
883 	ccb = cam_getccb(device);
884 
885 	if (ccb == NULL) {
886 		warnx("couldn't allocate CCB");
887 		return(1);
888 	}
889 
890 	/* cam_getccb cleans up the header, caller has to zero the payload */
891 	bzero(&(&ccb->ccb_h)[1],
892 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
893 
894 	serial_buf = (struct scsi_vpd_unit_serial_number *)
895 		malloc(sizeof(*serial_buf));
896 
897 	if (serial_buf == NULL) {
898 		cam_freeccb(ccb);
899 		warnx("can't malloc memory for serial number");
900 		return(1);
901 	}
902 
903 	scsi_inquiry(&ccb->csio,
904 		     /*retries*/ retry_count,
905 		     /*cbfcnp*/ NULL,
906 		     /* tag_action */ MSG_SIMPLE_Q_TAG,
907 		     /* inq_buf */ (u_int8_t *)serial_buf,
908 		     /* inq_len */ sizeof(*serial_buf),
909 		     /* evpd */ 1,
910 		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
911 		     /* sense_len */ SSD_FULL_SIZE,
912 		     /* timeout */ timeout ? timeout : 5000);
913 
914 	/* Disable freezing the device queue */
915 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
916 
917 	if (arglist & CAM_ARG_ERR_RECOVER)
918 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
919 
920 	if (cam_send_ccb(device, ccb) < 0) {
921 		warn("error getting serial number");
922 
923 		if (arglist & CAM_ARG_VERBOSE) {
924 			cam_error_print(device, ccb, CAM_ESF_ALL,
925 					CAM_EPF_ALL, stderr);
926 		}
927 
928 		cam_freeccb(ccb);
929 		free(serial_buf);
930 		return(1);
931 	}
932 
933 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
934 		error = 1;
935 
936 		if (arglist & CAM_ARG_VERBOSE) {
937 			cam_error_print(device, ccb, CAM_ESF_ALL,
938 					CAM_EPF_ALL, stderr);
939 		}
940 	}
941 
942 	cam_freeccb(ccb);
943 
944 	if (error != 0) {
945 		free(serial_buf);
946 		return(error);
947 	}
948 
949 	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
950 	serial_num[serial_buf->length] = '\0';
951 
952 	if ((arglist & CAM_ARG_GET_STDINQ)
953 	 || (arglist & CAM_ARG_GET_XFERRATE))
954 		fprintf(stdout, "%s%d: Serial Number ",
955 			device->device_name, device->dev_unit_num);
956 
957 	fprintf(stdout, "%.60s\n", serial_num);
958 
959 	free(serial_buf);
960 
961 	return(0);
962 }
963 
964 static int
965 camxferrate(struct cam_device *device)
966 {
967 	struct ccb_pathinq cpi;
968 	u_int32_t freq = 0;
969 	u_int32_t speed = 0;
970 	union ccb *ccb;
971 	u_int mb;
972 	int retval = 0;
973 
974 	if ((retval = get_cpi(device, &cpi)) != 0)
975 		return (1);
976 
977 	ccb = cam_getccb(device);
978 
979 	if (ccb == NULL) {
980 		warnx("couldn't allocate CCB");
981 		return(1);
982 	}
983 
984 	bzero(&(&ccb->ccb_h)[1],
985 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
986 
987 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
988 	ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
989 
990 	if (((retval = cam_send_ccb(device, ccb)) < 0)
991 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
992 		const char error_string[] = "error getting transfer settings";
993 
994 		if (retval < 0)
995 			warn(error_string);
996 		else
997 			warnx(error_string);
998 
999 		if (arglist & CAM_ARG_VERBOSE)
1000 			cam_error_print(device, ccb, CAM_ESF_ALL,
1001 					CAM_EPF_ALL, stderr);
1002 
1003 		retval = 1;
1004 
1005 		goto xferrate_bailout;
1006 
1007 	}
1008 
1009 	speed = cpi.base_transfer_speed;
1010 	freq = 0;
1011 	if (ccb->cts.transport == XPORT_SPI) {
1012 		struct ccb_trans_settings_spi *spi =
1013 		    &ccb->cts.xport_specific.spi;
1014 
1015 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1016 			freq = scsi_calc_syncsrate(spi->sync_period);
1017 			speed = freq;
1018 		}
1019 		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1020 			speed *= (0x01 << spi->bus_width);
1021 		}
1022 	} else if (ccb->cts.transport == XPORT_FC) {
1023 		struct ccb_trans_settings_fc *fc =
1024 		    &ccb->cts.xport_specific.fc;
1025 
1026 		if (fc->valid & CTS_FC_VALID_SPEED)
1027 			speed = fc->bitrate;
1028 	} else if (ccb->cts.transport == XPORT_SAS) {
1029 		struct ccb_trans_settings_sas *sas =
1030 		    &ccb->cts.xport_specific.sas;
1031 
1032 		if (sas->valid & CTS_SAS_VALID_SPEED)
1033 			speed = sas->bitrate;
1034 	} else if (ccb->cts.transport == XPORT_ATA) {
1035 		struct ccb_trans_settings_pata *pata =
1036 		    &ccb->cts.xport_specific.ata;
1037 
1038 		if (pata->valid & CTS_ATA_VALID_MODE)
1039 			speed = ata_mode2speed(pata->mode);
1040 	} else if (ccb->cts.transport == XPORT_SATA) {
1041 		struct	ccb_trans_settings_sata *sata =
1042 		    &ccb->cts.xport_specific.sata;
1043 
1044 		if (sata->valid & CTS_SATA_VALID_REVISION)
1045 			speed = ata_revision2speed(sata->revision);
1046 	}
1047 
1048 	mb = speed / 1000;
1049 	if (mb > 0) {
1050 		fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1051 			device->device_name, device->dev_unit_num,
1052 			mb, speed % 1000);
1053 	} else {
1054 		fprintf(stdout, "%s%d: %dKB/s transfers",
1055 			device->device_name, device->dev_unit_num,
1056 			speed);
1057 	}
1058 
1059 	if (ccb->cts.transport == XPORT_SPI) {
1060 		struct ccb_trans_settings_spi *spi =
1061 		    &ccb->cts.xport_specific.spi;
1062 
1063 		if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1064 		 && (spi->sync_offset != 0))
1065 			fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1066 				freq % 1000, spi->sync_offset);
1067 
1068 		if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1069 		 && (spi->bus_width > 0)) {
1070 			if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1071 			 && (spi->sync_offset != 0)) {
1072 				fprintf(stdout, ", ");
1073 			} else {
1074 				fprintf(stdout, " (");
1075 			}
1076 			fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1077 		} else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1078 		 && (spi->sync_offset != 0)) {
1079 			fprintf(stdout, ")");
1080 		}
1081 	} else if (ccb->cts.transport == XPORT_ATA) {
1082 		struct ccb_trans_settings_pata *pata =
1083 		    &ccb->cts.xport_specific.ata;
1084 
1085 		printf(" (");
1086 		if (pata->valid & CTS_ATA_VALID_MODE)
1087 			printf("%s, ", ata_mode2string(pata->mode));
1088 		if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1089 			printf("ATAPI %dbytes, ", pata->atapi);
1090 		if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1091 			printf("PIO %dbytes", pata->bytecount);
1092 		printf(")");
1093 	} else if (ccb->cts.transport == XPORT_SATA) {
1094 		struct ccb_trans_settings_sata *sata =
1095 		    &ccb->cts.xport_specific.sata;
1096 
1097 		printf(" (");
1098 		if (sata->valid & CTS_SATA_VALID_REVISION)
1099 			printf("SATA %d.x, ", sata->revision);
1100 		else
1101 			printf("SATA, ");
1102 		if (sata->valid & CTS_SATA_VALID_MODE)
1103 			printf("%s, ", ata_mode2string(sata->mode));
1104 		if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1105 			printf("ATAPI %dbytes, ", sata->atapi);
1106 		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1107 			printf("PIO %dbytes", sata->bytecount);
1108 		printf(")");
1109 	}
1110 
1111 	if (ccb->cts.protocol == PROTO_SCSI) {
1112 		struct ccb_trans_settings_scsi *scsi =
1113 		    &ccb->cts.proto_specific.scsi;
1114 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
1115 			if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1116 				fprintf(stdout, ", Command Queueing Enabled");
1117 			}
1118 		}
1119 	}
1120 
1121         fprintf(stdout, "\n");
1122 
1123 xferrate_bailout:
1124 
1125 	cam_freeccb(ccb);
1126 
1127 	return(retval);
1128 }
1129 
1130 static void
1131 atacapprint(struct ata_params *parm)
1132 {
1133 	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1134 				((u_int32_t)parm->lba_size_2 << 16);
1135 
1136 	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1137 				((u_int64_t)parm->lba_size48_2 << 16) |
1138 				((u_int64_t)parm->lba_size48_3 << 32) |
1139 				((u_int64_t)parm->lba_size48_4 << 48);
1140 
1141 	printf("\n");
1142 	printf("protocol              ");
1143 	printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1144 	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1145 		if (parm->satacapabilities & ATA_SATA_GEN3)
1146 			printf(" SATA 3.x\n");
1147 		else if (parm->satacapabilities & ATA_SATA_GEN2)
1148 			printf(" SATA 2.x\n");
1149 		else if (parm->satacapabilities & ATA_SATA_GEN1)
1150 			printf(" SATA 1.x\n");
1151 		else
1152 			printf(" SATA\n");
1153 	}
1154 	else
1155 		printf("\n");
1156 	printf("device model          %.40s\n", parm->model);
1157 	printf("firmware revision     %.8s\n", parm->revision);
1158 	printf("serial number         %.20s\n", parm->serial);
1159 	if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1160 		printf("WWN                   %04x%04x%04x%04x\n",
1161 		    parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1162 	}
1163 	if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1164 		printf("media serial number   %.30s\n",
1165 		    parm->media_serial);
1166 	}
1167 
1168 	printf("cylinders             %d\n", parm->cylinders);
1169 	printf("heads                 %d\n", parm->heads);
1170 	printf("sectors/track         %d\n", parm->sectors);
1171 	printf("sector size           logical %u, physical %lu, offset %lu\n",
1172 	    ata_logical_sector_size(parm),
1173 	    (unsigned long)ata_physical_sector_size(parm),
1174 	    (unsigned long)ata_logical_sector_offset(parm));
1175 
1176 	if (parm->config == ATA_PROTO_CFA ||
1177 	    (parm->support.command2 & ATA_SUPPORT_CFA))
1178 		printf("CFA supported\n");
1179 
1180 	printf("LBA%ssupported         ",
1181 		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1182 	if (lbasize)
1183 		printf("%d sectors\n", lbasize);
1184 	else
1185 		printf("\n");
1186 
1187 	printf("LBA48%ssupported       ",
1188 		parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1189 	if (lbasize48)
1190 		printf("%ju sectors\n", (uintmax_t)lbasize48);
1191 	else
1192 		printf("\n");
1193 
1194 	printf("PIO supported         PIO");
1195 	switch (ata_max_pmode(parm)) {
1196 	case ATA_PIO4:
1197 		printf("4");
1198 		break;
1199 	case ATA_PIO3:
1200 		printf("3");
1201 		break;
1202 	case ATA_PIO2:
1203 		printf("2");
1204 		break;
1205 	case ATA_PIO1:
1206 		printf("1");
1207 		break;
1208 	default:
1209 		printf("0");
1210 	}
1211 	if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1212 		printf(" w/o IORDY");
1213 	printf("\n");
1214 
1215 	printf("DMA%ssupported         ",
1216 		parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1217 	if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1218 		if (parm->mwdmamodes & 0xff) {
1219 			printf("WDMA");
1220 			if (parm->mwdmamodes & 0x04)
1221 				printf("2");
1222 			else if (parm->mwdmamodes & 0x02)
1223 				printf("1");
1224 			else if (parm->mwdmamodes & 0x01)
1225 				printf("0");
1226 			printf(" ");
1227 		}
1228 		if ((parm->atavalid & ATA_FLAG_88) &&
1229 		    (parm->udmamodes & 0xff)) {
1230 			printf("UDMA");
1231 			if (parm->udmamodes & 0x40)
1232 				printf("6");
1233 			else if (parm->udmamodes & 0x20)
1234 				printf("5");
1235 			else if (parm->udmamodes & 0x10)
1236 				printf("4");
1237 			else if (parm->udmamodes & 0x08)
1238 				printf("3");
1239 			else if (parm->udmamodes & 0x04)
1240 				printf("2");
1241 			else if (parm->udmamodes & 0x02)
1242 				printf("1");
1243 			else if (parm->udmamodes & 0x01)
1244 				printf("0");
1245 			printf(" ");
1246 		}
1247 	}
1248 	printf("\n");
1249 
1250 	if (parm->media_rotation_rate == 1) {
1251 		printf("media RPM             non-rotating\n");
1252 	} else if (parm->media_rotation_rate >= 0x0401 &&
1253 	    parm->media_rotation_rate <= 0xFFFE) {
1254 		printf("media RPM             %d\n",
1255 			parm->media_rotation_rate);
1256 	}
1257 
1258 	printf("\nFeature                      "
1259 		"Support  Enabled   Value           Vendor\n");
1260 	printf("read ahead                     %s	%s\n",
1261 		parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1262 		parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1263 	printf("write cache                    %s	%s\n",
1264 		parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1265 		parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1266 	printf("flush cache                    %s	%s\n",
1267 		parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1268 		parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1269 	printf("overlap                        %s\n",
1270 		parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1271 	printf("Tagged Command Queuing (TCQ)   %s	%s",
1272 		parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1273 		parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1274 		if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1275 			printf("	%d tags\n",
1276 			    ATA_QUEUE_LEN(parm->queue) + 1);
1277 		} else
1278 			printf("\n");
1279 	printf("Native Command Queuing (NCQ)   ");
1280 	if (parm->satacapabilities != 0xffff &&
1281 	    (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1282 		printf("yes		%d tags\n",
1283 		    ATA_QUEUE_LEN(parm->queue) + 1);
1284 	} else
1285 		printf("no\n");
1286 	printf("SMART                          %s	%s\n",
1287 		parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1288 		parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1289 	printf("microcode download             %s	%s\n",
1290 		parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1291 		parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1292 	printf("security                       %s	%s\n",
1293 		parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1294 		parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1295 	printf("power management               %s	%s\n",
1296 		parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1297 		parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1298 	printf("advanced power management      %s	%s",
1299 		parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1300 		parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1301 		if (parm->support.command2 & ATA_SUPPORT_APM) {
1302 			printf("	%d/0x%02X\n",
1303 			    parm->apm_value, parm->apm_value);
1304 		} else
1305 			printf("\n");
1306 	printf("automatic acoustic management  %s	%s",
1307 		parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1308 		parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1309 		if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1310 			printf("	%d/0x%02X	%d/0x%02X\n",
1311 			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1312 			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1313 			    ATA_ACOUSTIC_VENDOR(parm->acoustic),
1314 			    ATA_ACOUSTIC_VENDOR(parm->acoustic));
1315 		} else
1316 			printf("\n");
1317 	printf("media status notification      %s	%s\n",
1318 		parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1319 		parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1320 	printf("power-up in Standby            %s	%s\n",
1321 		parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1322 		parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1323 	printf("write-read-verify              %s	%s",
1324 		parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1325 		parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1326 		if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1327 			printf("	%d/0x%x\n",
1328 			    parm->wrv_mode, parm->wrv_mode);
1329 		} else
1330 			printf("\n");
1331 	printf("unload                         %s	%s\n",
1332 		parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1333 		parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1334 	printf("free-fall                      %s	%s\n",
1335 		parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1336 		parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1337 	printf("Data Set Management (DSM/TRIM) ");
1338 	if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) {
1339 		printf("yes\n");
1340 		printf("DSM - max 512byte blocks       ");
1341 		if (parm->max_dsm_blocks == 0x00)
1342 			printf("yes              not specified\n");
1343 		else
1344 			printf("yes              %d\n",
1345 				parm->max_dsm_blocks);
1346 
1347 		printf("DSM - deterministic read       ");
1348 		if (parm->support3 & ATA_SUPPORT_DRAT) {
1349 			if (parm->support3 & ATA_SUPPORT_RZAT)
1350 				printf("yes              zeroed\n");
1351 			else
1352 				printf("yes              any value\n");
1353 		} else {
1354 			printf("no\n");
1355 		}
1356 	} else {
1357 		printf("no\n");
1358 	}
1359 }
1360 
1361 static int
1362 scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
1363 {
1364 	struct ata_pass_16 *ata_pass_16;
1365 	struct ata_cmd ata_cmd;
1366 
1367 	ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
1368 	ata_cmd.command = ata_pass_16->command;
1369 	ata_cmd.control = ata_pass_16->control;
1370 	ata_cmd.features = ata_pass_16->features;
1371 
1372 	if (arglist & CAM_ARG_VERBOSE) {
1373 		warnx("sending ATA %s via pass_16 with timeout of %u msecs",
1374 		      ata_op_string(&ata_cmd),
1375 		      ccb->csio.ccb_h.timeout);
1376 	}
1377 
1378 	/* Disable freezing the device queue */
1379 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1380 
1381 	if (arglist & CAM_ARG_ERR_RECOVER)
1382 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1383 
1384 	if (cam_send_ccb(device, ccb) < 0) {
1385 		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1386 			warn("error sending ATA %s via pass_16",
1387 			     ata_op_string(&ata_cmd));
1388 		}
1389 
1390 		if (arglist & CAM_ARG_VERBOSE) {
1391 			cam_error_print(device, ccb, CAM_ESF_ALL,
1392 					CAM_EPF_ALL, stderr);
1393 		}
1394 
1395 		return (1);
1396 	}
1397 
1398 	if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
1399 	    (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1400 		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1401 			warnx("ATA %s via pass_16 failed",
1402 			      ata_op_string(&ata_cmd));
1403 		}
1404 		if (arglist & CAM_ARG_VERBOSE) {
1405 			cam_error_print(device, ccb, CAM_ESF_ALL,
1406 					CAM_EPF_ALL, stderr);
1407 		}
1408 
1409 		return (1);
1410 	}
1411 
1412 	return (0);
1413 }
1414 
1415 
1416 static int
1417 ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
1418 {
1419 	if (arglist & CAM_ARG_VERBOSE) {
1420 		warnx("sending ATA %s with timeout of %u msecs",
1421 		      ata_op_string(&(ccb->ataio.cmd)),
1422 		      ccb->ataio.ccb_h.timeout);
1423 	}
1424 
1425 	/* Disable freezing the device queue */
1426 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1427 
1428 	if (arglist & CAM_ARG_ERR_RECOVER)
1429 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1430 
1431 	if (cam_send_ccb(device, ccb) < 0) {
1432 		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1433 			warn("error sending ATA %s",
1434 			     ata_op_string(&(ccb->ataio.cmd)));
1435 		}
1436 
1437 		if (arglist & CAM_ARG_VERBOSE) {
1438 			cam_error_print(device, ccb, CAM_ESF_ALL,
1439 					CAM_EPF_ALL, stderr);
1440 		}
1441 
1442 		return (1);
1443 	}
1444 
1445 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1446 		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1447 			warnx("ATA %s failed: %d",
1448 			      ata_op_string(&(ccb->ataio.cmd)), quiet);
1449 		}
1450 
1451 		if (arglist & CAM_ARG_VERBOSE) {
1452 			cam_error_print(device, ccb, CAM_ESF_ALL,
1453 					CAM_EPF_ALL, stderr);
1454 		}
1455 
1456 		return (1);
1457 	}
1458 
1459 	return (0);
1460 }
1461 
1462 static int
1463 ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
1464 	       u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1465 	       u_int8_t tag_action, u_int8_t command, u_int8_t features,
1466 	       u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1467 	       u_int16_t dxfer_len, int timeout, int quiet)
1468 {
1469 	if (data_ptr != NULL) {
1470 		ata_flags |= AP_FLAG_BYT_BLOK_BYTES |
1471 			    AP_FLAG_TLEN_SECT_CNT;
1472 		if (flags & CAM_DIR_OUT)
1473 			ata_flags |= AP_FLAG_TDIR_TO_DEV;
1474 		else
1475 			ata_flags |= AP_FLAG_TDIR_FROM_DEV;
1476 	} else {
1477 		ata_flags |= AP_FLAG_TLEN_NO_DATA;
1478 	}
1479 
1480 	bzero(&(&ccb->ccb_h)[1],
1481 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1482 
1483 	scsi_ata_pass_16(&ccb->csio,
1484 			 retries,
1485 			 NULL,
1486 			 flags,
1487 			 tag_action,
1488 			 protocol,
1489 			 ata_flags,
1490 			 features,
1491 			 sector_count,
1492 			 lba,
1493 			 command,
1494 			 /*control*/0,
1495 			 data_ptr,
1496 			 dxfer_len,
1497 			 /*sense_len*/SSD_FULL_SIZE,
1498 			 timeout);
1499 
1500 	return scsi_cam_pass_16_send(device, ccb, quiet);
1501 }
1502 
1503 static int
1504 ata_try_pass_16(struct cam_device *device)
1505 {
1506 	struct ccb_pathinq cpi;
1507 
1508 	if (get_cpi(device, &cpi) != 0) {
1509 		warnx("couldn't get CPI");
1510 		return (-1);
1511 	}
1512 
1513 	if (cpi.protocol == PROTO_SCSI) {
1514 		/* possibly compatible with pass_16 */
1515 		return (1);
1516 	}
1517 
1518 	/* likely not compatible with pass_16 */
1519 	return (0);
1520 }
1521 
1522 static int
1523 ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries,
1524 		 u_int32_t flags, u_int8_t protocol, u_int8_t tag_action,
1525 		 u_int8_t command, u_int8_t features, u_int32_t lba,
1526 		 u_int8_t sector_count, u_int8_t *data_ptr, u_int16_t dxfer_len,
1527 		 int timeout, int quiet)
1528 {
1529 
1530 
1531 	switch (ata_try_pass_16(device)) {
1532 	case -1:
1533 		return (1);
1534 	case 1:
1535 		/* Try using SCSI Passthrough */
1536 		return ata_do_pass_16(device, ccb, retries, flags, protocol,
1537 				      0, tag_action, command, features, lba,
1538 				      sector_count, data_ptr, dxfer_len,
1539 				      timeout, quiet);
1540 	}
1541 
1542 	bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1543 	      sizeof(struct ccb_hdr));
1544 	cam_fill_ataio(&ccb->ataio,
1545 		       retries,
1546 		       NULL,
1547 		       flags,
1548 		       tag_action,
1549 		       data_ptr,
1550 		       dxfer_len,
1551 		       timeout);
1552 
1553 	ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1554 	return ata_cam_send(device, ccb, quiet);
1555 }
1556 
1557 static void
1558 dump_data(uint16_t *ptr, uint32_t len)
1559 {
1560 	u_int i;
1561 
1562 	for (i = 0; i < len / 2; i++) {
1563 		if ((i % 8) == 0)
1564 			printf(" %3d: ", i);
1565 		printf("%04hx ", ptr[i]);
1566 		if ((i % 8) == 7)
1567 			printf("\n");
1568 	}
1569 	if ((i % 8) != 7)
1570 		printf("\n");
1571 }
1572 
1573 static int
1574 ata_do_identify(struct cam_device *device, int retry_count, int timeout,
1575 		union ccb *ccb, struct ata_params** ident_bufp)
1576 {
1577 	struct ata_params *ident_buf;
1578 	struct ccb_pathinq cpi;
1579 	struct ccb_getdev cgd;
1580 	u_int i, error;
1581 	int16_t *ptr;
1582 	u_int8_t command, retry_command;
1583 
1584 	if (get_cpi(device, &cpi) != 0) {
1585 		warnx("couldn't get CPI");
1586 		return (-1);
1587 	}
1588 
1589 	/* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */
1590 	if (cpi.protocol == PROTO_ATA) {
1591 		if (get_cgd(device, &cgd) != 0) {
1592 			warnx("couldn't get CGD");
1593 			return (-1);
1594 		}
1595 
1596 		command = (cgd.protocol == PROTO_ATA) ?
1597 		    ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
1598 		retry_command = 0;
1599 	} else {
1600 		/* We don't know which for sure so try both */
1601 		command = ATA_ATA_IDENTIFY;
1602 		retry_command = ATA_ATAPI_IDENTIFY;
1603 	}
1604 
1605 	ptr = (uint16_t *)calloc(1, sizeof(struct ata_params));
1606 	if (ptr == NULL) {
1607 		warnx("can't calloc memory for identify\n");
1608 		return (1);
1609 	}
1610 
1611 	error = ata_do_28bit_cmd(device,
1612 				 ccb,
1613 				 /*retries*/retry_count,
1614 				 /*flags*/CAM_DIR_IN,
1615 				 /*protocol*/AP_PROTO_PIO_IN,
1616 				 /*tag_action*/MSG_SIMPLE_Q_TAG,
1617 				 /*command*/command,
1618 				 /*features*/0,
1619 				 /*lba*/0,
1620 				 /*sector_count*/(u_int8_t)sizeof(struct ata_params),
1621 				 /*data_ptr*/(u_int8_t *)ptr,
1622 				 /*dxfer_len*/sizeof(struct ata_params),
1623 				 /*timeout*/timeout ? timeout : 30 * 1000,
1624 				 /*quiet*/1);
1625 
1626 	if (error != 0) {
1627 		if (retry_command == 0) {
1628 			free(ptr);
1629 			return (1);
1630 		}
1631 		error = ata_do_28bit_cmd(device,
1632 					 ccb,
1633 					 /*retries*/retry_count,
1634 					 /*flags*/CAM_DIR_IN,
1635 					 /*protocol*/AP_PROTO_PIO_IN,
1636 					 /*tag_action*/MSG_SIMPLE_Q_TAG,
1637 					 /*command*/retry_command,
1638 					 /*features*/0,
1639 					 /*lba*/0,
1640 					 /*sector_count*/(u_int8_t)
1641 					     sizeof(struct ata_params),
1642 					 /*data_ptr*/(u_int8_t *)ptr,
1643 					 /*dxfer_len*/sizeof(struct ata_params),
1644 					 /*timeout*/timeout ? timeout : 30 * 1000,
1645 					 /*quiet*/0);
1646 
1647 		if (error != 0) {
1648 			free(ptr);
1649 			return (1);
1650 		}
1651 	}
1652 
1653 	error = 1;
1654 	for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1655 		ptr[i] = le16toh(ptr[i]);
1656 		if (ptr[i] != 0)
1657 			error = 0;
1658 	}
1659 
1660 	if (arglist & CAM_ARG_VERBOSE) {
1661 		fprintf(stdout, "%s%d: Raw identify data:\n",
1662 		    device->device_name, device->dev_unit_num);
1663 		dump_data(ptr, sizeof(struct ata_params));
1664 	}
1665 
1666 	/* check for invalid (all zero) response */
1667 	if (error != 0) {
1668 		warnx("Invalid identify response detected");
1669 		free(ptr);
1670 		return (error);
1671 	}
1672 
1673 	ident_buf = (struct ata_params *)ptr;
1674 	if (strncmp(ident_buf->model, "FX", 2) &&
1675 	    strncmp(ident_buf->model, "NEC", 3) &&
1676 	    strncmp(ident_buf->model, "Pioneer", 7) &&
1677 	    strncmp(ident_buf->model, "SHARP", 5)) {
1678 		ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1679 		ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1680 		ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1681 		ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1682 	}
1683 	ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1684 	ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1685 	ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1686 	ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1687 	ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1688 	ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1689 	ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1690 	ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1691 	    sizeof(ident_buf->media_serial));
1692 
1693 	*ident_bufp = ident_buf;
1694 
1695 	return (0);
1696 }
1697 
1698 
1699 static int
1700 ataidentify(struct cam_device *device, int retry_count, int timeout)
1701 {
1702 	union ccb *ccb;
1703 	struct ata_params *ident_buf;
1704 
1705 	if ((ccb = cam_getccb(device)) == NULL) {
1706 		warnx("couldn't allocate CCB");
1707 		return (1);
1708 	}
1709 
1710 	if (ata_do_identify(device, retry_count, timeout, ccb, &ident_buf) != 0) {
1711 		cam_freeccb(ccb);
1712 		return (1);
1713 	}
1714 
1715 	printf("%s%d: ", device->device_name, device->dev_unit_num);
1716 	ata_print_ident(ident_buf);
1717 	camxferrate(device);
1718 	atacapprint(ident_buf);
1719 
1720 	free(ident_buf);
1721 	cam_freeccb(ccb);
1722 
1723 	return (0);
1724 }
1725 #endif /* MINIMALISTIC */
1726 
1727 
1728 #ifndef MINIMALISTIC
1729 enum {
1730 	ATA_SECURITY_ACTION_PRINT,
1731 	ATA_SECURITY_ACTION_FREEZE,
1732 	ATA_SECURITY_ACTION_UNLOCK,
1733 	ATA_SECURITY_ACTION_DISABLE,
1734 	ATA_SECURITY_ACTION_ERASE,
1735 	ATA_SECURITY_ACTION_ERASE_ENHANCED,
1736 	ATA_SECURITY_ACTION_SET_PASSWORD
1737 };
1738 
1739 static void
1740 atasecurity_print_time(u_int16_t tw)
1741 {
1742 
1743 	if (tw == 0)
1744 		printf("unspecified");
1745 	else if (tw >= 255)
1746 		printf("> 508 min");
1747 	else
1748 		printf("%i min", 2 * tw);
1749 }
1750 
1751 static u_int32_t
1752 atasecurity_erase_timeout_msecs(u_int16_t timeout)
1753 {
1754 
1755 	if (timeout == 0)
1756 		return 2 * 3600 * 1000; /* default: two hours */
1757 	else if (timeout > 255)
1758 		return (508 + 60) * 60 * 1000; /* spec says > 508 minutes */
1759 
1760 	return ((2 * timeout) + 5) * 60 * 1000; /* add a 5min margin */
1761 }
1762 
1763 
1764 static void
1765 atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
1766 {
1767 	struct ata_cmd cmd;
1768 
1769 	bzero(&cmd, sizeof(cmd));
1770 	cmd.command = command;
1771 	printf("Issuing %s", ata_op_string(&cmd));
1772 
1773 	if (pwd != NULL) {
1774 		char pass[sizeof(pwd->password)+1];
1775 
1776 		/* pwd->password may not be null terminated */
1777 		pass[sizeof(pwd->password)] = '\0';
1778 		strncpy(pass, pwd->password, sizeof(pwd->password));
1779 		printf(" password='%s', user='%s'",
1780 			pass,
1781 			(pwd->ctrl & ATA_SECURITY_PASSWORD_MASTER) ?
1782 			"master" : "user");
1783 
1784 		if (command == ATA_SECURITY_SET_PASSWORD) {
1785 			printf(", mode='%s'",
1786 			       (pwd->ctrl & ATA_SECURITY_LEVEL_MAXIMUM) ?
1787 			       "maximum" : "high");
1788 		}
1789 	}
1790 
1791 	printf("\n");
1792 }
1793 
1794 static int
1795 atasecurity_freeze(struct cam_device *device, union ccb *ccb,
1796 		   int retry_count, u_int32_t timeout, int quiet)
1797 {
1798 
1799 	if (quiet == 0)
1800 		atasecurity_notify(ATA_SECURITY_FREEZE_LOCK, NULL);
1801 
1802 	return ata_do_28bit_cmd(device,
1803 				ccb,
1804 				retry_count,
1805 				/*flags*/CAM_DIR_NONE,
1806 				/*protocol*/AP_PROTO_NON_DATA,
1807 				/*tag_action*/MSG_SIMPLE_Q_TAG,
1808 				/*command*/ATA_SECURITY_FREEZE_LOCK,
1809 				/*features*/0,
1810 				/*lba*/0,
1811 				/*sector_count*/0,
1812 				/*data_ptr*/NULL,
1813 				/*dxfer_len*/0,
1814 				/*timeout*/timeout,
1815 				/*quiet*/0);
1816 }
1817 
1818 static int
1819 atasecurity_unlock(struct cam_device *device, union ccb *ccb,
1820 		   int retry_count, u_int32_t timeout,
1821 		   struct ata_security_password *pwd, int quiet)
1822 {
1823 
1824 	if (quiet == 0)
1825 		atasecurity_notify(ATA_SECURITY_UNLOCK, pwd);
1826 
1827 	return ata_do_28bit_cmd(device,
1828 				ccb,
1829 				retry_count,
1830 				/*flags*/CAM_DIR_OUT,
1831 				/*protocol*/AP_PROTO_PIO_OUT,
1832 				/*tag_action*/MSG_SIMPLE_Q_TAG,
1833 				/*command*/ATA_SECURITY_UNLOCK,
1834 				/*features*/0,
1835 				/*lba*/0,
1836 				/*sector_count*/0,
1837 				/*data_ptr*/(u_int8_t *)pwd,
1838 				/*dxfer_len*/sizeof(*pwd),
1839 				/*timeout*/timeout,
1840 				/*quiet*/0);
1841 }
1842 
1843 static int
1844 atasecurity_disable(struct cam_device *device, union ccb *ccb,
1845 		    int retry_count, u_int32_t timeout,
1846 		    struct ata_security_password *pwd, int quiet)
1847 {
1848 
1849 	if (quiet == 0)
1850 		atasecurity_notify(ATA_SECURITY_DISABLE_PASSWORD, pwd);
1851 	return ata_do_28bit_cmd(device,
1852 				ccb,
1853 				retry_count,
1854 				/*flags*/CAM_DIR_OUT,
1855 				/*protocol*/AP_PROTO_PIO_OUT,
1856 				/*tag_action*/MSG_SIMPLE_Q_TAG,
1857 				/*command*/ATA_SECURITY_DISABLE_PASSWORD,
1858 				/*features*/0,
1859 				/*lba*/0,
1860 				/*sector_count*/0,
1861 				/*data_ptr*/(u_int8_t *)pwd,
1862 				/*dxfer_len*/sizeof(*pwd),
1863 				/*timeout*/timeout,
1864 				/*quiet*/0);
1865 }
1866 
1867 
1868 static int
1869 atasecurity_erase_confirm(struct cam_device *device,
1870 			  struct ata_params* ident_buf)
1871 {
1872 
1873 	printf("\nYou are about to ERASE ALL DATA from the following"
1874 	       " device:\n%s%d,%s%d: ", device->device_name,
1875 	       device->dev_unit_num, device->given_dev_name,
1876 	       device->given_unit_number);
1877 	ata_print_ident(ident_buf);
1878 
1879 	for(;;) {
1880 		char str[50];
1881 		printf("\nAre you SURE you want to ERASE ALL DATA? (yes/no) ");
1882 
1883 		if (fgets(str, sizeof(str), stdin) != NULL) {
1884 			if (strncasecmp(str, "yes", 3) == 0) {
1885 				return (1);
1886 			} else if (strncasecmp(str, "no", 2) == 0) {
1887 				return (0);
1888 			} else {
1889 				printf("Please answer \"yes\" or "
1890 				       "\"no\"\n");
1891 			}
1892 		}
1893 	}
1894 
1895 	/* NOTREACHED */
1896 	return (0);
1897 }
1898 
1899 static int
1900 atasecurity_erase(struct cam_device *device, union ccb *ccb,
1901 		  int retry_count, u_int32_t timeout,
1902 		  u_int32_t erase_timeout,
1903 		  struct ata_security_password *pwd, int quiet)
1904 {
1905 	int error;
1906 
1907 	if (quiet == 0)
1908 		atasecurity_notify(ATA_SECURITY_ERASE_PREPARE, NULL);
1909 
1910 	error = ata_do_28bit_cmd(device,
1911 				 ccb,
1912 				 retry_count,
1913 				 /*flags*/CAM_DIR_NONE,
1914 				 /*protocol*/AP_PROTO_NON_DATA,
1915 				 /*tag_action*/MSG_SIMPLE_Q_TAG,
1916 				 /*command*/ATA_SECURITY_ERASE_PREPARE,
1917 				 /*features*/0,
1918 				 /*lba*/0,
1919 				 /*sector_count*/0,
1920 				 /*data_ptr*/NULL,
1921 				 /*dxfer_len*/0,
1922 				 /*timeout*/timeout,
1923 				 /*quiet*/0);
1924 
1925 	if (error != 0)
1926 		return error;
1927 
1928 	if (quiet == 0)
1929 		atasecurity_notify(ATA_SECURITY_ERASE_UNIT, pwd);
1930 
1931 	error = ata_do_28bit_cmd(device,
1932 				 ccb,
1933 				 retry_count,
1934 				 /*flags*/CAM_DIR_OUT,
1935 				 /*protocol*/AP_PROTO_PIO_OUT,
1936 				 /*tag_action*/MSG_SIMPLE_Q_TAG,
1937 				 /*command*/ATA_SECURITY_ERASE_UNIT,
1938 				 /*features*/0,
1939 				 /*lba*/0,
1940 				 /*sector_count*/0,
1941 				 /*data_ptr*/(u_int8_t *)pwd,
1942 				 /*dxfer_len*/sizeof(*pwd),
1943 				 /*timeout*/erase_timeout,
1944 				 /*quiet*/0);
1945 
1946 	if (error == 0 && quiet == 0)
1947 		printf("\nErase Complete\n");
1948 
1949 	return error;
1950 }
1951 
1952 static int
1953 atasecurity_set_password(struct cam_device *device, union ccb *ccb,
1954 			 int retry_count, u_int32_t timeout,
1955 			 struct ata_security_password *pwd, int quiet)
1956 {
1957 
1958 	if (quiet == 0)
1959 		atasecurity_notify(ATA_SECURITY_SET_PASSWORD, pwd);
1960 
1961 	return ata_do_28bit_cmd(device,
1962 				 ccb,
1963 				 retry_count,
1964 				 /*flags*/CAM_DIR_OUT,
1965 				 /*protocol*/AP_PROTO_PIO_OUT,
1966 				 /*tag_action*/MSG_SIMPLE_Q_TAG,
1967 				 /*command*/ATA_SECURITY_SET_PASSWORD,
1968 				 /*features*/0,
1969 				 /*lba*/0,
1970 				 /*sector_count*/0,
1971 				 /*data_ptr*/(u_int8_t *)pwd,
1972 				 /*dxfer_len*/sizeof(*pwd),
1973 				 /*timeout*/timeout,
1974 				 /*quiet*/0);
1975 }
1976 
1977 static void
1978 atasecurity_print(struct ata_params *parm)
1979 {
1980 
1981 	printf("\nSecurity Option           Value\n");
1982 	if (arglist & CAM_ARG_VERBOSE) {
1983 		printf("status                    %04x\n",
1984 		       parm->security_status);
1985 	}
1986 	printf("supported                 %s\n",
1987 		parm->security_status & ATA_SECURITY_SUPPORTED ? "yes" : "no");
1988 	if (!(parm->security_status & ATA_SECURITY_SUPPORTED))
1989 		return;
1990 	printf("enabled                   %s\n",
1991 		parm->security_status & ATA_SECURITY_ENABLED ? "yes" : "no");
1992 	printf("drive locked              %s\n",
1993 		parm->security_status & ATA_SECURITY_LOCKED ? "yes" : "no");
1994 	printf("security config frozen    %s\n",
1995 		parm->security_status & ATA_SECURITY_FROZEN ? "yes" : "no");
1996 	printf("count expired             %s\n",
1997 		parm->security_status & ATA_SECURITY_COUNT_EXP ? "yes" : "no");
1998 	printf("security level            %s\n",
1999 		parm->security_status & ATA_SECURITY_LEVEL ? "maximum" : "high");
2000 	printf("enhanced erase supported  %s\n",
2001 		parm->security_status & ATA_SECURITY_ENH_SUPP ? "yes" : "no");
2002 	printf("erase time                ");
2003 	atasecurity_print_time(parm->erase_time);
2004 	printf("\n");
2005 	printf("enhanced erase time       ");
2006 	atasecurity_print_time(parm->enhanced_erase_time);
2007 	printf("\n");
2008 	printf("master password rev       %04x%s\n",
2009 		parm->master_passwd_revision,
2010 		parm->master_passwd_revision == 0x0000 ||
2011 		parm->master_passwd_revision == 0xFFFF ?  " (unsupported)" : "");
2012 }
2013 
2014 /*
2015  * Validates and copies the password in optarg to the passed buffer.
2016  * If the password in optarg is the same length as the buffer then
2017  * the data will still be copied but no null termination will occur.
2018  */
2019 static int
2020 ata_getpwd(u_int8_t *passwd, int max, char opt)
2021 {
2022 	int len;
2023 
2024 	len = strlen(optarg);
2025 	if (len > max) {
2026 		warnx("-%c password is too long", opt);
2027 		return (1);
2028 	} else if (len == 0) {
2029 		warnx("-%c password is missing", opt);
2030 		return (1);
2031 	} else if (optarg[0] == '-'){
2032 		warnx("-%c password starts with '-' (generic arg?)", opt);
2033 		return (1);
2034 	} else if (strlen(passwd) != 0 && strcmp(passwd, optarg) != 0) {
2035 		warnx("-%c password conflicts with existing password from -%c",
2036 		      opt, pwd_opt);
2037 		return (1);
2038 	}
2039 
2040 	/* Callers pass in a buffer which does NOT need to be terminated */
2041 	strncpy(passwd, optarg, max);
2042 	pwd_opt = opt;
2043 
2044 	return (0);
2045 }
2046 
2047 static int
2048 atasecurity(struct cam_device *device, int retry_count, int timeout,
2049 	    int argc, char **argv, char *combinedopt)
2050 {
2051 	union ccb *ccb;
2052 	struct ata_params *ident_buf;
2053 	int error, confirm, quiet, c, action, actions, setpwd;
2054 	int security_enabled, erase_timeout, pwdsize;
2055 	struct ata_security_password pwd;
2056 
2057 	actions = 0;
2058 	setpwd = 0;
2059 	erase_timeout = 0;
2060 	confirm = 0;
2061 	quiet = 0;
2062 
2063 	memset(&pwd, 0, sizeof(pwd));
2064 
2065 	/* default action is to print security information */
2066 	action = ATA_SECURITY_ACTION_PRINT;
2067 
2068 	/* user is master by default as its safer that way */
2069 	pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2070 	pwdsize = sizeof(pwd.password);
2071 
2072 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2073 		switch(c){
2074 		case 'f':
2075 			action = ATA_SECURITY_ACTION_FREEZE;
2076 			actions++;
2077 			break;
2078 
2079 		case 'U':
2080 			if (strcasecmp(optarg, "user") == 0) {
2081 				pwd.ctrl |= ATA_SECURITY_PASSWORD_USER;
2082 				pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER;
2083 			} else if (strcasecmp(optarg, "master") != 0) {
2084 				pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2085 				pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER;
2086 			} else {
2087 				warnx("-U argument '%s' is invalid (must be "
2088 				      "'user' or 'master')", optarg);
2089 				return (1);
2090 			}
2091 			break;
2092 
2093 		case 'l':
2094 			if (strcasecmp(optarg, "high") == 0) {
2095 				pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH;
2096 				pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM;
2097 			} else if (strcasecmp(optarg, "maximum") == 0) {
2098 				pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM;
2099 				pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH;
2100 			} else {
2101 				warnx("-l argument '%s' is unknown (must be "
2102 				      "'high' or 'maximum')", optarg);
2103 				return (1);
2104 			}
2105 			break;
2106 
2107 		case 'k':
2108 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2109 				return (1);
2110 			action = ATA_SECURITY_ACTION_UNLOCK;
2111 			actions++;
2112 			break;
2113 
2114 		case 'd':
2115 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2116 				return (1);
2117 			action = ATA_SECURITY_ACTION_DISABLE;
2118 			actions++;
2119 			break;
2120 
2121 		case 'e':
2122 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2123 				return (1);
2124 			action = ATA_SECURITY_ACTION_ERASE;
2125 			actions++;
2126 			break;
2127 
2128 		case 'h':
2129 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2130 				return (1);
2131 			pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED;
2132 			action = ATA_SECURITY_ACTION_ERASE_ENHANCED;
2133 			actions++;
2134 			break;
2135 
2136 		case 's':
2137 			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2138 				return (1);
2139 			setpwd = 1;
2140 			if (action == ATA_SECURITY_ACTION_PRINT)
2141 				action = ATA_SECURITY_ACTION_SET_PASSWORD;
2142 			/*
2143 			 * Don't increment action as this can be combined
2144 			 * with other actions.
2145 			 */
2146 			break;
2147 
2148 		case 'y':
2149 			confirm++;
2150 			break;
2151 
2152 		case 'q':
2153 			quiet++;
2154 			break;
2155 
2156 		case 'T':
2157 			erase_timeout = atoi(optarg) * 1000;
2158 			break;
2159 		}
2160 	}
2161 
2162 	if (actions > 1) {
2163 		warnx("too many security actions specified");
2164 		return (1);
2165 	}
2166 
2167 	if ((ccb = cam_getccb(device)) == NULL) {
2168 		warnx("couldn't allocate CCB");
2169 		return (1);
2170 	}
2171 
2172 	error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2173 	if (error != 0) {
2174 		cam_freeccb(ccb);
2175 		return (1);
2176 	}
2177 
2178 	if (quiet == 0) {
2179 		printf("%s%d: ", device->device_name, device->dev_unit_num);
2180 		ata_print_ident(ident_buf);
2181 		camxferrate(device);
2182 	}
2183 
2184 	if (action == ATA_SECURITY_ACTION_PRINT) {
2185 		atasecurity_print(ident_buf);
2186 		free(ident_buf);
2187 		cam_freeccb(ccb);
2188 		return (0);
2189 	}
2190 
2191 	if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) {
2192 		warnx("Security not supported");
2193 		free(ident_buf);
2194 		cam_freeccb(ccb);
2195 		return (1);
2196 	}
2197 
2198 	/* default timeout 15 seconds the same as linux hdparm */
2199 	timeout = timeout ? timeout : 15 * 1000;
2200 
2201 	security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED;
2202 
2203 	/* first set the password if requested */
2204 	if (setpwd == 1) {
2205 		/* confirm we can erase before setting the password if erasing */
2206 		if (confirm == 0 &&
2207 		    (action == ATA_SECURITY_ACTION_ERASE_ENHANCED ||
2208 		    action == ATA_SECURITY_ACTION_ERASE) &&
2209 		    atasecurity_erase_confirm(device, ident_buf) == 0) {
2210 			cam_freeccb(ccb);
2211 			free(ident_buf);
2212 			return (error);
2213 		}
2214 
2215 		if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) {
2216 			pwd.revision = ident_buf->master_passwd_revision;
2217 			if (pwd.revision != 0 && pwd.revision != 0xfff &&
2218 			    --pwd.revision == 0) {
2219 				pwd.revision = 0xfffe;
2220 			}
2221 		}
2222 		error = atasecurity_set_password(device, ccb, retry_count,
2223 						 timeout, &pwd, quiet);
2224 		if (error != 0) {
2225 			cam_freeccb(ccb);
2226 			free(ident_buf);
2227 			return (error);
2228 		}
2229 		security_enabled = 1;
2230 	}
2231 
2232 	switch(action) {
2233 	case ATA_SECURITY_ACTION_FREEZE:
2234 		error = atasecurity_freeze(device, ccb, retry_count,
2235 					   timeout, quiet);
2236 		break;
2237 
2238 	case ATA_SECURITY_ACTION_UNLOCK:
2239 		if (security_enabled) {
2240 			if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2241 				error = atasecurity_unlock(device, ccb,
2242 					retry_count, timeout, &pwd, quiet);
2243 			} else {
2244 				warnx("Can't unlock, drive is not locked");
2245 				error = 1;
2246 			}
2247 		} else {
2248 			warnx("Can't unlock, security is disabled");
2249 			error = 1;
2250 		}
2251 		break;
2252 
2253 	case ATA_SECURITY_ACTION_DISABLE:
2254 		if (security_enabled) {
2255 			/* First unlock the drive if its locked */
2256 			if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2257 				error = atasecurity_unlock(device, ccb,
2258 							   retry_count,
2259 							   timeout,
2260 							   &pwd,
2261 							   quiet);
2262 			}
2263 
2264 			if (error == 0) {
2265 				error = atasecurity_disable(device,
2266 							    ccb,
2267 							    retry_count,
2268 							    timeout,
2269 							    &pwd,
2270 							    quiet);
2271 			}
2272 		} else {
2273 			warnx("Can't disable security (already disabled)");
2274 			error = 1;
2275 		}
2276 		break;
2277 
2278 	case ATA_SECURITY_ACTION_ERASE:
2279 		if (security_enabled) {
2280 			if (erase_timeout == 0) {
2281 				erase_timeout = atasecurity_erase_timeout_msecs(
2282 				    ident_buf->erase_time);
2283 			}
2284 
2285 			error = atasecurity_erase(device, ccb, retry_count,
2286 					          timeout, erase_timeout, &pwd,
2287 						  quiet);
2288 		} else {
2289 			warnx("Can't secure erase (security is disabled)");
2290 			error = 1;
2291 		}
2292 		break;
2293 
2294 	case ATA_SECURITY_ACTION_ERASE_ENHANCED:
2295 		if (security_enabled) {
2296 			if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) {
2297 				if (erase_timeout == 0) {
2298 					erase_timeout =
2299 					    atasecurity_erase_timeout_msecs(
2300 						ident_buf->enhanced_erase_time);
2301 				}
2302 
2303 				error = atasecurity_erase(device, ccb,
2304 							  retry_count, timeout,
2305 							  erase_timeout, &pwd,
2306 							  quiet);
2307 			} else {
2308 				warnx("Enhanced erase is not supported");
2309 				error = 1;
2310 			}
2311 		} else {
2312 			warnx("Can't secure erase (enhanced), "
2313 			      "(security is disabled)");
2314 			error = 1;
2315 		}
2316 		break;
2317 	}
2318 
2319 	cam_freeccb(ccb);
2320 	free(ident_buf);
2321 
2322 	return (error);
2323 }
2324 #endif /* MINIMALISTIC */
2325 
2326 /*
2327  * Parse out a bus, or a bus, target and lun in the following
2328  * format:
2329  * bus
2330  * bus:target
2331  * bus:target:lun
2332  *
2333  * Returns the number of parsed components, or 0.
2334  */
2335 static int
2336 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
2337 {
2338 	char *tmpstr;
2339 	int convs = 0;
2340 
2341 	while (isspace(*tstr) && (*tstr != '\0'))
2342 		tstr++;
2343 
2344 	tmpstr = (char *)strtok(tstr, ":");
2345 	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
2346 		*bus = strtol(tmpstr, NULL, 0);
2347 		*arglst |= CAM_ARG_BUS;
2348 		convs++;
2349 		tmpstr = (char *)strtok(NULL, ":");
2350 		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
2351 			*target = strtol(tmpstr, NULL, 0);
2352 			*arglst |= CAM_ARG_TARGET;
2353 			convs++;
2354 			tmpstr = (char *)strtok(NULL, ":");
2355 			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
2356 				*lun = strtol(tmpstr, NULL, 0);
2357 				*arglst |= CAM_ARG_LUN;
2358 				convs++;
2359 			}
2360 		}
2361 	}
2362 
2363 	return convs;
2364 }
2365 
2366 static int
2367 dorescan_or_reset(int argc, char **argv, int rescan)
2368 {
2369 	static const char must[] =
2370 		"you must specify \"all\", a bus, or a bus:target:lun to %s";
2371 	int rv, error = 0;
2372 	int bus = -1, target = -1, lun = -1;
2373 	char *tstr;
2374 
2375 	if (argc < 3) {
2376 		warnx(must, rescan? "rescan" : "reset");
2377 		return(1);
2378 	}
2379 
2380 	tstr = argv[optind];
2381 	while (isspace(*tstr) && (*tstr != '\0'))
2382 		tstr++;
2383 	if (strncasecmp(tstr, "all", strlen("all")) == 0)
2384 		arglist |= CAM_ARG_BUS;
2385 	else {
2386 		rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
2387 		if (rv != 1 && rv != 3) {
2388 			warnx(must, rescan? "rescan" : "reset");
2389 			return(1);
2390 		}
2391 	}
2392 
2393 	if ((arglist & CAM_ARG_BUS)
2394 	    && (arglist & CAM_ARG_TARGET)
2395 	    && (arglist & CAM_ARG_LUN))
2396 		error = scanlun_or_reset_dev(bus, target, lun, rescan);
2397 	else
2398 		error = rescan_or_reset_bus(bus, rescan);
2399 
2400 	return(error);
2401 }
2402 
2403 static int
2404 rescan_or_reset_bus(int bus, int rescan)
2405 {
2406 	union ccb ccb, matchccb;
2407 	int fd, retval;
2408 	int bufsize;
2409 
2410 	retval = 0;
2411 
2412 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2413 		warnx("error opening transport layer device %s", XPT_DEVICE);
2414 		warn("%s", XPT_DEVICE);
2415 		return(1);
2416 	}
2417 
2418 	if (bus != -1) {
2419 		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
2420 		ccb.ccb_h.path_id = bus;
2421 		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
2422 		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
2423 		ccb.crcn.flags = CAM_FLAG_NONE;
2424 
2425 		/* run this at a low priority */
2426 		ccb.ccb_h.pinfo.priority = 5;
2427 
2428 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2429 			warn("CAMIOCOMMAND ioctl failed");
2430 			close(fd);
2431 			return(1);
2432 		}
2433 
2434 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
2435 			fprintf(stdout, "%s of bus %d was successful\n",
2436 			    rescan ? "Re-scan" : "Reset", bus);
2437 		} else {
2438 			fprintf(stdout, "%s of bus %d returned error %#x\n",
2439 				rescan ? "Re-scan" : "Reset", bus,
2440 				ccb.ccb_h.status & CAM_STATUS_MASK);
2441 			retval = 1;
2442 		}
2443 
2444 		close(fd);
2445 		return(retval);
2446 
2447 	}
2448 
2449 
2450 	/*
2451 	 * The right way to handle this is to modify the xpt so that it can
2452 	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
2453 	 * that isn't implemented, so instead we enumerate the busses and
2454 	 * send the rescan or reset to those busses in the case where the
2455 	 * given bus is -1 (wildcard).  We don't send a rescan or reset
2456 	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
2457 	 * no-op, sending a rescan to the xpt bus would result in a status of
2458 	 * CAM_REQ_INVALID.
2459 	 */
2460 	bzero(&(&matchccb.ccb_h)[1],
2461 	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
2462 	matchccb.ccb_h.func_code = XPT_DEV_MATCH;
2463 	matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
2464 	bufsize = sizeof(struct dev_match_result) * 20;
2465 	matchccb.cdm.match_buf_len = bufsize;
2466 	matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
2467 	if (matchccb.cdm.matches == NULL) {
2468 		warnx("can't malloc memory for matches");
2469 		retval = 1;
2470 		goto bailout;
2471 	}
2472 	matchccb.cdm.num_matches = 0;
2473 
2474 	matchccb.cdm.num_patterns = 1;
2475 	matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
2476 
2477 	matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
2478 		matchccb.cdm.pattern_buf_len);
2479 	if (matchccb.cdm.patterns == NULL) {
2480 		warnx("can't malloc memory for patterns");
2481 		retval = 1;
2482 		goto bailout;
2483 	}
2484 	matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
2485 	matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
2486 
2487 	do {
2488 		unsigned int i;
2489 
2490 		if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
2491 			warn("CAMIOCOMMAND ioctl failed");
2492 			retval = 1;
2493 			goto bailout;
2494 		}
2495 
2496 		if ((matchccb.ccb_h.status != CAM_REQ_CMP)
2497 		 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
2498 		   && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
2499 			warnx("got CAM error %#x, CDM error %d\n",
2500 			      matchccb.ccb_h.status, matchccb.cdm.status);
2501 			retval = 1;
2502 			goto bailout;
2503 		}
2504 
2505 		for (i = 0; i < matchccb.cdm.num_matches; i++) {
2506 			struct bus_match_result *bus_result;
2507 
2508 			/* This shouldn't happen. */
2509 			if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
2510 				continue;
2511 
2512 			bus_result = &matchccb.cdm.matches[i].result.bus_result;
2513 
2514 			/*
2515 			 * We don't want to rescan or reset the xpt bus.
2516 			 * See above.
2517 			 */
2518 			if ((int)bus_result->path_id == -1)
2519 				continue;
2520 
2521 			ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
2522 						       XPT_RESET_BUS;
2523 			ccb.ccb_h.path_id = bus_result->path_id;
2524 			ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
2525 			ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
2526 			ccb.crcn.flags = CAM_FLAG_NONE;
2527 
2528 			/* run this at a low priority */
2529 			ccb.ccb_h.pinfo.priority = 5;
2530 
2531 			if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2532 				warn("CAMIOCOMMAND ioctl failed");
2533 				retval = 1;
2534 				goto bailout;
2535 			}
2536 
2537 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
2538 				fprintf(stdout, "%s of bus %d was successful\n",
2539 					rescan? "Re-scan" : "Reset",
2540 					bus_result->path_id);
2541 			} else {
2542 				/*
2543 				 * Don't bail out just yet, maybe the other
2544 				 * rescan or reset commands will complete
2545 				 * successfully.
2546 				 */
2547 				fprintf(stderr, "%s of bus %d returned error "
2548 					"%#x\n", rescan? "Re-scan" : "Reset",
2549 					bus_result->path_id,
2550 					ccb.ccb_h.status & CAM_STATUS_MASK);
2551 				retval = 1;
2552 			}
2553 		}
2554 	} while ((matchccb.ccb_h.status == CAM_REQ_CMP)
2555 		 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
2556 
2557 bailout:
2558 
2559 	if (fd != -1)
2560 		close(fd);
2561 
2562 	if (matchccb.cdm.patterns != NULL)
2563 		free(matchccb.cdm.patterns);
2564 	if (matchccb.cdm.matches != NULL)
2565 		free(matchccb.cdm.matches);
2566 
2567 	return(retval);
2568 }
2569 
2570 static int
2571 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
2572 {
2573 	union ccb ccb;
2574 	struct cam_device *device;
2575 	int fd;
2576 
2577 	device = NULL;
2578 
2579 	if (bus < 0) {
2580 		warnx("invalid bus number %d", bus);
2581 		return(1);
2582 	}
2583 
2584 	if (target < 0) {
2585 		warnx("invalid target number %d", target);
2586 		return(1);
2587 	}
2588 
2589 	if (lun < 0) {
2590 		warnx("invalid lun number %d", lun);
2591 		return(1);
2592 	}
2593 
2594 	fd = -1;
2595 
2596 	bzero(&ccb, sizeof(union ccb));
2597 
2598 	if (scan) {
2599 		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2600 			warnx("error opening transport layer device %s\n",
2601 			    XPT_DEVICE);
2602 			warn("%s", XPT_DEVICE);
2603 			return(1);
2604 		}
2605 	} else {
2606 		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
2607 		if (device == NULL) {
2608 			warnx("%s", cam_errbuf);
2609 			return(1);
2610 		}
2611 	}
2612 
2613 	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
2614 	ccb.ccb_h.path_id = bus;
2615 	ccb.ccb_h.target_id = target;
2616 	ccb.ccb_h.target_lun = lun;
2617 	ccb.ccb_h.timeout = 5000;
2618 	ccb.crcn.flags = CAM_FLAG_NONE;
2619 
2620 	/* run this at a low priority */
2621 	ccb.ccb_h.pinfo.priority = 5;
2622 
2623 	if (scan) {
2624 		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
2625 			warn("CAMIOCOMMAND ioctl failed");
2626 			close(fd);
2627 			return(1);
2628 		}
2629 	} else {
2630 		if (cam_send_ccb(device, &ccb) < 0) {
2631 			warn("error sending XPT_RESET_DEV CCB");
2632 			cam_close_device(device);
2633 			return(1);
2634 		}
2635 	}
2636 
2637 	if (scan)
2638 		close(fd);
2639 	else
2640 		cam_close_device(device);
2641 
2642 	/*
2643 	 * An error code of CAM_BDR_SENT is normal for a BDR request.
2644 	 */
2645 	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2646 	 || ((!scan)
2647 	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
2648 		fprintf(stdout, "%s of %d:%d:%d was successful\n",
2649 		    scan? "Re-scan" : "Reset", bus, target, lun);
2650 		return(0);
2651 	} else {
2652 		fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
2653 		    scan? "Re-scan" : "Reset", bus, target, lun,
2654 		    ccb.ccb_h.status & CAM_STATUS_MASK);
2655 		return(1);
2656 	}
2657 }
2658 
2659 #ifndef MINIMALISTIC
2660 static int
2661 readdefects(struct cam_device *device, int argc, char **argv,
2662 	    char *combinedopt, int retry_count, int timeout)
2663 {
2664 	union ccb *ccb = NULL;
2665 	struct scsi_read_defect_data_10 *rdd_cdb;
2666 	u_int8_t *defect_list = NULL;
2667 	u_int32_t max_dlist_length = SRDD10_MAX_LENGTH, dlist_length = 0;
2668 	u_int32_t returned_length = 0;
2669 	u_int32_t num_returned = 0;
2670 	u_int8_t returned_format;
2671 	unsigned int i;
2672 	int c, error = 0;
2673 	int lists_specified;
2674 	int get_length = 1;
2675 
2676 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2677 		switch(c){
2678 		case 'f':
2679 		{
2680 			char *tstr;
2681 			tstr = optarg;
2682 			while (isspace(*tstr) && (*tstr != '\0'))
2683 				tstr++;
2684 			if (strcmp(tstr, "block") == 0)
2685 				arglist |= CAM_ARG_FORMAT_BLOCK;
2686 			else if (strcmp(tstr, "bfi") == 0)
2687 				arglist |= CAM_ARG_FORMAT_BFI;
2688 			else if (strcmp(tstr, "phys") == 0)
2689 				arglist |= CAM_ARG_FORMAT_PHYS;
2690 			else {
2691 				error = 1;
2692 				warnx("invalid defect format %s", tstr);
2693 				goto defect_bailout;
2694 			}
2695 			break;
2696 		}
2697 		case 'G':
2698 			arglist |= CAM_ARG_GLIST;
2699 			break;
2700 		case 'P':
2701 			arglist |= CAM_ARG_PLIST;
2702 			break;
2703 		default:
2704 			break;
2705 		}
2706 	}
2707 
2708 	ccb = cam_getccb(device);
2709 
2710 	/*
2711 	 * Eventually we should probably support the 12 byte READ DEFECT
2712 	 * DATA command.  It supports a longer parameter list, which may be
2713 	 * necessary on newer drives with lots of defects.  According to
2714 	 * the SBC-3 spec, drives are supposed to return an illegal request
2715 	 * if they have more defect data than will fit in 64K.
2716 	 */
2717 	defect_list = malloc(max_dlist_length);
2718 	if (defect_list == NULL) {
2719 		warnx("can't malloc memory for defect list");
2720 		error = 1;
2721 		goto defect_bailout;
2722 	}
2723 
2724 	/*
2725 	 * We start off asking for just the header to determine how much
2726 	 * defect data is available.  Some Hitachi drives return an error
2727 	 * if you ask for more data than the drive has.  Once we know the
2728 	 * length, we retry the command with the returned length.
2729 	 */
2730 	dlist_length = sizeof(struct scsi_read_defect_data_hdr_10);
2731 
2732 	rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
2733 
2734 retry:
2735 
2736 	lists_specified = 0;
2737 
2738 	/*
2739 	 * cam_getccb() zeros the CCB header only.  So we need to zero the
2740 	 * payload portion of the ccb.
2741 	 */
2742 	bzero(&(&ccb->ccb_h)[1],
2743 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2744 
2745 	cam_fill_csio(&ccb->csio,
2746 		      /*retries*/ retry_count,
2747 		      /*cbfcnp*/ NULL,
2748 		      /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
2749 					      CAM_PASS_ERR_RECOVER : 0),
2750 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
2751 		      /*data_ptr*/ defect_list,
2752 		      /*dxfer_len*/ dlist_length,
2753 		      /*sense_len*/ SSD_FULL_SIZE,
2754 		      /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
2755 		      /*timeout*/ timeout ? timeout : 5000);
2756 
2757 	rdd_cdb->opcode = READ_DEFECT_DATA_10;
2758 	if (arglist & CAM_ARG_FORMAT_BLOCK)
2759 		rdd_cdb->format = SRDD10_BLOCK_FORMAT;
2760 	else if (arglist & CAM_ARG_FORMAT_BFI)
2761 		rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
2762 	else if (arglist & CAM_ARG_FORMAT_PHYS)
2763 		rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
2764 	else {
2765 		error = 1;
2766 		warnx("no defect list format specified");
2767 		goto defect_bailout;
2768 	}
2769 	if (arglist & CAM_ARG_PLIST) {
2770 		rdd_cdb->format |= SRDD10_PLIST;
2771 		lists_specified++;
2772 	}
2773 
2774 	if (arglist & CAM_ARG_GLIST) {
2775 		rdd_cdb->format |= SRDD10_GLIST;
2776 		lists_specified++;
2777 	}
2778 
2779 	scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
2780 
2781 	/* Disable freezing the device queue */
2782 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2783 
2784 	if (cam_send_ccb(device, ccb) < 0) {
2785 		perror("error reading defect list");
2786 
2787 		if (arglist & CAM_ARG_VERBOSE) {
2788 			cam_error_print(device, ccb, CAM_ESF_ALL,
2789 					CAM_EPF_ALL, stderr);
2790 		}
2791 
2792 		error = 1;
2793 		goto defect_bailout;
2794 	}
2795 
2796 	returned_length = scsi_2btoul(((struct
2797 		scsi_read_defect_data_hdr_10 *)defect_list)->length);
2798 
2799 	if (get_length != 0) {
2800 		get_length = 0;
2801 
2802 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
2803 		     CAM_SCSI_STATUS_ERROR) {
2804 			struct scsi_sense_data *sense;
2805 			int error_code, sense_key, asc, ascq;
2806 
2807 			sense = &ccb->csio.sense_data;
2808 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
2809 			    ccb->csio.sense_resid, &error_code, &sense_key,
2810 			    &asc, &ascq, /*show_errors*/ 1);
2811 
2812 			/*
2813 			 * If the drive is reporting that it just doesn't
2814 			 * support the defect list format, go ahead and use
2815 			 * the length it reported.  Otherwise, the length
2816 			 * may not be valid, so use the maximum.
2817 			 */
2818 			if ((sense_key == SSD_KEY_RECOVERED_ERROR)
2819 			 && (asc == 0x1c) && (ascq == 0x00)
2820 			 && (returned_length > 0)) {
2821 				dlist_length = returned_length +
2822 				    sizeof(struct scsi_read_defect_data_hdr_10);
2823 				dlist_length = min(dlist_length,
2824 						   SRDD10_MAX_LENGTH);
2825 			} else
2826 				dlist_length = max_dlist_length;
2827 		} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
2828 			    CAM_REQ_CMP){
2829 			error = 1;
2830 			warnx("Error reading defect header");
2831 			if (arglist & CAM_ARG_VERBOSE)
2832 				cam_error_print(device, ccb, CAM_ESF_ALL,
2833 						CAM_EPF_ALL, stderr);
2834 			goto defect_bailout;
2835 		} else {
2836 			dlist_length = returned_length +
2837 			    sizeof(struct scsi_read_defect_data_hdr_10);
2838 			dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
2839 		}
2840 
2841 		goto retry;
2842 	}
2843 
2844 	returned_format = ((struct scsi_read_defect_data_hdr_10 *)
2845 			defect_list)->format;
2846 
2847 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
2848 	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
2849 	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
2850 		struct scsi_sense_data *sense;
2851 		int error_code, sense_key, asc, ascq;
2852 
2853 		sense = &ccb->csio.sense_data;
2854 		scsi_extract_sense_len(sense, ccb->csio.sense_len -
2855 		    ccb->csio.sense_resid, &error_code, &sense_key, &asc,
2856 		    &ascq, /*show_errors*/ 1);
2857 
2858 		/*
2859 		 * According to the SCSI spec, if the disk doesn't support
2860 		 * the requested format, it will generally return a sense
2861 		 * key of RECOVERED ERROR, and an additional sense code
2862 		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
2863 		 * also check to make sure that the returned length is
2864 		 * greater than 0, and then print out whatever format the
2865 		 * disk gave us.
2866 		 */
2867 		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
2868 		 && (asc == 0x1c) && (ascq == 0x00)
2869 		 && (returned_length > 0)) {
2870 			warnx("requested defect format not available");
2871 			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
2872 			case SRDD10_BLOCK_FORMAT:
2873 				warnx("Device returned block format");
2874 				break;
2875 			case SRDD10_BYTES_FROM_INDEX_FORMAT:
2876 				warnx("Device returned bytes from index"
2877 				      " format");
2878 				break;
2879 			case SRDD10_PHYSICAL_SECTOR_FORMAT:
2880 				warnx("Device returned physical sector format");
2881 				break;
2882 			default:
2883 				error = 1;
2884 				warnx("Device returned unknown defect"
2885 				     " data format %#x", returned_format);
2886 				goto defect_bailout;
2887 				break; /* NOTREACHED */
2888 			}
2889 		} else {
2890 			error = 1;
2891 			warnx("Error returned from read defect data command");
2892 			if (arglist & CAM_ARG_VERBOSE)
2893 				cam_error_print(device, ccb, CAM_ESF_ALL,
2894 						CAM_EPF_ALL, stderr);
2895 			goto defect_bailout;
2896 		}
2897 	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2898 		error = 1;
2899 		warnx("Error returned from read defect data command");
2900 		if (arglist & CAM_ARG_VERBOSE)
2901 			cam_error_print(device, ccb, CAM_ESF_ALL,
2902 					CAM_EPF_ALL, stderr);
2903 		goto defect_bailout;
2904 	}
2905 
2906 	/*
2907 	 * XXX KDM  I should probably clean up the printout format for the
2908 	 * disk defects.
2909 	 */
2910 	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
2911 		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
2912 		{
2913 			struct scsi_defect_desc_phys_sector *dlist;
2914 
2915 			dlist = (struct scsi_defect_desc_phys_sector *)
2916 				(defect_list +
2917 				sizeof(struct scsi_read_defect_data_hdr_10));
2918 
2919 			num_returned = returned_length /
2920 				sizeof(struct scsi_defect_desc_phys_sector);
2921 
2922 			fprintf(stderr, "Got %d defect", num_returned);
2923 
2924 			if ((lists_specified == 0) || (num_returned == 0)) {
2925 				fprintf(stderr, "s.\n");
2926 				break;
2927 			} else if (num_returned == 1)
2928 				fprintf(stderr, ":\n");
2929 			else
2930 				fprintf(stderr, "s:\n");
2931 
2932 			for (i = 0; i < num_returned; i++) {
2933 				fprintf(stdout, "%d:%d:%d\n",
2934 					scsi_3btoul(dlist[i].cylinder),
2935 					dlist[i].head,
2936 					scsi_4btoul(dlist[i].sector));
2937 			}
2938 			break;
2939 		}
2940 		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
2941 		{
2942 			struct scsi_defect_desc_bytes_from_index *dlist;
2943 
2944 			dlist = (struct scsi_defect_desc_bytes_from_index *)
2945 				(defect_list +
2946 				sizeof(struct scsi_read_defect_data_hdr_10));
2947 
2948 			num_returned = returned_length /
2949 			      sizeof(struct scsi_defect_desc_bytes_from_index);
2950 
2951 			fprintf(stderr, "Got %d defect", num_returned);
2952 
2953 			if ((lists_specified == 0) || (num_returned == 0)) {
2954 				fprintf(stderr, "s.\n");
2955 				break;
2956 			} else if (num_returned == 1)
2957 				fprintf(stderr, ":\n");
2958 			else
2959 				fprintf(stderr, "s:\n");
2960 
2961 			for (i = 0; i < num_returned; i++) {
2962 				fprintf(stdout, "%d:%d:%d\n",
2963 					scsi_3btoul(dlist[i].cylinder),
2964 					dlist[i].head,
2965 					scsi_4btoul(dlist[i].bytes_from_index));
2966 			}
2967 			break;
2968 		}
2969 		case SRDDH10_BLOCK_FORMAT:
2970 		{
2971 			struct scsi_defect_desc_block *dlist;
2972 
2973 			dlist = (struct scsi_defect_desc_block *)(defect_list +
2974 				sizeof(struct scsi_read_defect_data_hdr_10));
2975 
2976 			num_returned = returned_length /
2977 			      sizeof(struct scsi_defect_desc_block);
2978 
2979 			fprintf(stderr, "Got %d defect", num_returned);
2980 
2981 			if ((lists_specified == 0) || (num_returned == 0)) {
2982 				fprintf(stderr, "s.\n");
2983 				break;
2984 			} else if (num_returned == 1)
2985 				fprintf(stderr, ":\n");
2986 			else
2987 				fprintf(stderr, "s:\n");
2988 
2989 			for (i = 0; i < num_returned; i++)
2990 				fprintf(stdout, "%u\n",
2991 					scsi_4btoul(dlist[i].address));
2992 			break;
2993 		}
2994 		default:
2995 			fprintf(stderr, "Unknown defect format %d\n",
2996 				returned_format & SRDDH10_DLIST_FORMAT_MASK);
2997 			error = 1;
2998 			break;
2999 	}
3000 defect_bailout:
3001 
3002 	if (defect_list != NULL)
3003 		free(defect_list);
3004 
3005 	if (ccb != NULL)
3006 		cam_freeccb(ccb);
3007 
3008 	return(error);
3009 }
3010 #endif /* MINIMALISTIC */
3011 
3012 #if 0
3013 void
3014 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3015 {
3016 	union ccb *ccb;
3017 
3018 	ccb = cam_getccb(device);
3019 
3020 	cam_freeccb(ccb);
3021 }
3022 #endif
3023 
3024 #ifndef MINIMALISTIC
3025 void
3026 mode_sense(struct cam_device *device, int mode_page, int page_control,
3027 	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3028 {
3029 	union ccb *ccb;
3030 	int retval;
3031 
3032 	ccb = cam_getccb(device);
3033 
3034 	if (ccb == NULL)
3035 		errx(1, "mode_sense: couldn't allocate CCB");
3036 
3037 	bzero(&(&ccb->ccb_h)[1],
3038 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3039 
3040 	scsi_mode_sense(&ccb->csio,
3041 			/* retries */ retry_count,
3042 			/* cbfcnp */ NULL,
3043 			/* tag_action */ MSG_SIMPLE_Q_TAG,
3044 			/* dbd */ dbd,
3045 			/* page_code */ page_control << 6,
3046 			/* page */ mode_page,
3047 			/* param_buf */ data,
3048 			/* param_len */ datalen,
3049 			/* sense_len */ SSD_FULL_SIZE,
3050 			/* timeout */ timeout ? timeout : 5000);
3051 
3052 	if (arglist & CAM_ARG_ERR_RECOVER)
3053 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3054 
3055 	/* Disable freezing the device queue */
3056 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3057 
3058 	if (((retval = cam_send_ccb(device, ccb)) < 0)
3059 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3060 		if (arglist & CAM_ARG_VERBOSE) {
3061 			cam_error_print(device, ccb, CAM_ESF_ALL,
3062 					CAM_EPF_ALL, stderr);
3063 		}
3064 		cam_freeccb(ccb);
3065 		cam_close_device(device);
3066 		if (retval < 0)
3067 			err(1, "error sending mode sense command");
3068 		else
3069 			errx(1, "error sending mode sense command");
3070 	}
3071 
3072 	cam_freeccb(ccb);
3073 }
3074 
3075 void
3076 mode_select(struct cam_device *device, int save_pages, int retry_count,
3077 	   int timeout, u_int8_t *data, int datalen)
3078 {
3079 	union ccb *ccb;
3080 	int retval;
3081 
3082 	ccb = cam_getccb(device);
3083 
3084 	if (ccb == NULL)
3085 		errx(1, "mode_select: couldn't allocate CCB");
3086 
3087 	bzero(&(&ccb->ccb_h)[1],
3088 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3089 
3090 	scsi_mode_select(&ccb->csio,
3091 			 /* retries */ retry_count,
3092 			 /* cbfcnp */ NULL,
3093 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
3094 			 /* scsi_page_fmt */ 1,
3095 			 /* save_pages */ save_pages,
3096 			 /* param_buf */ data,
3097 			 /* param_len */ datalen,
3098 			 /* sense_len */ SSD_FULL_SIZE,
3099 			 /* timeout */ timeout ? timeout : 5000);
3100 
3101 	if (arglist & CAM_ARG_ERR_RECOVER)
3102 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3103 
3104 	/* Disable freezing the device queue */
3105 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3106 
3107 	if (((retval = cam_send_ccb(device, ccb)) < 0)
3108 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3109 		if (arglist & CAM_ARG_VERBOSE) {
3110 			cam_error_print(device, ccb, CAM_ESF_ALL,
3111 					CAM_EPF_ALL, stderr);
3112 		}
3113 		cam_freeccb(ccb);
3114 		cam_close_device(device);
3115 
3116 		if (retval < 0)
3117 			err(1, "error sending mode select command");
3118 		else
3119 			errx(1, "error sending mode select command");
3120 
3121 	}
3122 
3123 	cam_freeccb(ccb);
3124 }
3125 
3126 void
3127 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
3128 	 int retry_count, int timeout)
3129 {
3130 	int c, mode_page = -1, page_control = 0;
3131 	int binary = 0, list = 0;
3132 
3133 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3134 		switch(c) {
3135 		case 'b':
3136 			binary = 1;
3137 			break;
3138 		case 'd':
3139 			arglist |= CAM_ARG_DBD;
3140 			break;
3141 		case 'e':
3142 			arglist |= CAM_ARG_MODE_EDIT;
3143 			break;
3144 		case 'l':
3145 			list = 1;
3146 			break;
3147 		case 'm':
3148 			mode_page = strtol(optarg, NULL, 0);
3149 			if (mode_page < 0)
3150 				errx(1, "invalid mode page %d", mode_page);
3151 			break;
3152 		case 'P':
3153 			page_control = strtol(optarg, NULL, 0);
3154 			if ((page_control < 0) || (page_control > 3))
3155 				errx(1, "invalid page control field %d",
3156 				     page_control);
3157 			arglist |= CAM_ARG_PAGE_CNTL;
3158 			break;
3159 		default:
3160 			break;
3161 		}
3162 	}
3163 
3164 	if (mode_page == -1 && list == 0)
3165 		errx(1, "you must specify a mode page!");
3166 
3167 	if (list) {
3168 		mode_list(device, page_control, arglist & CAM_ARG_DBD,
3169 		    retry_count, timeout);
3170 	} else {
3171 		mode_edit(device, mode_page, page_control,
3172 		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
3173 		    retry_count, timeout);
3174 	}
3175 }
3176 
3177 static int
3178 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
3179 	int retry_count, int timeout)
3180 {
3181 	union ccb *ccb;
3182 	u_int32_t flags = CAM_DIR_NONE;
3183 	u_int8_t *data_ptr = NULL;
3184 	u_int8_t cdb[20];
3185 	u_int8_t atacmd[12];
3186 	struct get_hook hook;
3187 	int c, data_bytes = 0;
3188 	int cdb_len = 0;
3189 	int atacmd_len = 0;
3190 	int dmacmd = 0;
3191 	int fpdmacmd = 0;
3192 	int need_res = 0;
3193 	char *datastr = NULL, *tstr, *resstr = NULL;
3194 	int error = 0;
3195 	int fd_data = 0, fd_res = 0;
3196 	int retval;
3197 
3198 	ccb = cam_getccb(device);
3199 
3200 	if (ccb == NULL) {
3201 		warnx("scsicmd: error allocating ccb");
3202 		return(1);
3203 	}
3204 
3205 	bzero(&(&ccb->ccb_h)[1],
3206 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
3207 
3208 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3209 		switch(c) {
3210 		case 'a':
3211 			tstr = optarg;
3212 			while (isspace(*tstr) && (*tstr != '\0'))
3213 				tstr++;
3214 			hook.argc = argc - optind;
3215 			hook.argv = argv + optind;
3216 			hook.got = 0;
3217 			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
3218 						    iget, &hook);
3219 			/*
3220 			 * Increment optind by the number of arguments the
3221 			 * encoding routine processed.  After each call to
3222 			 * getopt(3), optind points to the argument that
3223 			 * getopt should process _next_.  In this case,
3224 			 * that means it points to the first command string
3225 			 * argument, if there is one.  Once we increment
3226 			 * this, it should point to either the next command
3227 			 * line argument, or it should be past the end of
3228 			 * the list.
3229 			 */
3230 			optind += hook.got;
3231 			break;
3232 		case 'c':
3233 			tstr = optarg;
3234 			while (isspace(*tstr) && (*tstr != '\0'))
3235 				tstr++;
3236 			hook.argc = argc - optind;
3237 			hook.argv = argv + optind;
3238 			hook.got = 0;
3239 			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
3240 						    iget, &hook);
3241 			/*
3242 			 * Increment optind by the number of arguments the
3243 			 * encoding routine processed.  After each call to
3244 			 * getopt(3), optind points to the argument that
3245 			 * getopt should process _next_.  In this case,
3246 			 * that means it points to the first command string
3247 			 * argument, if there is one.  Once we increment
3248 			 * this, it should point to either the next command
3249 			 * line argument, or it should be past the end of
3250 			 * the list.
3251 			 */
3252 			optind += hook.got;
3253 			break;
3254 		case 'd':
3255 			dmacmd = 1;
3256 			break;
3257 		case 'f':
3258 			fpdmacmd = 1;
3259 			break;
3260 		case 'i':
3261 			if (arglist & CAM_ARG_CMD_OUT) {
3262 				warnx("command must either be "
3263 				      "read or write, not both");
3264 				error = 1;
3265 				goto scsicmd_bailout;
3266 			}
3267 			arglist |= CAM_ARG_CMD_IN;
3268 			flags = CAM_DIR_IN;
3269 			data_bytes = strtol(optarg, NULL, 0);
3270 			if (data_bytes <= 0) {
3271 				warnx("invalid number of input bytes %d",
3272 				      data_bytes);
3273 				error = 1;
3274 				goto scsicmd_bailout;
3275 			}
3276 			hook.argc = argc - optind;
3277 			hook.argv = argv + optind;
3278 			hook.got = 0;
3279 			optind++;
3280 			datastr = cget(&hook, NULL);
3281 			/*
3282 			 * If the user supplied "-" instead of a format, he
3283 			 * wants the data to be written to stdout.
3284 			 */
3285 			if ((datastr != NULL)
3286 			 && (datastr[0] == '-'))
3287 				fd_data = 1;
3288 
3289 			data_ptr = (u_int8_t *)malloc(data_bytes);
3290 			if (data_ptr == NULL) {
3291 				warnx("can't malloc memory for data_ptr");
3292 				error = 1;
3293 				goto scsicmd_bailout;
3294 			}
3295 			break;
3296 		case 'o':
3297 			if (arglist & CAM_ARG_CMD_IN) {
3298 				warnx("command must either be "
3299 				      "read or write, not both");
3300 				error = 1;
3301 				goto scsicmd_bailout;
3302 			}
3303 			arglist |= CAM_ARG_CMD_OUT;
3304 			flags = CAM_DIR_OUT;
3305 			data_bytes = strtol(optarg, NULL, 0);
3306 			if (data_bytes <= 0) {
3307 				warnx("invalid number of output bytes %d",
3308 				      data_bytes);
3309 				error = 1;
3310 				goto scsicmd_bailout;
3311 			}
3312 			hook.argc = argc - optind;
3313 			hook.argv = argv + optind;
3314 			hook.got = 0;
3315 			datastr = cget(&hook, NULL);
3316 			data_ptr = (u_int8_t *)malloc(data_bytes);
3317 			if (data_ptr == NULL) {
3318 				warnx("can't malloc memory for data_ptr");
3319 				error = 1;
3320 				goto scsicmd_bailout;
3321 			}
3322 			bzero(data_ptr, data_bytes);
3323 			/*
3324 			 * If the user supplied "-" instead of a format, he
3325 			 * wants the data to be read from stdin.
3326 			 */
3327 			if ((datastr != NULL)
3328 			 && (datastr[0] == '-'))
3329 				fd_data = 1;
3330 			else
3331 				buff_encode_visit(data_ptr, data_bytes, datastr,
3332 						  iget, &hook);
3333 			optind += hook.got;
3334 			break;
3335 		case 'r':
3336 			need_res = 1;
3337 			hook.argc = argc - optind;
3338 			hook.argv = argv + optind;
3339 			hook.got = 0;
3340 			resstr = cget(&hook, NULL);
3341 			if ((resstr != NULL) && (resstr[0] == '-'))
3342 				fd_res = 1;
3343 			optind += hook.got;
3344 			break;
3345 		default:
3346 			break;
3347 		}
3348 	}
3349 
3350 	/*
3351 	 * If fd_data is set, and we're writing to the device, we need to
3352 	 * read the data the user wants written from stdin.
3353 	 */
3354 	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
3355 		ssize_t amt_read;
3356 		int amt_to_read = data_bytes;
3357 		u_int8_t *buf_ptr = data_ptr;
3358 
3359 		for (amt_read = 0; amt_to_read > 0;
3360 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
3361 			if (amt_read == -1) {
3362 				warn("error reading data from stdin");
3363 				error = 1;
3364 				goto scsicmd_bailout;
3365 			}
3366 			amt_to_read -= amt_read;
3367 			buf_ptr += amt_read;
3368 		}
3369 	}
3370 
3371 	if (arglist & CAM_ARG_ERR_RECOVER)
3372 		flags |= CAM_PASS_ERR_RECOVER;
3373 
3374 	/* Disable freezing the device queue */
3375 	flags |= CAM_DEV_QFRZDIS;
3376 
3377 	if (cdb_len) {
3378 		/*
3379 		 * This is taken from the SCSI-3 draft spec.
3380 		 * (T10/1157D revision 0.3)
3381 		 * The top 3 bits of an opcode are the group code.
3382 		 * The next 5 bits are the command code.
3383 		 * Group 0:  six byte commands
3384 		 * Group 1:  ten byte commands
3385 		 * Group 2:  ten byte commands
3386 		 * Group 3:  reserved
3387 		 * Group 4:  sixteen byte commands
3388 		 * Group 5:  twelve byte commands
3389 		 * Group 6:  vendor specific
3390 		 * Group 7:  vendor specific
3391 		 */
3392 		switch((cdb[0] >> 5) & 0x7) {
3393 			case 0:
3394 				cdb_len = 6;
3395 				break;
3396 			case 1:
3397 			case 2:
3398 				cdb_len = 10;
3399 				break;
3400 			case 3:
3401 			case 6:
3402 			case 7:
3403 			        /* computed by buff_encode_visit */
3404 				break;
3405 			case 4:
3406 				cdb_len = 16;
3407 				break;
3408 			case 5:
3409 				cdb_len = 12;
3410 				break;
3411 		}
3412 
3413 		/*
3414 		 * We should probably use csio_build_visit or something like that
3415 		 * here, but it's easier to encode arguments as you go.  The
3416 		 * alternative would be skipping the CDB argument and then encoding
3417 		 * it here, since we've got the data buffer argument by now.
3418 		 */
3419 		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
3420 
3421 		cam_fill_csio(&ccb->csio,
3422 		      /*retries*/ retry_count,
3423 		      /*cbfcnp*/ NULL,
3424 		      /*flags*/ flags,
3425 		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
3426 		      /*data_ptr*/ data_ptr,
3427 		      /*dxfer_len*/ data_bytes,
3428 		      /*sense_len*/ SSD_FULL_SIZE,
3429 		      /*cdb_len*/ cdb_len,
3430 		      /*timeout*/ timeout ? timeout : 5000);
3431 	} else {
3432 		atacmd_len = 12;
3433 		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
3434 		if (need_res)
3435 			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
3436 		if (dmacmd)
3437 			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
3438 		if (fpdmacmd)
3439 			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
3440 
3441 		cam_fill_ataio(&ccb->ataio,
3442 		      /*retries*/ retry_count,
3443 		      /*cbfcnp*/ NULL,
3444 		      /*flags*/ flags,
3445 		      /*tag_action*/ 0,
3446 		      /*data_ptr*/ data_ptr,
3447 		      /*dxfer_len*/ data_bytes,
3448 		      /*timeout*/ timeout ? timeout : 5000);
3449 	}
3450 
3451 	if (((retval = cam_send_ccb(device, ccb)) < 0)
3452 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3453 		const char warnstr[] = "error sending command";
3454 
3455 		if (retval < 0)
3456 			warn(warnstr);
3457 		else
3458 			warnx(warnstr);
3459 
3460 		if (arglist & CAM_ARG_VERBOSE) {
3461 			cam_error_print(device, ccb, CAM_ESF_ALL,
3462 					CAM_EPF_ALL, stderr);
3463 		}
3464 
3465 		error = 1;
3466 		goto scsicmd_bailout;
3467 	}
3468 
3469 	if (atacmd_len && need_res) {
3470 		if (fd_res == 0) {
3471 			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
3472 					  arg_put, NULL);
3473 			fprintf(stdout, "\n");
3474 		} else {
3475 			fprintf(stdout,
3476 			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
3477 			    ccb->ataio.res.status,
3478 			    ccb->ataio.res.error,
3479 			    ccb->ataio.res.lba_low,
3480 			    ccb->ataio.res.lba_mid,
3481 			    ccb->ataio.res.lba_high,
3482 			    ccb->ataio.res.device,
3483 			    ccb->ataio.res.lba_low_exp,
3484 			    ccb->ataio.res.lba_mid_exp,
3485 			    ccb->ataio.res.lba_high_exp,
3486 			    ccb->ataio.res.sector_count,
3487 			    ccb->ataio.res.sector_count_exp);
3488 			fflush(stdout);
3489 		}
3490 	}
3491 
3492 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3493 	 && (arglist & CAM_ARG_CMD_IN)
3494 	 && (data_bytes > 0)) {
3495 		if (fd_data == 0) {
3496 			buff_decode_visit(data_ptr, data_bytes, datastr,
3497 					  arg_put, NULL);
3498 			fprintf(stdout, "\n");
3499 		} else {
3500 			ssize_t amt_written;
3501 			int amt_to_write = data_bytes;
3502 			u_int8_t *buf_ptr = data_ptr;
3503 
3504 			for (amt_written = 0; (amt_to_write > 0) &&
3505 			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
3506 				amt_to_write -= amt_written;
3507 				buf_ptr += amt_written;
3508 			}
3509 			if (amt_written == -1) {
3510 				warn("error writing data to stdout");
3511 				error = 1;
3512 				goto scsicmd_bailout;
3513 			} else if ((amt_written == 0)
3514 				&& (amt_to_write > 0)) {
3515 				warnx("only wrote %u bytes out of %u",
3516 				      data_bytes - amt_to_write, data_bytes);
3517 			}
3518 		}
3519 	}
3520 
3521 scsicmd_bailout:
3522 
3523 	if ((data_bytes > 0) && (data_ptr != NULL))
3524 		free(data_ptr);
3525 
3526 	cam_freeccb(ccb);
3527 
3528 	return(error);
3529 }
3530 
3531 static int
3532 camdebug(int argc, char **argv, char *combinedopt)
3533 {
3534 	int c, fd;
3535 	int bus = -1, target = -1, lun = -1;
3536 	char *tstr, *tmpstr = NULL;
3537 	union ccb ccb;
3538 	int error = 0;
3539 
3540 	bzero(&ccb, sizeof(union ccb));
3541 
3542 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3543 		switch(c) {
3544 		case 'I':
3545 			arglist |= CAM_ARG_DEBUG_INFO;
3546 			ccb.cdbg.flags |= CAM_DEBUG_INFO;
3547 			break;
3548 		case 'P':
3549 			arglist |= CAM_ARG_DEBUG_PERIPH;
3550 			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
3551 			break;
3552 		case 'S':
3553 			arglist |= CAM_ARG_DEBUG_SUBTRACE;
3554 			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
3555 			break;
3556 		case 'T':
3557 			arglist |= CAM_ARG_DEBUG_TRACE;
3558 			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
3559 			break;
3560 		case 'X':
3561 			arglist |= CAM_ARG_DEBUG_XPT;
3562 			ccb.cdbg.flags |= CAM_DEBUG_XPT;
3563 			break;
3564 		case 'c':
3565 			arglist |= CAM_ARG_DEBUG_CDB;
3566 			ccb.cdbg.flags |= CAM_DEBUG_CDB;
3567 			break;
3568 		case 'p':
3569 			arglist |= CAM_ARG_DEBUG_PROBE;
3570 			ccb.cdbg.flags |= CAM_DEBUG_PROBE;
3571 			break;
3572 		default:
3573 			break;
3574 		}
3575 	}
3576 
3577 	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3578 		warnx("error opening transport layer device %s", XPT_DEVICE);
3579 		warn("%s", XPT_DEVICE);
3580 		return(1);
3581 	}
3582 	argc -= optind;
3583 	argv += optind;
3584 
3585 	if (argc <= 0) {
3586 		warnx("you must specify \"off\", \"all\" or a bus,");
3587 		warnx("bus:target, or bus:target:lun");
3588 		close(fd);
3589 		return(1);
3590 	}
3591 
3592 	tstr = *argv;
3593 
3594 	while (isspace(*tstr) && (*tstr != '\0'))
3595 		tstr++;
3596 
3597 	if (strncmp(tstr, "off", 3) == 0) {
3598 		ccb.cdbg.flags = CAM_DEBUG_NONE;
3599 		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
3600 			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
3601 			     CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
3602 	} else if (strncmp(tstr, "all", 3) != 0) {
3603 		tmpstr = (char *)strtok(tstr, ":");
3604 		if ((tmpstr != NULL) && (*tmpstr != '\0')){
3605 			bus = strtol(tmpstr, NULL, 0);
3606 			arglist |= CAM_ARG_BUS;
3607 			tmpstr = (char *)strtok(NULL, ":");
3608 			if ((tmpstr != NULL) && (*tmpstr != '\0')){
3609 				target = strtol(tmpstr, NULL, 0);
3610 				arglist |= CAM_ARG_TARGET;
3611 				tmpstr = (char *)strtok(NULL, ":");
3612 				if ((tmpstr != NULL) && (*tmpstr != '\0')){
3613 					lun = strtol(tmpstr, NULL, 0);
3614 					arglist |= CAM_ARG_LUN;
3615 				}
3616 			}
3617 		} else {
3618 			error = 1;
3619 			warnx("you must specify \"all\", \"off\", or a bus,");
3620 			warnx("bus:target, or bus:target:lun to debug");
3621 		}
3622 	}
3623 
3624 	if (error == 0) {
3625 
3626 		ccb.ccb_h.func_code = XPT_DEBUG;
3627 		ccb.ccb_h.path_id = bus;
3628 		ccb.ccb_h.target_id = target;
3629 		ccb.ccb_h.target_lun = lun;
3630 
3631 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3632 			warn("CAMIOCOMMAND ioctl failed");
3633 			error = 1;
3634 		}
3635 
3636 		if (error == 0) {
3637 			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
3638 			     CAM_FUNC_NOTAVAIL) {
3639 				warnx("CAM debugging not available");
3640 				warnx("you need to put options CAMDEBUG in"
3641 				      " your kernel config file!");
3642 				error = 1;
3643 			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
3644 				    CAM_REQ_CMP) {
3645 				warnx("XPT_DEBUG CCB failed with status %#x",
3646 				      ccb.ccb_h.status);
3647 				error = 1;
3648 			} else {
3649 				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
3650 					fprintf(stderr,
3651 						"Debugging turned off\n");
3652 				} else {
3653 					fprintf(stderr,
3654 						"Debugging enabled for "
3655 						"%d:%d:%d\n",
3656 						bus, target, lun);
3657 				}
3658 			}
3659 		}
3660 		close(fd);
3661 	}
3662 
3663 	return(error);
3664 }
3665 
3666 static int
3667 tagcontrol(struct cam_device *device, int argc, char **argv,
3668 	   char *combinedopt)
3669 {
3670 	int c;
3671 	union ccb *ccb;
3672 	int numtags = -1;
3673 	int retval = 0;
3674 	int quiet = 0;
3675 	char pathstr[1024];
3676 
3677 	ccb = cam_getccb(device);
3678 
3679 	if (ccb == NULL) {
3680 		warnx("tagcontrol: error allocating ccb");
3681 		return(1);
3682 	}
3683 
3684 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3685 		switch(c) {
3686 		case 'N':
3687 			numtags = strtol(optarg, NULL, 0);
3688 			if (numtags < 0) {
3689 				warnx("tag count %d is < 0", numtags);
3690 				retval = 1;
3691 				goto tagcontrol_bailout;
3692 			}
3693 			break;
3694 		case 'q':
3695 			quiet++;
3696 			break;
3697 		default:
3698 			break;
3699 		}
3700 	}
3701 
3702 	cam_path_string(device, pathstr, sizeof(pathstr));
3703 
3704 	if (numtags >= 0) {
3705 		bzero(&(&ccb->ccb_h)[1],
3706 		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
3707 		ccb->ccb_h.func_code = XPT_REL_SIMQ;
3708 		ccb->ccb_h.flags = CAM_DEV_QFREEZE;
3709 		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
3710 		ccb->crs.openings = numtags;
3711 
3712 
3713 		if (cam_send_ccb(device, ccb) < 0) {
3714 			perror("error sending XPT_REL_SIMQ CCB");
3715 			retval = 1;
3716 			goto tagcontrol_bailout;
3717 		}
3718 
3719 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3720 			warnx("XPT_REL_SIMQ CCB failed");
3721 			cam_error_print(device, ccb, CAM_ESF_ALL,
3722 					CAM_EPF_ALL, stderr);
3723 			retval = 1;
3724 			goto tagcontrol_bailout;
3725 		}
3726 
3727 
3728 		if (quiet == 0)
3729 			fprintf(stdout, "%stagged openings now %d\n",
3730 				pathstr, ccb->crs.openings);
3731 	}
3732 
3733 	bzero(&(&ccb->ccb_h)[1],
3734 	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
3735 
3736 	ccb->ccb_h.func_code = XPT_GDEV_STATS;
3737 
3738 	if (cam_send_ccb(device, ccb) < 0) {
3739 		perror("error sending XPT_GDEV_STATS CCB");
3740 		retval = 1;
3741 		goto tagcontrol_bailout;
3742 	}
3743 
3744 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3745 		warnx("XPT_GDEV_STATS CCB failed");
3746 		cam_error_print(device, ccb, CAM_ESF_ALL,
3747 				CAM_EPF_ALL, stderr);
3748 		retval = 1;
3749 		goto tagcontrol_bailout;
3750 	}
3751 
3752 	if (arglist & CAM_ARG_VERBOSE) {
3753 		fprintf(stdout, "%s", pathstr);
3754 		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
3755 		fprintf(stdout, "%s", pathstr);
3756 		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
3757 		fprintf(stdout, "%s", pathstr);
3758 		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
3759 		fprintf(stdout, "%s", pathstr);
3760 		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
3761 		fprintf(stdout, "%s", pathstr);
3762 		fprintf(stdout, "held          %d\n", ccb->cgds.held);
3763 		fprintf(stdout, "%s", pathstr);
3764 		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
3765 		fprintf(stdout, "%s", pathstr);
3766 		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
3767 	} else {
3768 		if (quiet == 0) {
3769 			fprintf(stdout, "%s", pathstr);
3770 			fprintf(stdout, "device openings: ");
3771 		}
3772 		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
3773 			ccb->cgds.dev_active);
3774 	}
3775 
3776 tagcontrol_bailout:
3777 
3778 	cam_freeccb(ccb);
3779 	return(retval);
3780 }
3781 
3782 static void
3783 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
3784 {
3785 	char pathstr[1024];
3786 
3787 	cam_path_string(device, pathstr, sizeof(pathstr));
3788 
3789 	if (cts->transport == XPORT_SPI) {
3790 		struct ccb_trans_settings_spi *spi =
3791 		    &cts->xport_specific.spi;
3792 
3793 		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
3794 
3795 			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
3796 				spi->sync_period);
3797 
3798 			if (spi->sync_offset != 0) {
3799 				u_int freq;
3800 
3801 				freq = scsi_calc_syncsrate(spi->sync_period);
3802 				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
3803 					pathstr, freq / 1000, freq % 1000);
3804 			}
3805 		}
3806 
3807 		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
3808 			fprintf(stdout, "%soffset: %d\n", pathstr,
3809 			    spi->sync_offset);
3810 		}
3811 
3812 		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
3813 			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
3814 				(0x01 << spi->bus_width) * 8);
3815 		}
3816 
3817 		if (spi->valid & CTS_SPI_VALID_DISC) {
3818 			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
3819 				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
3820 				"enabled" : "disabled");
3821 		}
3822 	}
3823 	if (cts->transport == XPORT_FC) {
3824 		struct ccb_trans_settings_fc *fc =
3825 		    &cts->xport_specific.fc;
3826 
3827 		if (fc->valid & CTS_FC_VALID_WWNN)
3828 			fprintf(stdout, "%sWWNN: 0x%llx", pathstr,
3829 			    (long long) fc->wwnn);
3830 		if (fc->valid & CTS_FC_VALID_WWPN)
3831 			fprintf(stdout, "%sWWPN: 0x%llx", pathstr,
3832 			    (long long) fc->wwpn);
3833 		if (fc->valid & CTS_FC_VALID_PORT)
3834 			fprintf(stdout, "%sPortID: 0x%x", pathstr, fc->port);
3835 		if (fc->valid & CTS_FC_VALID_SPEED)
3836 			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
3837 			    pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
3838 	}
3839 	if (cts->transport == XPORT_SAS) {
3840 		struct ccb_trans_settings_sas *sas =
3841 		    &cts->xport_specific.sas;
3842 
3843 		if (sas->valid & CTS_SAS_VALID_SPEED)
3844 			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
3845 			    pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
3846 	}
3847 	if (cts->transport == XPORT_ATA) {
3848 		struct ccb_trans_settings_pata *pata =
3849 		    &cts->xport_specific.ata;
3850 
3851 		if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
3852 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
3853 				ata_mode2string(pata->mode));
3854 		}
3855 		if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
3856 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
3857 				pata->atapi);
3858 		}
3859 		if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
3860 			fprintf(stdout, "%sPIO transaction length: %d\n",
3861 				pathstr, pata->bytecount);
3862 		}
3863 	}
3864 	if (cts->transport == XPORT_SATA) {
3865 		struct ccb_trans_settings_sata *sata =
3866 		    &cts->xport_specific.sata;
3867 
3868 		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
3869 			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
3870 				sata->revision);
3871 		}
3872 		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
3873 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
3874 				ata_mode2string(sata->mode));
3875 		}
3876 		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
3877 			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
3878 				sata->atapi);
3879 		}
3880 		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
3881 			fprintf(stdout, "%sPIO transaction length: %d\n",
3882 				pathstr, sata->bytecount);
3883 		}
3884 		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
3885 			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
3886 				sata->pm_present);
3887 		}
3888 		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
3889 			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
3890 				sata->tags);
3891 		}
3892 		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
3893 			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
3894 				sata->caps);
3895 		}
3896 	}
3897 	if (cts->protocol == PROTO_ATA) {
3898 		struct ccb_trans_settings_ata *ata=
3899 		    &cts->proto_specific.ata;
3900 
3901 		if (ata->valid & CTS_ATA_VALID_TQ) {
3902 			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
3903 				(ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
3904 				"enabled" : "disabled");
3905 		}
3906 	}
3907 	if (cts->protocol == PROTO_SCSI) {
3908 		struct ccb_trans_settings_scsi *scsi=
3909 		    &cts->proto_specific.scsi;
3910 
3911 		if (scsi->valid & CTS_SCSI_VALID_TQ) {
3912 			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
3913 				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
3914 				"enabled" : "disabled");
3915 		}
3916 	}
3917 
3918 }
3919 
3920 /*
3921  * Get a path inquiry CCB for the specified device.
3922  */
3923 static int
3924 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
3925 {
3926 	union ccb *ccb;
3927 	int retval = 0;
3928 
3929 	ccb = cam_getccb(device);
3930 	if (ccb == NULL) {
3931 		warnx("get_cpi: couldn't allocate CCB");
3932 		return(1);
3933 	}
3934 	bzero(&(&ccb->ccb_h)[1],
3935 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3936 	ccb->ccb_h.func_code = XPT_PATH_INQ;
3937 	if (cam_send_ccb(device, ccb) < 0) {
3938 		warn("get_cpi: error sending Path Inquiry CCB");
3939 		if (arglist & CAM_ARG_VERBOSE)
3940 			cam_error_print(device, ccb, CAM_ESF_ALL,
3941 					CAM_EPF_ALL, stderr);
3942 		retval = 1;
3943 		goto get_cpi_bailout;
3944 	}
3945 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3946 		if (arglist & CAM_ARG_VERBOSE)
3947 			cam_error_print(device, ccb, CAM_ESF_ALL,
3948 					CAM_EPF_ALL, stderr);
3949 		retval = 1;
3950 		goto get_cpi_bailout;
3951 	}
3952 	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
3953 
3954 get_cpi_bailout:
3955 	cam_freeccb(ccb);
3956 	return(retval);
3957 }
3958 
3959 /*
3960  * Get a get device CCB for the specified device.
3961  */
3962 static int
3963 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
3964 {
3965 	union ccb *ccb;
3966 	int retval = 0;
3967 
3968 	ccb = cam_getccb(device);
3969 	if (ccb == NULL) {
3970 		warnx("get_cgd: couldn't allocate CCB");
3971 		return(1);
3972 	}
3973 	bzero(&(&ccb->ccb_h)[1],
3974 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3975 	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
3976 	if (cam_send_ccb(device, ccb) < 0) {
3977 		warn("get_cgd: error sending Path Inquiry CCB");
3978 		if (arglist & CAM_ARG_VERBOSE)
3979 			cam_error_print(device, ccb, CAM_ESF_ALL,
3980 					CAM_EPF_ALL, stderr);
3981 		retval = 1;
3982 		goto get_cgd_bailout;
3983 	}
3984 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3985 		if (arglist & CAM_ARG_VERBOSE)
3986 			cam_error_print(device, ccb, CAM_ESF_ALL,
3987 					CAM_EPF_ALL, stderr);
3988 		retval = 1;
3989 		goto get_cgd_bailout;
3990 	}
3991 	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3992 
3993 get_cgd_bailout:
3994 	cam_freeccb(ccb);
3995 	return(retval);
3996 }
3997 
3998 /* return the type of disk (really the command type) */
3999 static const char *
4000 get_disk_type(struct cam_device *device)
4001 {
4002 	struct ccb_getdev	cgd;
4003 
4004 	(void) memset(&cgd, 0x0, sizeof(cgd));
4005 	get_cgd(device, &cgd);
4006 	switch(cgd.protocol) {
4007 	case PROTO_SCSI:
4008 		return "scsi";
4009 	case PROTO_ATA:
4010 	case PROTO_ATAPI:
4011 	case PROTO_SATAPM:
4012 		return "ata";
4013 	default:
4014 		return "unknown";
4015 	}
4016 }
4017 
4018 static void
4019 cpi_print(struct ccb_pathinq *cpi)
4020 {
4021 	char adapter_str[1024];
4022 	int i;
4023 
4024 	snprintf(adapter_str, sizeof(adapter_str),
4025 		 "%s%d:", cpi->dev_name, cpi->unit_number);
4026 
4027 	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
4028 		cpi->version_num);
4029 
4030 	for (i = 1; i < 0xff; i = i << 1) {
4031 		const char *str;
4032 
4033 		if ((i & cpi->hba_inquiry) == 0)
4034 			continue;
4035 
4036 		fprintf(stdout, "%s supports ", adapter_str);
4037 
4038 		switch(i) {
4039 		case PI_MDP_ABLE:
4040 			str = "MDP message";
4041 			break;
4042 		case PI_WIDE_32:
4043 			str = "32 bit wide SCSI";
4044 			break;
4045 		case PI_WIDE_16:
4046 			str = "16 bit wide SCSI";
4047 			break;
4048 		case PI_SDTR_ABLE:
4049 			str = "SDTR message";
4050 			break;
4051 		case PI_LINKED_CDB:
4052 			str = "linked CDBs";
4053 			break;
4054 		case PI_TAG_ABLE:
4055 			str = "tag queue messages";
4056 			break;
4057 		case PI_SOFT_RST:
4058 			str = "soft reset alternative";
4059 			break;
4060 		case PI_SATAPM:
4061 			str = "SATA Port Multiplier";
4062 			break;
4063 		default:
4064 			str = "unknown PI bit set";
4065 			break;
4066 		}
4067 		fprintf(stdout, "%s\n", str);
4068 	}
4069 
4070 	for (i = 1; i < 0xff; i = i << 1) {
4071 		const char *str;
4072 
4073 		if ((i & cpi->hba_misc) == 0)
4074 			continue;
4075 
4076 		fprintf(stdout, "%s ", adapter_str);
4077 
4078 		switch(i) {
4079 		case PIM_SCANHILO:
4080 			str = "bus scans from high ID to low ID";
4081 			break;
4082 		case PIM_NOREMOVE:
4083 			str = "removable devices not included in scan";
4084 			break;
4085 		case PIM_NOINITIATOR:
4086 			str = "initiator role not supported";
4087 			break;
4088 		case PIM_NOBUSRESET:
4089 			str = "user has disabled initial BUS RESET or"
4090 			      " controller is in target/mixed mode";
4091 			break;
4092 		case PIM_NO_6_BYTE:
4093 			str = "do not send 6-byte commands";
4094 			break;
4095 		case PIM_SEQSCAN:
4096 			str = "scan bus sequentially";
4097 			break;
4098 		default:
4099 			str = "unknown PIM bit set";
4100 			break;
4101 		}
4102 		fprintf(stdout, "%s\n", str);
4103 	}
4104 
4105 	for (i = 1; i < 0xff; i = i << 1) {
4106 		const char *str;
4107 
4108 		if ((i & cpi->target_sprt) == 0)
4109 			continue;
4110 
4111 		fprintf(stdout, "%s supports ", adapter_str);
4112 		switch(i) {
4113 		case PIT_PROCESSOR:
4114 			str = "target mode processor mode";
4115 			break;
4116 		case PIT_PHASE:
4117 			str = "target mode phase cog. mode";
4118 			break;
4119 		case PIT_DISCONNECT:
4120 			str = "disconnects in target mode";
4121 			break;
4122 		case PIT_TERM_IO:
4123 			str = "terminate I/O message in target mode";
4124 			break;
4125 		case PIT_GRP_6:
4126 			str = "group 6 commands in target mode";
4127 			break;
4128 		case PIT_GRP_7:
4129 			str = "group 7 commands in target mode";
4130 			break;
4131 		default:
4132 			str = "unknown PIT bit set";
4133 			break;
4134 		}
4135 
4136 		fprintf(stdout, "%s\n", str);
4137 	}
4138 	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
4139 		cpi->hba_eng_cnt);
4140 	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
4141 		cpi->max_target);
4142 	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
4143 		cpi->max_lun);
4144 	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
4145 		adapter_str, cpi->hpath_id);
4146 	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
4147 		cpi->initiator_id);
4148 	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
4149 	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
4150 	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
4151 	    adapter_str, cpi->hba_vendor);
4152 	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
4153 	    adapter_str, cpi->hba_device);
4154 	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
4155 	    adapter_str, cpi->hba_subvendor);
4156 	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
4157 	    adapter_str, cpi->hba_subdevice);
4158 	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
4159 	fprintf(stdout, "%s base transfer speed: ", adapter_str);
4160 	if (cpi->base_transfer_speed > 1000)
4161 		fprintf(stdout, "%d.%03dMB/sec\n",
4162 			cpi->base_transfer_speed / 1000,
4163 			cpi->base_transfer_speed % 1000);
4164 	else
4165 		fprintf(stdout, "%dKB/sec\n",
4166 			(cpi->base_transfer_speed % 1000) * 1000);
4167 	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
4168 	    adapter_str, cpi->maxio);
4169 }
4170 
4171 static int
4172 get_print_cts(struct cam_device *device, int user_settings, int quiet,
4173 	      struct ccb_trans_settings *cts)
4174 {
4175 	int retval;
4176 	union ccb *ccb;
4177 
4178 	retval = 0;
4179 	ccb = cam_getccb(device);
4180 
4181 	if (ccb == NULL) {
4182 		warnx("get_print_cts: error allocating ccb");
4183 		return(1);
4184 	}
4185 
4186 	bzero(&(&ccb->ccb_h)[1],
4187 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
4188 
4189 	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
4190 
4191 	if (user_settings == 0)
4192 		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
4193 	else
4194 		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
4195 
4196 	if (cam_send_ccb(device, ccb) < 0) {
4197 		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
4198 		if (arglist & CAM_ARG_VERBOSE)
4199 			cam_error_print(device, ccb, CAM_ESF_ALL,
4200 					CAM_EPF_ALL, stderr);
4201 		retval = 1;
4202 		goto get_print_cts_bailout;
4203 	}
4204 
4205 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4206 		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
4207 		if (arglist & CAM_ARG_VERBOSE)
4208 			cam_error_print(device, ccb, CAM_ESF_ALL,
4209 					CAM_EPF_ALL, stderr);
4210 		retval = 1;
4211 		goto get_print_cts_bailout;
4212 	}
4213 
4214 	if (quiet == 0)
4215 		cts_print(device, &ccb->cts);
4216 
4217 	if (cts != NULL)
4218 		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
4219 
4220 get_print_cts_bailout:
4221 
4222 	cam_freeccb(ccb);
4223 
4224 	return(retval);
4225 }
4226 
4227 static int
4228 ratecontrol(struct cam_device *device, int retry_count, int timeout,
4229 	    int argc, char **argv, char *combinedopt)
4230 {
4231 	int c;
4232 	union ccb *ccb;
4233 	int user_settings = 0;
4234 	int retval = 0;
4235 	int disc_enable = -1, tag_enable = -1;
4236 	int mode = -1;
4237 	int offset = -1;
4238 	double syncrate = -1;
4239 	int bus_width = -1;
4240 	int quiet = 0;
4241 	int change_settings = 0, send_tur = 0;
4242 	struct ccb_pathinq cpi;
4243 
4244 	ccb = cam_getccb(device);
4245 	if (ccb == NULL) {
4246 		warnx("ratecontrol: error allocating ccb");
4247 		return(1);
4248 	}
4249 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4250 		switch(c){
4251 		case 'a':
4252 			send_tur = 1;
4253 			break;
4254 		case 'c':
4255 			user_settings = 0;
4256 			break;
4257 		case 'D':
4258 			if (strncasecmp(optarg, "enable", 6) == 0)
4259 				disc_enable = 1;
4260 			else if (strncasecmp(optarg, "disable", 7) == 0)
4261 				disc_enable = 0;
4262 			else {
4263 				warnx("-D argument \"%s\" is unknown", optarg);
4264 				retval = 1;
4265 				goto ratecontrol_bailout;
4266 			}
4267 			change_settings = 1;
4268 			break;
4269 		case 'M':
4270 			mode = ata_string2mode(optarg);
4271 			if (mode < 0) {
4272 				warnx("unknown mode '%s'", optarg);
4273 				retval = 1;
4274 				goto ratecontrol_bailout;
4275 			}
4276 			change_settings = 1;
4277 			break;
4278 		case 'O':
4279 			offset = strtol(optarg, NULL, 0);
4280 			if (offset < 0) {
4281 				warnx("offset value %d is < 0", offset);
4282 				retval = 1;
4283 				goto ratecontrol_bailout;
4284 			}
4285 			change_settings = 1;
4286 			break;
4287 		case 'q':
4288 			quiet++;
4289 			break;
4290 		case 'R':
4291 			syncrate = atof(optarg);
4292 			if (syncrate < 0) {
4293 				warnx("sync rate %f is < 0", syncrate);
4294 				retval = 1;
4295 				goto ratecontrol_bailout;
4296 			}
4297 			change_settings = 1;
4298 			break;
4299 		case 'T':
4300 			if (strncasecmp(optarg, "enable", 6) == 0)
4301 				tag_enable = 1;
4302 			else if (strncasecmp(optarg, "disable", 7) == 0)
4303 				tag_enable = 0;
4304 			else {
4305 				warnx("-T argument \"%s\" is unknown", optarg);
4306 				retval = 1;
4307 				goto ratecontrol_bailout;
4308 			}
4309 			change_settings = 1;
4310 			break;
4311 		case 'U':
4312 			user_settings = 1;
4313 			break;
4314 		case 'W':
4315 			bus_width = strtol(optarg, NULL, 0);
4316 			if (bus_width < 0) {
4317 				warnx("bus width %d is < 0", bus_width);
4318 				retval = 1;
4319 				goto ratecontrol_bailout;
4320 			}
4321 			change_settings = 1;
4322 			break;
4323 		default:
4324 			break;
4325 		}
4326 	}
4327 	bzero(&(&ccb->ccb_h)[1],
4328 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4329 	/*
4330 	 * Grab path inquiry information, so we can determine whether
4331 	 * or not the initiator is capable of the things that the user
4332 	 * requests.
4333 	 */
4334 	ccb->ccb_h.func_code = XPT_PATH_INQ;
4335 	if (cam_send_ccb(device, ccb) < 0) {
4336 		perror("error sending XPT_PATH_INQ CCB");
4337 		if (arglist & CAM_ARG_VERBOSE) {
4338 			cam_error_print(device, ccb, CAM_ESF_ALL,
4339 					CAM_EPF_ALL, stderr);
4340 		}
4341 		retval = 1;
4342 		goto ratecontrol_bailout;
4343 	}
4344 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4345 		warnx("XPT_PATH_INQ CCB failed");
4346 		if (arglist & CAM_ARG_VERBOSE) {
4347 			cam_error_print(device, ccb, CAM_ESF_ALL,
4348 					CAM_EPF_ALL, stderr);
4349 		}
4350 		retval = 1;
4351 		goto ratecontrol_bailout;
4352 	}
4353 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
4354 	bzero(&(&ccb->ccb_h)[1],
4355 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
4356 	if (quiet == 0) {
4357 		fprintf(stdout, "%s parameters:\n",
4358 		    user_settings ? "User" : "Current");
4359 	}
4360 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
4361 	if (retval != 0)
4362 		goto ratecontrol_bailout;
4363 
4364 	if (arglist & CAM_ARG_VERBOSE)
4365 		cpi_print(&cpi);
4366 
4367 	if (change_settings) {
4368 		int didsettings = 0;
4369 		struct ccb_trans_settings_spi *spi = NULL;
4370 		struct ccb_trans_settings_pata *pata = NULL;
4371 		struct ccb_trans_settings_sata *sata = NULL;
4372 		struct ccb_trans_settings_ata *ata = NULL;
4373 		struct ccb_trans_settings_scsi *scsi = NULL;
4374 
4375 		if (ccb->cts.transport == XPORT_SPI)
4376 			spi = &ccb->cts.xport_specific.spi;
4377 		if (ccb->cts.transport == XPORT_ATA)
4378 			pata = &ccb->cts.xport_specific.ata;
4379 		if (ccb->cts.transport == XPORT_SATA)
4380 			sata = &ccb->cts.xport_specific.sata;
4381 		if (ccb->cts.protocol == PROTO_ATA)
4382 			ata = &ccb->cts.proto_specific.ata;
4383 		if (ccb->cts.protocol == PROTO_SCSI)
4384 			scsi = &ccb->cts.proto_specific.scsi;
4385 		ccb->cts.xport_specific.valid = 0;
4386 		ccb->cts.proto_specific.valid = 0;
4387 		if (spi && disc_enable != -1) {
4388 			spi->valid |= CTS_SPI_VALID_DISC;
4389 			if (disc_enable == 0)
4390 				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
4391 			else
4392 				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
4393 			didsettings++;
4394 		}
4395 		if (tag_enable != -1) {
4396 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
4397 				warnx("HBA does not support tagged queueing, "
4398 				      "so you cannot modify tag settings");
4399 				retval = 1;
4400 				goto ratecontrol_bailout;
4401 			}
4402 			if (ata) {
4403 				ata->valid |= CTS_SCSI_VALID_TQ;
4404 				if (tag_enable == 0)
4405 					ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
4406 				else
4407 					ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
4408 				didsettings++;
4409 			} else if (scsi) {
4410 				scsi->valid |= CTS_SCSI_VALID_TQ;
4411 				if (tag_enable == 0)
4412 					scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
4413 				else
4414 					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
4415 				didsettings++;
4416 			}
4417 		}
4418 		if (spi && offset != -1) {
4419 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
4420 				warnx("HBA is not capable of changing offset");
4421 				retval = 1;
4422 				goto ratecontrol_bailout;
4423 			}
4424 			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
4425 			spi->sync_offset = offset;
4426 			didsettings++;
4427 		}
4428 		if (spi && syncrate != -1) {
4429 			int prelim_sync_period;
4430 
4431 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
4432 				warnx("HBA is not capable of changing "
4433 				      "transfer rates");
4434 				retval = 1;
4435 				goto ratecontrol_bailout;
4436 			}
4437 			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
4438 			/*
4439 			 * The sync rate the user gives us is in MHz.
4440 			 * We need to translate it into KHz for this
4441 			 * calculation.
4442 			 */
4443 			syncrate *= 1000;
4444 			/*
4445 			 * Next, we calculate a "preliminary" sync period
4446 			 * in tenths of a nanosecond.
4447 			 */
4448 			if (syncrate == 0)
4449 				prelim_sync_period = 0;
4450 			else
4451 				prelim_sync_period = 10000000 / syncrate;
4452 			spi->sync_period =
4453 				scsi_calc_syncparam(prelim_sync_period);
4454 			didsettings++;
4455 		}
4456 		if (sata && syncrate != -1) {
4457 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
4458 				warnx("HBA is not capable of changing "
4459 				      "transfer rates");
4460 				retval = 1;
4461 				goto ratecontrol_bailout;
4462 			}
4463 			if  (!user_settings) {
4464 				warnx("You can modify only user rate "
4465 				    "settings for SATA");
4466 				retval = 1;
4467 				goto ratecontrol_bailout;
4468 			}
4469 			sata->revision = ata_speed2revision(syncrate * 100);
4470 			if (sata->revision < 0) {
4471 				warnx("Invalid rate %f", syncrate);
4472 				retval = 1;
4473 				goto ratecontrol_bailout;
4474 			}
4475 			sata->valid |= CTS_SATA_VALID_REVISION;
4476 			didsettings++;
4477 		}
4478 		if ((pata || sata) && mode != -1) {
4479 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
4480 				warnx("HBA is not capable of changing "
4481 				      "transfer rates");
4482 				retval = 1;
4483 				goto ratecontrol_bailout;
4484 			}
4485 			if  (!user_settings) {
4486 				warnx("You can modify only user mode "
4487 				    "settings for ATA/SATA");
4488 				retval = 1;
4489 				goto ratecontrol_bailout;
4490 			}
4491 			if (pata) {
4492 				pata->mode = mode;
4493 				pata->valid |= CTS_ATA_VALID_MODE;
4494 			} else {
4495 				sata->mode = mode;
4496 				sata->valid |= CTS_SATA_VALID_MODE;
4497 			}
4498 			didsettings++;
4499 		}
4500 		/*
4501 		 * The bus_width argument goes like this:
4502 		 * 0 == 8 bit
4503 		 * 1 == 16 bit
4504 		 * 2 == 32 bit
4505 		 * Therefore, if you shift the number of bits given on the
4506 		 * command line right by 4, you should get the correct
4507 		 * number.
4508 		 */
4509 		if (spi && bus_width != -1) {
4510 			/*
4511 			 * We might as well validate things here with a
4512 			 * decipherable error message, rather than what
4513 			 * will probably be an indecipherable error message
4514 			 * by the time it gets back to us.
4515 			 */
4516 			if ((bus_width == 16)
4517 			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
4518 				warnx("HBA does not support 16 bit bus width");
4519 				retval = 1;
4520 				goto ratecontrol_bailout;
4521 			} else if ((bus_width == 32)
4522 				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
4523 				warnx("HBA does not support 32 bit bus width");
4524 				retval = 1;
4525 				goto ratecontrol_bailout;
4526 			} else if ((bus_width != 8)
4527 				&& (bus_width != 16)
4528 				&& (bus_width != 32)) {
4529 				warnx("Invalid bus width %d", bus_width);
4530 				retval = 1;
4531 				goto ratecontrol_bailout;
4532 			}
4533 			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
4534 			spi->bus_width = bus_width >> 4;
4535 			didsettings++;
4536 		}
4537 		if  (didsettings == 0) {
4538 			goto ratecontrol_bailout;
4539 		}
4540 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
4541 		if (cam_send_ccb(device, ccb) < 0) {
4542 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
4543 			if (arglist & CAM_ARG_VERBOSE) {
4544 				cam_error_print(device, ccb, CAM_ESF_ALL,
4545 						CAM_EPF_ALL, stderr);
4546 			}
4547 			retval = 1;
4548 			goto ratecontrol_bailout;
4549 		}
4550 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4551 			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
4552 			if (arglist & CAM_ARG_VERBOSE) {
4553 				cam_error_print(device, ccb, CAM_ESF_ALL,
4554 						CAM_EPF_ALL, stderr);
4555 			}
4556 			retval = 1;
4557 			goto ratecontrol_bailout;
4558 		}
4559 	}
4560 	if (send_tur) {
4561 		retval = testunitready(device, retry_count, timeout,
4562 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
4563 		/*
4564 		 * If the TUR didn't succeed, just bail.
4565 		 */
4566 		if (retval != 0) {
4567 			if (quiet == 0)
4568 				fprintf(stderr, "Test Unit Ready failed\n");
4569 			goto ratecontrol_bailout;
4570 		}
4571 	}
4572 	if ((change_settings || send_tur) && !quiet &&
4573 	    (ccb->cts.transport == XPORT_ATA ||
4574 	     ccb->cts.transport == XPORT_SATA || send_tur)) {
4575 		fprintf(stdout, "New parameters:\n");
4576 		retval = get_print_cts(device, user_settings, 0, NULL);
4577 	}
4578 
4579 ratecontrol_bailout:
4580 	cam_freeccb(ccb);
4581 	return(retval);
4582 }
4583 
4584 static int
4585 scsiformat(struct cam_device *device, int argc, char **argv,
4586 	   char *combinedopt, int retry_count, int timeout)
4587 {
4588 	union ccb *ccb;
4589 	int c;
4590 	int ycount = 0, quiet = 0;
4591 	int error = 0, retval = 0;
4592 	int use_timeout = 10800 * 1000;
4593 	int immediate = 1;
4594 	struct format_defect_list_header fh;
4595 	u_int8_t *data_ptr = NULL;
4596 	u_int32_t dxfer_len = 0;
4597 	u_int8_t byte2 = 0;
4598 	int num_warnings = 0;
4599 	int reportonly = 0;
4600 
4601 	ccb = cam_getccb(device);
4602 
4603 	if (ccb == NULL) {
4604 		warnx("scsiformat: error allocating ccb");
4605 		return(1);
4606 	}
4607 
4608 	bzero(&(&ccb->ccb_h)[1],
4609 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4610 
4611 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4612 		switch(c) {
4613 		case 'q':
4614 			quiet++;
4615 			break;
4616 		case 'r':
4617 			reportonly = 1;
4618 			break;
4619 		case 'w':
4620 			immediate = 0;
4621 			break;
4622 		case 'y':
4623 			ycount++;
4624 			break;
4625 		}
4626 	}
4627 
4628 	if (reportonly)
4629 		goto doreport;
4630 
4631 	if (quiet == 0) {
4632 		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
4633 			"following device:\n");
4634 
4635 		error = scsidoinquiry(device, argc, argv, combinedopt,
4636 				      retry_count, timeout);
4637 
4638 		if (error != 0) {
4639 			warnx("scsiformat: error sending inquiry");
4640 			goto scsiformat_bailout;
4641 		}
4642 	}
4643 
4644 	if (ycount == 0) {
4645 		if (!get_confirmation()) {
4646 			error = 1;
4647 			goto scsiformat_bailout;
4648 		}
4649 	}
4650 
4651 	if (timeout != 0)
4652 		use_timeout = timeout;
4653 
4654 	if (quiet == 0) {
4655 		fprintf(stdout, "Current format timeout is %d seconds\n",
4656 			use_timeout / 1000);
4657 	}
4658 
4659 	/*
4660 	 * If the user hasn't disabled questions and didn't specify a
4661 	 * timeout on the command line, ask them if they want the current
4662 	 * timeout.
4663 	 */
4664 	if ((ycount == 0)
4665 	 && (timeout == 0)) {
4666 		char str[1024];
4667 		int new_timeout = 0;
4668 
4669 		fprintf(stdout, "Enter new timeout in seconds or press\n"
4670 			"return to keep the current timeout [%d] ",
4671 			use_timeout / 1000);
4672 
4673 		if (fgets(str, sizeof(str), stdin) != NULL) {
4674 			if (str[0] != '\0')
4675 				new_timeout = atoi(str);
4676 		}
4677 
4678 		if (new_timeout != 0) {
4679 			use_timeout = new_timeout * 1000;
4680 			fprintf(stdout, "Using new timeout value %d\n",
4681 				use_timeout / 1000);
4682 		}
4683 	}
4684 
4685 	/*
4686 	 * Keep this outside the if block below to silence any unused
4687 	 * variable warnings.
4688 	 */
4689 	bzero(&fh, sizeof(fh));
4690 
4691 	/*
4692 	 * If we're in immediate mode, we've got to include the format
4693 	 * header
4694 	 */
4695 	if (immediate != 0) {
4696 		fh.byte2 = FU_DLH_IMMED;
4697 		data_ptr = (u_int8_t *)&fh;
4698 		dxfer_len = sizeof(fh);
4699 		byte2 = FU_FMT_DATA;
4700 	} else if (quiet == 0) {
4701 		fprintf(stdout, "Formatting...");
4702 		fflush(stdout);
4703 	}
4704 
4705 	scsi_format_unit(&ccb->csio,
4706 			 /* retries */ retry_count,
4707 			 /* cbfcnp */ NULL,
4708 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
4709 			 /* byte2 */ byte2,
4710 			 /* ileave */ 0,
4711 			 /* data_ptr */ data_ptr,
4712 			 /* dxfer_len */ dxfer_len,
4713 			 /* sense_len */ SSD_FULL_SIZE,
4714 			 /* timeout */ use_timeout);
4715 
4716 	/* Disable freezing the device queue */
4717 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4718 
4719 	if (arglist & CAM_ARG_ERR_RECOVER)
4720 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4721 
4722 	if (((retval = cam_send_ccb(device, ccb)) < 0)
4723 	 || ((immediate == 0)
4724 	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
4725 		const char errstr[] = "error sending format command";
4726 
4727 		if (retval < 0)
4728 			warn(errstr);
4729 		else
4730 			warnx(errstr);
4731 
4732 		if (arglist & CAM_ARG_VERBOSE) {
4733 			cam_error_print(device, ccb, CAM_ESF_ALL,
4734 					CAM_EPF_ALL, stderr);
4735 		}
4736 		error = 1;
4737 		goto scsiformat_bailout;
4738 	}
4739 
4740 	/*
4741 	 * If we ran in non-immediate mode, we already checked for errors
4742 	 * above and printed out any necessary information.  If we're in
4743 	 * immediate mode, we need to loop through and get status
4744 	 * information periodically.
4745 	 */
4746 	if (immediate == 0) {
4747 		if (quiet == 0) {
4748 			fprintf(stdout, "Format Complete\n");
4749 		}
4750 		goto scsiformat_bailout;
4751 	}
4752 
4753 doreport:
4754 	do {
4755 		cam_status status;
4756 
4757 		bzero(&(&ccb->ccb_h)[1],
4758 		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4759 
4760 		/*
4761 		 * There's really no need to do error recovery or
4762 		 * retries here, since we're just going to sit in a
4763 		 * loop and wait for the device to finish formatting.
4764 		 */
4765 		scsi_test_unit_ready(&ccb->csio,
4766 				     /* retries */ 0,
4767 				     /* cbfcnp */ NULL,
4768 				     /* tag_action */ MSG_SIMPLE_Q_TAG,
4769 				     /* sense_len */ SSD_FULL_SIZE,
4770 				     /* timeout */ 5000);
4771 
4772 		/* Disable freezing the device queue */
4773 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4774 
4775 		retval = cam_send_ccb(device, ccb);
4776 
4777 		/*
4778 		 * If we get an error from the ioctl, bail out.  SCSI
4779 		 * errors are expected.
4780 		 */
4781 		if (retval < 0) {
4782 			warn("error sending CAMIOCOMMAND ioctl");
4783 			if (arglist & CAM_ARG_VERBOSE) {
4784 				cam_error_print(device, ccb, CAM_ESF_ALL,
4785 						CAM_EPF_ALL, stderr);
4786 			}
4787 			error = 1;
4788 			goto scsiformat_bailout;
4789 		}
4790 
4791 		status = ccb->ccb_h.status & CAM_STATUS_MASK;
4792 
4793 		if ((status != CAM_REQ_CMP)
4794 		 && (status == CAM_SCSI_STATUS_ERROR)
4795 		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
4796 			struct scsi_sense_data *sense;
4797 			int error_code, sense_key, asc, ascq;
4798 
4799 			sense = &ccb->csio.sense_data;
4800 			scsi_extract_sense_len(sense, ccb->csio.sense_len -
4801 			    ccb->csio.sense_resid, &error_code, &sense_key,
4802 			    &asc, &ascq, /*show_errors*/ 1);
4803 
4804 			/*
4805 			 * According to the SCSI-2 and SCSI-3 specs, a
4806 			 * drive that is in the middle of a format should
4807 			 * return NOT READY with an ASC of "logical unit
4808 			 * not ready, format in progress".  The sense key
4809 			 * specific bytes will then be a progress indicator.
4810 			 */
4811 			if ((sense_key == SSD_KEY_NOT_READY)
4812 			 && (asc == 0x04) && (ascq == 0x04)) {
4813 				uint8_t sks[3];
4814 
4815 				if ((scsi_get_sks(sense, ccb->csio.sense_len -
4816 				     ccb->csio.sense_resid, sks) == 0)
4817 				 && (quiet == 0)) {
4818 					int val;
4819 					u_int64_t percentage;
4820 
4821 					val = scsi_2btoul(&sks[1]);
4822 					percentage = 10000 * val;
4823 
4824 					fprintf(stdout,
4825 						"\rFormatting:  %ju.%02u %% "
4826 						"(%d/%d) done",
4827 						(uintmax_t)(percentage /
4828 						(0x10000 * 100)),
4829 						(unsigned)((percentage /
4830 						0x10000) % 100),
4831 						val, 0x10000);
4832 					fflush(stdout);
4833 				} else if ((quiet == 0)
4834 					&& (++num_warnings <= 1)) {
4835 					warnx("Unexpected SCSI Sense Key "
4836 					      "Specific value returned "
4837 					      "during format:");
4838 					scsi_sense_print(device, &ccb->csio,
4839 							 stderr);
4840 					warnx("Unable to print status "
4841 					      "information, but format will "
4842 					      "proceed.");
4843 					warnx("will exit when format is "
4844 					      "complete");
4845 				}
4846 				sleep(1);
4847 			} else {
4848 				warnx("Unexpected SCSI error during format");
4849 				cam_error_print(device, ccb, CAM_ESF_ALL,
4850 						CAM_EPF_ALL, stderr);
4851 				error = 1;
4852 				goto scsiformat_bailout;
4853 			}
4854 
4855 		} else if (status != CAM_REQ_CMP) {
4856 			warnx("Unexpected CAM status %#x", status);
4857 			if (arglist & CAM_ARG_VERBOSE)
4858 				cam_error_print(device, ccb, CAM_ESF_ALL,
4859 						CAM_EPF_ALL, stderr);
4860 			error = 1;
4861 			goto scsiformat_bailout;
4862 		}
4863 
4864 	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
4865 
4866 	if (quiet == 0)
4867 		fprintf(stdout, "\nFormat Complete\n");
4868 
4869 scsiformat_bailout:
4870 
4871 	cam_freeccb(ccb);
4872 
4873 	return(error);
4874 }
4875 
4876 static int
4877 scsireportluns(struct cam_device *device, int argc, char **argv,
4878 	       char *combinedopt, int retry_count, int timeout)
4879 {
4880 	union ccb *ccb;
4881 	int c, countonly, lunsonly;
4882 	struct scsi_report_luns_data *lundata;
4883 	int alloc_len;
4884 	uint8_t report_type;
4885 	uint32_t list_len, i, j;
4886 	int retval;
4887 
4888 	retval = 0;
4889 	lundata = NULL;
4890 	report_type = RPL_REPORT_DEFAULT;
4891 	ccb = cam_getccb(device);
4892 
4893 	if (ccb == NULL) {
4894 		warnx("%s: error allocating ccb", __func__);
4895 		return (1);
4896 	}
4897 
4898 	bzero(&(&ccb->ccb_h)[1],
4899 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4900 
4901 	countonly = 0;
4902 	lunsonly = 0;
4903 
4904 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4905 		switch (c) {
4906 		case 'c':
4907 			countonly++;
4908 			break;
4909 		case 'l':
4910 			lunsonly++;
4911 			break;
4912 		case 'r':
4913 			if (strcasecmp(optarg, "default") == 0)
4914 				report_type = RPL_REPORT_DEFAULT;
4915 			else if (strcasecmp(optarg, "wellknown") == 0)
4916 				report_type = RPL_REPORT_WELLKNOWN;
4917 			else if (strcasecmp(optarg, "all") == 0)
4918 				report_type = RPL_REPORT_ALL;
4919 			else {
4920 				warnx("%s: invalid report type \"%s\"",
4921 				      __func__, optarg);
4922 				retval = 1;
4923 				goto bailout;
4924 			}
4925 			break;
4926 		default:
4927 			break;
4928 		}
4929 	}
4930 
4931 	if ((countonly != 0)
4932 	 && (lunsonly != 0)) {
4933 		warnx("%s: you can only specify one of -c or -l", __func__);
4934 		retval = 1;
4935 		goto bailout;
4936 	}
4937 	/*
4938 	 * According to SPC-4, the allocation length must be at least 16
4939 	 * bytes -- enough for the header and one LUN.
4940 	 */
4941 	alloc_len = sizeof(*lundata) + 8;
4942 
4943 retry:
4944 
4945 	lundata = malloc(alloc_len);
4946 
4947 	if (lundata == NULL) {
4948 		warn("%s: error mallocing %d bytes", __func__, alloc_len);
4949 		retval = 1;
4950 		goto bailout;
4951 	}
4952 
4953 	scsi_report_luns(&ccb->csio,
4954 			 /*retries*/ retry_count,
4955 			 /*cbfcnp*/ NULL,
4956 			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4957 			 /*select_report*/ report_type,
4958 			 /*rpl_buf*/ lundata,
4959 			 /*alloc_len*/ alloc_len,
4960 			 /*sense_len*/ SSD_FULL_SIZE,
4961 			 /*timeout*/ timeout ? timeout : 5000);
4962 
4963 	/* Disable freezing the device queue */
4964 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4965 
4966 	if (arglist & CAM_ARG_ERR_RECOVER)
4967 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4968 
4969 	if (cam_send_ccb(device, ccb) < 0) {
4970 		warn("error sending REPORT LUNS command");
4971 
4972 		if (arglist & CAM_ARG_VERBOSE)
4973 			cam_error_print(device, ccb, CAM_ESF_ALL,
4974 					CAM_EPF_ALL, stderr);
4975 
4976 		retval = 1;
4977 		goto bailout;
4978 	}
4979 
4980 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4981 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4982 		retval = 1;
4983 		goto bailout;
4984 	}
4985 
4986 
4987 	list_len = scsi_4btoul(lundata->length);
4988 
4989 	/*
4990 	 * If we need to list the LUNs, and our allocation
4991 	 * length was too short, reallocate and retry.
4992 	 */
4993 	if ((countonly == 0)
4994 	 && (list_len > (alloc_len - sizeof(*lundata)))) {
4995 		alloc_len = list_len + sizeof(*lundata);
4996 		free(lundata);
4997 		goto retry;
4998 	}
4999 
5000 	if (lunsonly == 0)
5001 		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
5002 			((list_len / 8) > 1) ? "s" : "");
5003 
5004 	if (countonly != 0)
5005 		goto bailout;
5006 
5007 	for (i = 0; i < (list_len / 8); i++) {
5008 		int no_more;
5009 
5010 		no_more = 0;
5011 		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
5012 			if (j != 0)
5013 				fprintf(stdout, ",");
5014 			switch (lundata->luns[i].lundata[j] &
5015 				RPL_LUNDATA_ATYP_MASK) {
5016 			case RPL_LUNDATA_ATYP_PERIPH:
5017 				if ((lundata->luns[i].lundata[j] &
5018 				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
5019 					fprintf(stdout, "%d:",
5020 						lundata->luns[i].lundata[j] &
5021 						RPL_LUNDATA_PERIPH_BUS_MASK);
5022 				else if ((j == 0)
5023 				      && ((lundata->luns[i].lundata[j+2] &
5024 					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
5025 					no_more = 1;
5026 
5027 				fprintf(stdout, "%d",
5028 					lundata->luns[i].lundata[j+1]);
5029 				break;
5030 			case RPL_LUNDATA_ATYP_FLAT: {
5031 				uint8_t tmplun[2];
5032 				tmplun[0] = lundata->luns[i].lundata[j] &
5033 					RPL_LUNDATA_FLAT_LUN_MASK;
5034 				tmplun[1] = lundata->luns[i].lundata[j+1];
5035 
5036 				fprintf(stdout, "%d", scsi_2btoul(tmplun));
5037 				no_more = 1;
5038 				break;
5039 			}
5040 			case RPL_LUNDATA_ATYP_LUN:
5041 				fprintf(stdout, "%d:%d:%d",
5042 					(lundata->luns[i].lundata[j+1] &
5043 					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
5044 					lundata->luns[i].lundata[j] &
5045 					RPL_LUNDATA_LUN_TARG_MASK,
5046 					lundata->luns[i].lundata[j+1] &
5047 					RPL_LUNDATA_LUN_LUN_MASK);
5048 				break;
5049 			case RPL_LUNDATA_ATYP_EXTLUN: {
5050 				int field_len_code, eam_code;
5051 
5052 				eam_code = lundata->luns[i].lundata[j] &
5053 					RPL_LUNDATA_EXT_EAM_MASK;
5054 				field_len_code = (lundata->luns[i].lundata[j] &
5055 					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
5056 
5057 				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
5058 				 && (field_len_code == 0x00)) {
5059 					fprintf(stdout, "%d",
5060 						lundata->luns[i].lundata[j+1]);
5061 				} else if ((eam_code ==
5062 					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
5063 					&& (field_len_code == 0x03)) {
5064 					uint8_t tmp_lun[8];
5065 
5066 					/*
5067 					 * This format takes up all 8 bytes.
5068 					 * If we aren't starting at offset 0,
5069 					 * that's a bug.
5070 					 */
5071 					if (j != 0) {
5072 						fprintf(stdout, "Invalid "
5073 							"offset %d for "
5074 							"Extended LUN not "
5075 							"specified format", j);
5076 						no_more = 1;
5077 						break;
5078 					}
5079 					bzero(tmp_lun, sizeof(tmp_lun));
5080 					bcopy(&lundata->luns[i].lundata[j+1],
5081 					      &tmp_lun[1], sizeof(tmp_lun) - 1);
5082 					fprintf(stdout, "%#jx",
5083 					       (intmax_t)scsi_8btou64(tmp_lun));
5084 					no_more = 1;
5085 				} else {
5086 					fprintf(stderr, "Unknown Extended LUN"
5087 						"Address method %#x, length "
5088 						"code %#x", eam_code,
5089 						field_len_code);
5090 					no_more = 1;
5091 				}
5092 				break;
5093 			}
5094 			default:
5095 				fprintf(stderr, "Unknown LUN address method "
5096 					"%#x\n", lundata->luns[i].lundata[0] &
5097 					RPL_LUNDATA_ATYP_MASK);
5098 				break;
5099 			}
5100 			/*
5101 			 * For the flat addressing method, there are no
5102 			 * other levels after it.
5103 			 */
5104 			if (no_more != 0)
5105 				break;
5106 		}
5107 		fprintf(stdout, "\n");
5108 	}
5109 
5110 bailout:
5111 
5112 	cam_freeccb(ccb);
5113 
5114 	free(lundata);
5115 
5116 	return (retval);
5117 }
5118 
5119 static int
5120 scsireadcapacity(struct cam_device *device, int argc, char **argv,
5121 		 char *combinedopt, int retry_count, int timeout)
5122 {
5123 	union ccb *ccb;
5124 	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
5125 	struct scsi_read_capacity_data rcap;
5126 	struct scsi_read_capacity_data_long rcaplong;
5127 	uint64_t maxsector;
5128 	uint32_t block_len;
5129 	int retval;
5130 	int c;
5131 
5132 	blocksizeonly = 0;
5133 	humanize = 0;
5134 	numblocks = 0;
5135 	quiet = 0;
5136 	sizeonly = 0;
5137 	baseten = 0;
5138 	retval = 0;
5139 
5140 	ccb = cam_getccb(device);
5141 
5142 	if (ccb == NULL) {
5143 		warnx("%s: error allocating ccb", __func__);
5144 		return (1);
5145 	}
5146 
5147 	bzero(&(&ccb->ccb_h)[1],
5148 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5149 
5150 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5151 		switch (c) {
5152 		case 'b':
5153 			blocksizeonly++;
5154 			break;
5155 		case 'h':
5156 			humanize++;
5157 			baseten = 0;
5158 			break;
5159 		case 'H':
5160 			humanize++;
5161 			baseten++;
5162 			break;
5163 		case 'N':
5164 			numblocks++;
5165 			break;
5166 		case 'q':
5167 			quiet++;
5168 			break;
5169 		case 's':
5170 			sizeonly++;
5171 			break;
5172 		default:
5173 			break;
5174 		}
5175 	}
5176 
5177 	if ((blocksizeonly != 0)
5178 	 && (numblocks != 0)) {
5179 		warnx("%s: you can only specify one of -b or -N", __func__);
5180 		retval = 1;
5181 		goto bailout;
5182 	}
5183 
5184 	if ((blocksizeonly != 0)
5185 	 && (sizeonly != 0)) {
5186 		warnx("%s: you can only specify one of -b or -s", __func__);
5187 		retval = 1;
5188 		goto bailout;
5189 	}
5190 
5191 	if ((humanize != 0)
5192 	 && (quiet != 0)) {
5193 		warnx("%s: you can only specify one of -h/-H or -q", __func__);
5194 		retval = 1;
5195 		goto bailout;
5196 	}
5197 
5198 	if ((humanize != 0)
5199 	 && (blocksizeonly != 0)) {
5200 		warnx("%s: you can only specify one of -h/-H or -b", __func__);
5201 		retval = 1;
5202 		goto bailout;
5203 	}
5204 
5205 	scsi_read_capacity(&ccb->csio,
5206 			   /*retries*/ retry_count,
5207 			   /*cbfcnp*/ NULL,
5208 			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
5209 			   &rcap,
5210 			   SSD_FULL_SIZE,
5211 			   /*timeout*/ timeout ? timeout : 5000);
5212 
5213 	/* Disable freezing the device queue */
5214 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5215 
5216 	if (arglist & CAM_ARG_ERR_RECOVER)
5217 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5218 
5219 	if (cam_send_ccb(device, ccb) < 0) {
5220 		warn("error sending READ CAPACITY command");
5221 
5222 		if (arglist & CAM_ARG_VERBOSE)
5223 			cam_error_print(device, ccb, CAM_ESF_ALL,
5224 					CAM_EPF_ALL, stderr);
5225 
5226 		retval = 1;
5227 		goto bailout;
5228 	}
5229 
5230 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5231 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5232 		retval = 1;
5233 		goto bailout;
5234 	}
5235 
5236 	maxsector = scsi_4btoul(rcap.addr);
5237 	block_len = scsi_4btoul(rcap.length);
5238 
5239 	/*
5240 	 * A last block of 2^32-1 means that the true capacity is over 2TB,
5241 	 * and we need to issue the long READ CAPACITY to get the real
5242 	 * capacity.  Otherwise, we're all set.
5243 	 */
5244 	if (maxsector != 0xffffffff)
5245 		goto do_print;
5246 
5247 	scsi_read_capacity_16(&ccb->csio,
5248 			      /*retries*/ retry_count,
5249 			      /*cbfcnp*/ NULL,
5250 			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
5251 			      /*lba*/ 0,
5252 			      /*reladdr*/ 0,
5253 			      /*pmi*/ 0,
5254 			      /*rcap_buf*/ (uint8_t *)&rcaplong,
5255 			      /*rcap_buf_len*/ sizeof(rcaplong),
5256 			      /*sense_len*/ SSD_FULL_SIZE,
5257 			      /*timeout*/ timeout ? timeout : 5000);
5258 
5259 	/* Disable freezing the device queue */
5260 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5261 
5262 	if (arglist & CAM_ARG_ERR_RECOVER)
5263 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5264 
5265 	if (cam_send_ccb(device, ccb) < 0) {
5266 		warn("error sending READ CAPACITY (16) command");
5267 
5268 		if (arglist & CAM_ARG_VERBOSE)
5269 			cam_error_print(device, ccb, CAM_ESF_ALL,
5270 					CAM_EPF_ALL, stderr);
5271 
5272 		retval = 1;
5273 		goto bailout;
5274 	}
5275 
5276 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5277 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5278 		retval = 1;
5279 		goto bailout;
5280 	}
5281 
5282 	maxsector = scsi_8btou64(rcaplong.addr);
5283 	block_len = scsi_4btoul(rcaplong.length);
5284 
5285 do_print:
5286 	if (blocksizeonly == 0) {
5287 		/*
5288 		 * Humanize implies !quiet, and also implies numblocks.
5289 		 */
5290 		if (humanize != 0) {
5291 			char tmpstr[6];
5292 			int64_t tmpbytes;
5293 			int ret;
5294 
5295 			tmpbytes = (maxsector + 1) * block_len;
5296 			ret = humanize_number(tmpstr, sizeof(tmpstr),
5297 					      tmpbytes, "", HN_AUTOSCALE,
5298 					      HN_B | HN_DECIMAL |
5299 					      ((baseten != 0) ?
5300 					      HN_DIVISOR_1000 : 0));
5301 			if (ret == -1) {
5302 				warnx("%s: humanize_number failed!", __func__);
5303 				retval = 1;
5304 				goto bailout;
5305 			}
5306 			fprintf(stdout, "Device Size: %s%s", tmpstr,
5307 				(sizeonly == 0) ?  ", " : "\n");
5308 		} else if (numblocks != 0) {
5309 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
5310 				"Blocks: " : "", (uintmax_t)maxsector + 1,
5311 				(sizeonly == 0) ? ", " : "\n");
5312 		} else {
5313 			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
5314 				"Last Block: " : "", (uintmax_t)maxsector,
5315 				(sizeonly == 0) ? ", " : "\n");
5316 		}
5317 	}
5318 	if (sizeonly == 0)
5319 		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
5320 			"Block Length: " : "", block_len, (quiet == 0) ?
5321 			" bytes" : "");
5322 bailout:
5323 	cam_freeccb(ccb);
5324 
5325 	return (retval);
5326 }
5327 
5328 static int
5329 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
5330        int retry_count, int timeout)
5331 {
5332 	int c, error = 0;
5333 	union ccb *ccb;
5334 	uint8_t *smp_request = NULL, *smp_response = NULL;
5335 	int request_size = 0, response_size = 0;
5336 	int fd_request = 0, fd_response = 0;
5337 	char *datastr = NULL;
5338 	struct get_hook hook;
5339 	int retval;
5340 	int flags = 0;
5341 
5342 	/*
5343 	 * Note that at the moment we don't support sending SMP CCBs to
5344 	 * devices that aren't probed by CAM.
5345 	 */
5346 	ccb = cam_getccb(device);
5347 	if (ccb == NULL) {
5348 		warnx("%s: error allocating CCB", __func__);
5349 		return (1);
5350 	}
5351 
5352 	bzero(&(&ccb->ccb_h)[1],
5353 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5354 
5355 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5356 		switch (c) {
5357 		case 'R':
5358 			arglist |= CAM_ARG_CMD_IN;
5359 			response_size = strtol(optarg, NULL, 0);
5360 			if (response_size <= 0) {
5361 				warnx("invalid number of response bytes %d",
5362 				      response_size);
5363 				error = 1;
5364 				goto smpcmd_bailout;
5365 			}
5366 			hook.argc = argc - optind;
5367 			hook.argv = argv + optind;
5368 			hook.got = 0;
5369 			optind++;
5370 			datastr = cget(&hook, NULL);
5371 			/*
5372 			 * If the user supplied "-" instead of a format, he
5373 			 * wants the data to be written to stdout.
5374 			 */
5375 			if ((datastr != NULL)
5376 			 && (datastr[0] == '-'))
5377 				fd_response = 1;
5378 
5379 			smp_response = (u_int8_t *)malloc(response_size);
5380 			if (smp_response == NULL) {
5381 				warn("can't malloc memory for SMP response");
5382 				error = 1;
5383 				goto smpcmd_bailout;
5384 			}
5385 			break;
5386 		case 'r':
5387 			arglist |= CAM_ARG_CMD_OUT;
5388 			request_size = strtol(optarg, NULL, 0);
5389 			if (request_size <= 0) {
5390 				warnx("invalid number of request bytes %d",
5391 				      request_size);
5392 				error = 1;
5393 				goto smpcmd_bailout;
5394 			}
5395 			hook.argc = argc - optind;
5396 			hook.argv = argv + optind;
5397 			hook.got = 0;
5398 			datastr = cget(&hook, NULL);
5399 			smp_request = (u_int8_t *)malloc(request_size);
5400 			if (smp_request == NULL) {
5401 				warn("can't malloc memory for SMP request");
5402 				error = 1;
5403 				goto smpcmd_bailout;
5404 			}
5405 			bzero(smp_request, request_size);
5406 			/*
5407 			 * If the user supplied "-" instead of a format, he
5408 			 * wants the data to be read from stdin.
5409 			 */
5410 			if ((datastr != NULL)
5411 			 && (datastr[0] == '-'))
5412 				fd_request = 1;
5413 			else
5414 				buff_encode_visit(smp_request, request_size,
5415 						  datastr,
5416 						  iget, &hook);
5417 			optind += hook.got;
5418 			break;
5419 		default:
5420 			break;
5421 		}
5422 	}
5423 
5424 	/*
5425 	 * If fd_data is set, and we're writing to the device, we need to
5426 	 * read the data the user wants written from stdin.
5427 	 */
5428 	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
5429 		ssize_t amt_read;
5430 		int amt_to_read = request_size;
5431 		u_int8_t *buf_ptr = smp_request;
5432 
5433 		for (amt_read = 0; amt_to_read > 0;
5434 		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
5435 			if (amt_read == -1) {
5436 				warn("error reading data from stdin");
5437 				error = 1;
5438 				goto smpcmd_bailout;
5439 			}
5440 			amt_to_read -= amt_read;
5441 			buf_ptr += amt_read;
5442 		}
5443 	}
5444 
5445 	if (((arglist & CAM_ARG_CMD_IN) == 0)
5446 	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
5447 		warnx("%s: need both the request (-r) and response (-R) "
5448 		      "arguments", __func__);
5449 		error = 1;
5450 		goto smpcmd_bailout;
5451 	}
5452 
5453 	flags |= CAM_DEV_QFRZDIS;
5454 
5455 	cam_fill_smpio(&ccb->smpio,
5456 		       /*retries*/ retry_count,
5457 		       /*cbfcnp*/ NULL,
5458 		       /*flags*/ flags,
5459 		       /*smp_request*/ smp_request,
5460 		       /*smp_request_len*/ request_size,
5461 		       /*smp_response*/ smp_response,
5462 		       /*smp_response_len*/ response_size,
5463 		       /*timeout*/ timeout ? timeout : 5000);
5464 
5465 	ccb->smpio.flags = SMP_FLAG_NONE;
5466 
5467 	if (((retval = cam_send_ccb(device, ccb)) < 0)
5468 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5469 		const char warnstr[] = "error sending command";
5470 
5471 		if (retval < 0)
5472 			warn(warnstr);
5473 		else
5474 			warnx(warnstr);
5475 
5476 		if (arglist & CAM_ARG_VERBOSE) {
5477 			cam_error_print(device, ccb, CAM_ESF_ALL,
5478 					CAM_EPF_ALL, stderr);
5479 		}
5480 	}
5481 
5482 	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
5483 	 && (response_size > 0)) {
5484 		if (fd_response == 0) {
5485 			buff_decode_visit(smp_response, response_size,
5486 					  datastr, arg_put, NULL);
5487 			fprintf(stdout, "\n");
5488 		} else {
5489 			ssize_t amt_written;
5490 			int amt_to_write = response_size;
5491 			u_int8_t *buf_ptr = smp_response;
5492 
5493 			for (amt_written = 0; (amt_to_write > 0) &&
5494 			     (amt_written = write(STDOUT_FILENO, buf_ptr,
5495 						  amt_to_write)) > 0;){
5496 				amt_to_write -= amt_written;
5497 				buf_ptr += amt_written;
5498 			}
5499 			if (amt_written == -1) {
5500 				warn("error writing data to stdout");
5501 				error = 1;
5502 				goto smpcmd_bailout;
5503 			} else if ((amt_written == 0)
5504 				&& (amt_to_write > 0)) {
5505 				warnx("only wrote %u bytes out of %u",
5506 				      response_size - amt_to_write,
5507 				      response_size);
5508 			}
5509 		}
5510 	}
5511 smpcmd_bailout:
5512 	if (ccb != NULL)
5513 		cam_freeccb(ccb);
5514 
5515 	if (smp_request != NULL)
5516 		free(smp_request);
5517 
5518 	if (smp_response != NULL)
5519 		free(smp_response);
5520 
5521 	return (error);
5522 }
5523 
5524 static int
5525 smpreportgeneral(struct cam_device *device, int argc, char **argv,
5526 		 char *combinedopt, int retry_count, int timeout)
5527 {
5528 	union ccb *ccb;
5529 	struct smp_report_general_request *request = NULL;
5530 	struct smp_report_general_response *response = NULL;
5531 	struct sbuf *sb = NULL;
5532 	int error = 0;
5533 	int c, long_response = 0;
5534 	int retval;
5535 
5536 	/*
5537 	 * Note that at the moment we don't support sending SMP CCBs to
5538 	 * devices that aren't probed by CAM.
5539 	 */
5540 	ccb = cam_getccb(device);
5541 	if (ccb == NULL) {
5542 		warnx("%s: error allocating CCB", __func__);
5543 		return (1);
5544 	}
5545 
5546 	bzero(&(&ccb->ccb_h)[1],
5547 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5548 
5549 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5550 		switch (c) {
5551 		case 'l':
5552 			long_response = 1;
5553 			break;
5554 		default:
5555 			break;
5556 		}
5557 	}
5558 	request = malloc(sizeof(*request));
5559 	if (request == NULL) {
5560 		warn("%s: unable to allocate %zd bytes", __func__,
5561 		     sizeof(*request));
5562 		error = 1;
5563 		goto bailout;
5564 	}
5565 
5566 	response = malloc(sizeof(*response));
5567 	if (response == NULL) {
5568 		warn("%s: unable to allocate %zd bytes", __func__,
5569 		     sizeof(*response));
5570 		error = 1;
5571 		goto bailout;
5572 	}
5573 
5574 try_long:
5575 	smp_report_general(&ccb->smpio,
5576 			   retry_count,
5577 			   /*cbfcnp*/ NULL,
5578 			   request,
5579 			   /*request_len*/ sizeof(*request),
5580 			   (uint8_t *)response,
5581 			   /*response_len*/ sizeof(*response),
5582 			   /*long_response*/ long_response,
5583 			   timeout);
5584 
5585 	if (((retval = cam_send_ccb(device, ccb)) < 0)
5586 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5587 		const char warnstr[] = "error sending command";
5588 
5589 		if (retval < 0)
5590 			warn(warnstr);
5591 		else
5592 			warnx(warnstr);
5593 
5594 		if (arglist & CAM_ARG_VERBOSE) {
5595 			cam_error_print(device, ccb, CAM_ESF_ALL,
5596 					CAM_EPF_ALL, stderr);
5597 		}
5598 		error = 1;
5599 		goto bailout;
5600 	}
5601 
5602 	/*
5603 	 * If the device supports the long response bit, try again and see
5604 	 * if we can get all of the data.
5605 	 */
5606 	if ((response->long_response & SMP_RG_LONG_RESPONSE)
5607 	 && (long_response == 0)) {
5608 		ccb->ccb_h.status = CAM_REQ_INPROG;
5609 		bzero(&(&ccb->ccb_h)[1],
5610 		      sizeof(union ccb) - sizeof(struct ccb_hdr));
5611 		long_response = 1;
5612 		goto try_long;
5613 	}
5614 
5615 	/*
5616 	 * XXX KDM detect and decode SMP errors here.
5617 	 */
5618 	sb = sbuf_new_auto();
5619 	if (sb == NULL) {
5620 		warnx("%s: error allocating sbuf", __func__);
5621 		goto bailout;
5622 	}
5623 
5624 	smp_report_general_sbuf(response, sizeof(*response), sb);
5625 
5626 	if (sbuf_finish(sb) != 0) {
5627 		warnx("%s: sbuf_finish", __func__);
5628 		goto bailout;
5629 	}
5630 
5631 	printf("%s", sbuf_data(sb));
5632 
5633 bailout:
5634 	if (ccb != NULL)
5635 		cam_freeccb(ccb);
5636 
5637 	if (request != NULL)
5638 		free(request);
5639 
5640 	if (response != NULL)
5641 		free(response);
5642 
5643 	if (sb != NULL)
5644 		sbuf_delete(sb);
5645 
5646 	return (error);
5647 }
5648 
5649 static struct camcontrol_opts phy_ops[] = {
5650 	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
5651 	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
5652 	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
5653 	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
5654 	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
5655 	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
5656 	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
5657 	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
5658 	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
5659 	{NULL, 0, 0, NULL}
5660 };
5661 
5662 static int
5663 smpphycontrol(struct cam_device *device, int argc, char **argv,
5664 	      char *combinedopt, int retry_count, int timeout)
5665 {
5666 	union ccb *ccb;
5667 	struct smp_phy_control_request *request = NULL;
5668 	struct smp_phy_control_response *response = NULL;
5669 	int long_response = 0;
5670 	int retval = 0;
5671 	int phy = -1;
5672 	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
5673 	int phy_op_set = 0;
5674 	uint64_t attached_dev_name = 0;
5675 	int dev_name_set = 0;
5676 	uint32_t min_plr = 0, max_plr = 0;
5677 	uint32_t pp_timeout_val = 0;
5678 	int slumber_partial = 0;
5679 	int set_pp_timeout_val = 0;
5680 	int c;
5681 
5682 	/*
5683 	 * Note that at the moment we don't support sending SMP CCBs to
5684 	 * devices that aren't probed by CAM.
5685 	 */
5686 	ccb = cam_getccb(device);
5687 	if (ccb == NULL) {
5688 		warnx("%s: error allocating CCB", __func__);
5689 		return (1);
5690 	}
5691 
5692 	bzero(&(&ccb->ccb_h)[1],
5693 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5694 
5695 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5696 		switch (c) {
5697 		case 'a':
5698 		case 'A':
5699 		case 's':
5700 		case 'S': {
5701 			int enable = -1;
5702 
5703 			if (strcasecmp(optarg, "enable") == 0)
5704 				enable = 1;
5705 			else if (strcasecmp(optarg, "disable") == 0)
5706 				enable = 2;
5707 			else {
5708 				warnx("%s: Invalid argument %s", __func__,
5709 				      optarg);
5710 				retval = 1;
5711 				goto bailout;
5712 			}
5713 			switch (c) {
5714 			case 's':
5715 				slumber_partial |= enable <<
5716 						   SMP_PC_SAS_SLUMBER_SHIFT;
5717 				break;
5718 			case 'S':
5719 				slumber_partial |= enable <<
5720 						   SMP_PC_SAS_PARTIAL_SHIFT;
5721 				break;
5722 			case 'a':
5723 				slumber_partial |= enable <<
5724 						   SMP_PC_SATA_SLUMBER_SHIFT;
5725 				break;
5726 			case 'A':
5727 				slumber_partial |= enable <<
5728 						   SMP_PC_SATA_PARTIAL_SHIFT;
5729 				break;
5730 			default:
5731 				warnx("%s: programmer error", __func__);
5732 				retval = 1;
5733 				goto bailout;
5734 				break; /*NOTREACHED*/
5735 			}
5736 			break;
5737 		}
5738 		case 'd':
5739 			attached_dev_name = (uintmax_t)strtoumax(optarg,
5740 								 NULL,0);
5741 			dev_name_set = 1;
5742 			break;
5743 		case 'l':
5744 			long_response = 1;
5745 			break;
5746 		case 'm':
5747 			/*
5748 			 * We don't do extensive checking here, so this
5749 			 * will continue to work when new speeds come out.
5750 			 */
5751 			min_plr = strtoul(optarg, NULL, 0);
5752 			if ((min_plr == 0)
5753 			 || (min_plr > 0xf)) {
5754 				warnx("%s: invalid link rate %x",
5755 				      __func__, min_plr);
5756 				retval = 1;
5757 				goto bailout;
5758 			}
5759 			break;
5760 		case 'M':
5761 			/*
5762 			 * We don't do extensive checking here, so this
5763 			 * will continue to work when new speeds come out.
5764 			 */
5765 			max_plr = strtoul(optarg, NULL, 0);
5766 			if ((max_plr == 0)
5767 			 || (max_plr > 0xf)) {
5768 				warnx("%s: invalid link rate %x",
5769 				      __func__, max_plr);
5770 				retval = 1;
5771 				goto bailout;
5772 			}
5773 			break;
5774 		case 'o': {
5775 			camcontrol_optret optreturn;
5776 			cam_argmask argnums;
5777 			const char *subopt;
5778 
5779 			if (phy_op_set != 0) {
5780 				warnx("%s: only one phy operation argument "
5781 				      "(-o) allowed", __func__);
5782 				retval = 1;
5783 				goto bailout;
5784 			}
5785 
5786 			phy_op_set = 1;
5787 
5788 			/*
5789 			 * Allow the user to specify the phy operation
5790 			 * numerically, as well as with a name.  This will
5791 			 * future-proof it a bit, so options that are added
5792 			 * in future specs can be used.
5793 			 */
5794 			if (isdigit(optarg[0])) {
5795 				phy_operation = strtoul(optarg, NULL, 0);
5796 				if ((phy_operation == 0)
5797 				 || (phy_operation > 0xff)) {
5798 					warnx("%s: invalid phy operation %#x",
5799 					      __func__, phy_operation);
5800 					retval = 1;
5801 					goto bailout;
5802 				}
5803 				break;
5804 			}
5805 			optreturn = getoption(phy_ops, optarg, &phy_operation,
5806 					      &argnums, &subopt);
5807 
5808 			if (optreturn == CC_OR_AMBIGUOUS) {
5809 				warnx("%s: ambiguous option %s", __func__,
5810 				      optarg);
5811 				usage(0);
5812 				retval = 1;
5813 				goto bailout;
5814 			} else if (optreturn == CC_OR_NOT_FOUND) {
5815 				warnx("%s: option %s not found", __func__,
5816 				      optarg);
5817 				usage(0);
5818 				retval = 1;
5819 				goto bailout;
5820 			}
5821 			break;
5822 		}
5823 		case 'p':
5824 			phy = atoi(optarg);
5825 			break;
5826 		case 'T':
5827 			pp_timeout_val = strtoul(optarg, NULL, 0);
5828 			if (pp_timeout_val > 15) {
5829 				warnx("%s: invalid partial pathway timeout "
5830 				      "value %u, need a value less than 16",
5831 				      __func__, pp_timeout_val);
5832 				retval = 1;
5833 				goto bailout;
5834 			}
5835 			set_pp_timeout_val = 1;
5836 			break;
5837 		default:
5838 			break;
5839 		}
5840 	}
5841 
5842 	if (phy == -1) {
5843 		warnx("%s: a PHY (-p phy) argument is required",__func__);
5844 		retval = 1;
5845 		goto bailout;
5846 	}
5847 
5848 	if (((dev_name_set != 0)
5849 	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
5850 	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
5851 	  && (dev_name_set == 0))) {
5852 		warnx("%s: -d name and -o setdevname arguments both "
5853 		      "required to set device name", __func__);
5854 		retval = 1;
5855 		goto bailout;
5856 	}
5857 
5858 	request = malloc(sizeof(*request));
5859 	if (request == NULL) {
5860 		warn("%s: unable to allocate %zd bytes", __func__,
5861 		     sizeof(*request));
5862 		retval = 1;
5863 		goto bailout;
5864 	}
5865 
5866 	response = malloc(sizeof(*response));
5867 	if (response == NULL) {
5868 		warn("%s: unable to allocate %zd bytes", __func__,
5869 		     sizeof(*request));
5870 		retval = 1;
5871 		goto bailout;
5872 	}
5873 
5874 	smp_phy_control(&ccb->smpio,
5875 			retry_count,
5876 			/*cbfcnp*/ NULL,
5877 			request,
5878 			sizeof(*request),
5879 			(uint8_t *)response,
5880 			sizeof(*response),
5881 			long_response,
5882 			/*expected_exp_change_count*/ 0,
5883 			phy,
5884 			phy_operation,
5885 			(set_pp_timeout_val != 0) ? 1 : 0,
5886 			attached_dev_name,
5887 			min_plr,
5888 			max_plr,
5889 			slumber_partial,
5890 			pp_timeout_val,
5891 			timeout);
5892 
5893 	if (((retval = cam_send_ccb(device, ccb)) < 0)
5894 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5895 		const char warnstr[] = "error sending command";
5896 
5897 		if (retval < 0)
5898 			warn(warnstr);
5899 		else
5900 			warnx(warnstr);
5901 
5902 		if (arglist & CAM_ARG_VERBOSE) {
5903 			/*
5904 			 * Use CAM_EPF_NORMAL so we only get one line of
5905 			 * SMP command decoding.
5906 			 */
5907 			cam_error_print(device, ccb, CAM_ESF_ALL,
5908 					CAM_EPF_NORMAL, stderr);
5909 		}
5910 		retval = 1;
5911 		goto bailout;
5912 	}
5913 
5914 	/* XXX KDM print out something here for success? */
5915 bailout:
5916 	if (ccb != NULL)
5917 		cam_freeccb(ccb);
5918 
5919 	if (request != NULL)
5920 		free(request);
5921 
5922 	if (response != NULL)
5923 		free(response);
5924 
5925 	return (retval);
5926 }
5927 
5928 static int
5929 smpmaninfo(struct cam_device *device, int argc, char **argv,
5930 	   char *combinedopt, int retry_count, int timeout)
5931 {
5932 	union ccb *ccb;
5933 	struct smp_report_manuf_info_request request;
5934 	struct smp_report_manuf_info_response response;
5935 	struct sbuf *sb = NULL;
5936 	int long_response = 0;
5937 	int retval = 0;
5938 	int c;
5939 
5940 	/*
5941 	 * Note that at the moment we don't support sending SMP CCBs to
5942 	 * devices that aren't probed by CAM.
5943 	 */
5944 	ccb = cam_getccb(device);
5945 	if (ccb == NULL) {
5946 		warnx("%s: error allocating CCB", __func__);
5947 		return (1);
5948 	}
5949 
5950 	bzero(&(&ccb->ccb_h)[1],
5951 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5952 
5953 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5954 		switch (c) {
5955 		case 'l':
5956 			long_response = 1;
5957 			break;
5958 		default:
5959 			break;
5960 		}
5961 	}
5962 	bzero(&request, sizeof(request));
5963 	bzero(&response, sizeof(response));
5964 
5965 	smp_report_manuf_info(&ccb->smpio,
5966 			      retry_count,
5967 			      /*cbfcnp*/ NULL,
5968 			      &request,
5969 			      sizeof(request),
5970 			      (uint8_t *)&response,
5971 			      sizeof(response),
5972 			      long_response,
5973 			      timeout);
5974 
5975 	if (((retval = cam_send_ccb(device, ccb)) < 0)
5976 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5977 		const char warnstr[] = "error sending command";
5978 
5979 		if (retval < 0)
5980 			warn(warnstr);
5981 		else
5982 			warnx(warnstr);
5983 
5984 		if (arglist & CAM_ARG_VERBOSE) {
5985 			cam_error_print(device, ccb, CAM_ESF_ALL,
5986 					CAM_EPF_ALL, stderr);
5987 		}
5988 		retval = 1;
5989 		goto bailout;
5990 	}
5991 
5992 	sb = sbuf_new_auto();
5993 	if (sb == NULL) {
5994 		warnx("%s: error allocating sbuf", __func__);
5995 		goto bailout;
5996 	}
5997 
5998 	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
5999 
6000 	if (sbuf_finish(sb) != 0) {
6001 		warnx("%s: sbuf_finish", __func__);
6002 		goto bailout;
6003 	}
6004 
6005 	printf("%s", sbuf_data(sb));
6006 
6007 bailout:
6008 
6009 	if (ccb != NULL)
6010 		cam_freeccb(ccb);
6011 
6012 	if (sb != NULL)
6013 		sbuf_delete(sb);
6014 
6015 	return (retval);
6016 }
6017 
6018 static int
6019 getdevid(struct cam_devitem *item)
6020 {
6021 	int retval = 0;
6022 	union ccb *ccb = NULL;
6023 
6024 	struct cam_device *dev;
6025 
6026 	dev = cam_open_btl(item->dev_match.path_id,
6027 			   item->dev_match.target_id,
6028 			   item->dev_match.target_lun, O_RDWR, NULL);
6029 
6030 	if (dev == NULL) {
6031 		warnx("%s", cam_errbuf);
6032 		retval = 1;
6033 		goto bailout;
6034 	}
6035 
6036 	item->device_id_len = 0;
6037 
6038 	ccb = cam_getccb(dev);
6039 	if (ccb == NULL) {
6040 		warnx("%s: error allocating CCB", __func__);
6041 		retval = 1;
6042 		goto bailout;
6043 	}
6044 
6045 	bzero(&(&ccb->ccb_h)[1],
6046 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6047 
6048 	/*
6049 	 * On the first try, we just probe for the size of the data, and
6050 	 * then allocate that much memory and try again.
6051 	 */
6052 retry:
6053 	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
6054 	ccb->ccb_h.flags = CAM_DIR_IN;
6055 	ccb->cdai.flags = 0;
6056 	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
6057 	ccb->cdai.bufsiz = item->device_id_len;
6058 	if (item->device_id_len != 0)
6059 		ccb->cdai.buf = (uint8_t *)item->device_id;
6060 
6061 	if (cam_send_ccb(dev, ccb) < 0) {
6062 		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
6063 		retval = 1;
6064 		goto bailout;
6065 	}
6066 
6067 	if (ccb->ccb_h.status != CAM_REQ_CMP) {
6068 		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
6069 		retval = 1;
6070 		goto bailout;
6071 	}
6072 
6073 	if (item->device_id_len == 0) {
6074 		/*
6075 		 * This is our first time through.  Allocate the buffer,
6076 		 * and then go back to get the data.
6077 		 */
6078 		if (ccb->cdai.provsiz == 0) {
6079 			warnx("%s: invalid .provsiz field returned with "
6080 			     "XPT_GDEV_ADVINFO CCB", __func__);
6081 			retval = 1;
6082 			goto bailout;
6083 		}
6084 		item->device_id_len = ccb->cdai.provsiz;
6085 		item->device_id = malloc(item->device_id_len);
6086 		if (item->device_id == NULL) {
6087 			warn("%s: unable to allocate %d bytes", __func__,
6088 			     item->device_id_len);
6089 			retval = 1;
6090 			goto bailout;
6091 		}
6092 		ccb->ccb_h.status = CAM_REQ_INPROG;
6093 		goto retry;
6094 	}
6095 
6096 bailout:
6097 	if (dev != NULL)
6098 		cam_close_device(dev);
6099 
6100 	if (ccb != NULL)
6101 		cam_freeccb(ccb);
6102 
6103 	return (retval);
6104 }
6105 
6106 /*
6107  * XXX KDM merge this code with getdevtree()?
6108  */
6109 static int
6110 buildbusdevlist(struct cam_devlist *devlist)
6111 {
6112 	union ccb ccb;
6113 	int bufsize, fd = -1;
6114 	struct dev_match_pattern *patterns;
6115 	struct cam_devitem *item = NULL;
6116 	int skip_device = 0;
6117 	int retval = 0;
6118 
6119 	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
6120 		warn("couldn't open %s", XPT_DEVICE);
6121 		return(1);
6122 	}
6123 
6124 	bzero(&ccb, sizeof(union ccb));
6125 
6126 	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
6127 	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
6128 	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
6129 
6130 	ccb.ccb_h.func_code = XPT_DEV_MATCH;
6131 	bufsize = sizeof(struct dev_match_result) * 100;
6132 	ccb.cdm.match_buf_len = bufsize;
6133 	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
6134 	if (ccb.cdm.matches == NULL) {
6135 		warnx("can't malloc memory for matches");
6136 		close(fd);
6137 		return(1);
6138 	}
6139 	ccb.cdm.num_matches = 0;
6140 	ccb.cdm.num_patterns = 2;
6141 	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
6142 		ccb.cdm.num_patterns;
6143 
6144 	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
6145 	if (patterns == NULL) {
6146 		warnx("can't malloc memory for patterns");
6147 		retval = 1;
6148 		goto bailout;
6149 	}
6150 
6151 	ccb.cdm.patterns = patterns;
6152 	bzero(patterns, ccb.cdm.pattern_buf_len);
6153 
6154 	patterns[0].type = DEV_MATCH_DEVICE;
6155 	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
6156 	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
6157 	patterns[1].type = DEV_MATCH_PERIPH;
6158 	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
6159 	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
6160 
6161 	/*
6162 	 * We do the ioctl multiple times if necessary, in case there are
6163 	 * more than 100 nodes in the EDT.
6164 	 */
6165 	do {
6166 		unsigned int i;
6167 
6168 		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
6169 			warn("error sending CAMIOCOMMAND ioctl");
6170 			retval = 1;
6171 			goto bailout;
6172 		}
6173 
6174 		if ((ccb.ccb_h.status != CAM_REQ_CMP)
6175 		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
6176 		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
6177 			warnx("got CAM error %#x, CDM error %d\n",
6178 			      ccb.ccb_h.status, ccb.cdm.status);
6179 			retval = 1;
6180 			goto bailout;
6181 		}
6182 
6183 		for (i = 0; i < ccb.cdm.num_matches; i++) {
6184 			switch (ccb.cdm.matches[i].type) {
6185 			case DEV_MATCH_DEVICE: {
6186 				struct device_match_result *dev_result;
6187 
6188 				dev_result =
6189 				     &ccb.cdm.matches[i].result.device_result;
6190 
6191 				if (dev_result->flags &
6192 				    DEV_RESULT_UNCONFIGURED) {
6193 					skip_device = 1;
6194 					break;
6195 				} else
6196 					skip_device = 0;
6197 
6198 				item = malloc(sizeof(*item));
6199 				if (item == NULL) {
6200 					warn("%s: unable to allocate %zd bytes",
6201 					     __func__, sizeof(*item));
6202 					retval = 1;
6203 					goto bailout;
6204 				}
6205 				bzero(item, sizeof(*item));
6206 				bcopy(dev_result, &item->dev_match,
6207 				      sizeof(*dev_result));
6208 				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
6209 						   links);
6210 
6211 				if (getdevid(item) != 0) {
6212 					retval = 1;
6213 					goto bailout;
6214 				}
6215 				break;
6216 			}
6217 			case DEV_MATCH_PERIPH: {
6218 				struct periph_match_result *periph_result;
6219 
6220 				periph_result =
6221 				      &ccb.cdm.matches[i].result.periph_result;
6222 
6223 				if (skip_device != 0)
6224 					break;
6225 				item->num_periphs++;
6226 				item->periph_matches = realloc(
6227 					item->periph_matches,
6228 					item->num_periphs *
6229 					sizeof(struct periph_match_result));
6230 				if (item->periph_matches == NULL) {
6231 					warn("%s: error allocating periph "
6232 					     "list", __func__);
6233 					retval = 1;
6234 					goto bailout;
6235 				}
6236 				bcopy(periph_result, &item->periph_matches[
6237 				      item->num_periphs - 1],
6238 				      sizeof(*periph_result));
6239 				break;
6240 			}
6241 			default:
6242 				fprintf(stderr, "%s: unexpected match "
6243 					"type %d\n", __func__,
6244 					ccb.cdm.matches[i].type);
6245 				retval = 1;
6246 				goto bailout;
6247 				break; /*NOTREACHED*/
6248 			}
6249 		}
6250 	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
6251 		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
6252 bailout:
6253 
6254 	if (fd != -1)
6255 		close(fd);
6256 
6257 	free(patterns);
6258 
6259 	free(ccb.cdm.matches);
6260 
6261 	if (retval != 0)
6262 		freebusdevlist(devlist);
6263 
6264 	return (retval);
6265 }
6266 
6267 static void
6268 freebusdevlist(struct cam_devlist *devlist)
6269 {
6270 	struct cam_devitem *item, *item2;
6271 
6272 	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
6273 		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
6274 			      links);
6275 		free(item->device_id);
6276 		free(item->periph_matches);
6277 		free(item);
6278 	}
6279 }
6280 
6281 static struct cam_devitem *
6282 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
6283 {
6284 	struct cam_devitem *item;
6285 
6286 	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
6287 		uint8_t *item_addr;
6288 
6289 		/*
6290 		 * XXX KDM look for LUN IDs as well?
6291 		 */
6292 		item_addr = scsi_get_devid(item->device_id,
6293 					   item->device_id_len,
6294 					   scsi_devid_is_sas_target);
6295 		if (item_addr == NULL)
6296 			continue;
6297 
6298 		if (scsi_8btou64(item_addr) == sasaddr)
6299 			return (item);
6300 	}
6301 
6302 	return (NULL);
6303 }
6304 
6305 static int
6306 smpphylist(struct cam_device *device, int argc, char **argv,
6307 	   char *combinedopt, int retry_count, int timeout)
6308 {
6309 	struct smp_report_general_request *rgrequest = NULL;
6310 	struct smp_report_general_response *rgresponse = NULL;
6311 	struct smp_discover_request *disrequest = NULL;
6312 	struct smp_discover_response *disresponse = NULL;
6313 	struct cam_devlist devlist;
6314 	union ccb *ccb;
6315 	int long_response = 0;
6316 	int num_phys = 0;
6317 	int quiet = 0;
6318 	int retval;
6319 	int i, c;
6320 
6321 	/*
6322 	 * Note that at the moment we don't support sending SMP CCBs to
6323 	 * devices that aren't probed by CAM.
6324 	 */
6325 	ccb = cam_getccb(device);
6326 	if (ccb == NULL) {
6327 		warnx("%s: error allocating CCB", __func__);
6328 		return (1);
6329 	}
6330 
6331 	bzero(&(&ccb->ccb_h)[1],
6332 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6333 	STAILQ_INIT(&devlist.dev_queue);
6334 
6335 	rgrequest = malloc(sizeof(*rgrequest));
6336 	if (rgrequest == NULL) {
6337 		warn("%s: unable to allocate %zd bytes", __func__,
6338 		     sizeof(*rgrequest));
6339 		retval = 1;
6340 		goto bailout;
6341 	}
6342 
6343 	rgresponse = malloc(sizeof(*rgresponse));
6344 	if (rgresponse == NULL) {
6345 		warn("%s: unable to allocate %zd bytes", __func__,
6346 		     sizeof(*rgresponse));
6347 		retval = 1;
6348 		goto bailout;
6349 	}
6350 
6351 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6352 		switch (c) {
6353 		case 'l':
6354 			long_response = 1;
6355 			break;
6356 		case 'q':
6357 			quiet = 1;
6358 			break;
6359 		default:
6360 			break;
6361 		}
6362 	}
6363 
6364 	smp_report_general(&ccb->smpio,
6365 			   retry_count,
6366 			   /*cbfcnp*/ NULL,
6367 			   rgrequest,
6368 			   /*request_len*/ sizeof(*rgrequest),
6369 			   (uint8_t *)rgresponse,
6370 			   /*response_len*/ sizeof(*rgresponse),
6371 			   /*long_response*/ long_response,
6372 			   timeout);
6373 
6374 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6375 
6376 	if (((retval = cam_send_ccb(device, ccb)) < 0)
6377 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6378 		const char warnstr[] = "error sending command";
6379 
6380 		if (retval < 0)
6381 			warn(warnstr);
6382 		else
6383 			warnx(warnstr);
6384 
6385 		if (arglist & CAM_ARG_VERBOSE) {
6386 			cam_error_print(device, ccb, CAM_ESF_ALL,
6387 					CAM_EPF_ALL, stderr);
6388 		}
6389 		retval = 1;
6390 		goto bailout;
6391 	}
6392 
6393 	num_phys = rgresponse->num_phys;
6394 
6395 	if (num_phys == 0) {
6396 		if (quiet == 0)
6397 			fprintf(stdout, "%s: No Phys reported\n", __func__);
6398 		retval = 1;
6399 		goto bailout;
6400 	}
6401 
6402 	devlist.path_id = device->path_id;
6403 
6404 	retval = buildbusdevlist(&devlist);
6405 	if (retval != 0)
6406 		goto bailout;
6407 
6408 	if (quiet == 0) {
6409 		fprintf(stdout, "%d PHYs:\n", num_phys);
6410 		fprintf(stdout, "PHY  Attached SAS Address\n");
6411 	}
6412 
6413 	disrequest = malloc(sizeof(*disrequest));
6414 	if (disrequest == NULL) {
6415 		warn("%s: unable to allocate %zd bytes", __func__,
6416 		     sizeof(*disrequest));
6417 		retval = 1;
6418 		goto bailout;
6419 	}
6420 
6421 	disresponse = malloc(sizeof(*disresponse));
6422 	if (disresponse == NULL) {
6423 		warn("%s: unable to allocate %zd bytes", __func__,
6424 		     sizeof(*disresponse));
6425 		retval = 1;
6426 		goto bailout;
6427 	}
6428 
6429 	for (i = 0; i < num_phys; i++) {
6430 		struct cam_devitem *item;
6431 		struct device_match_result *dev_match;
6432 		char vendor[16], product[48], revision[16];
6433 		char tmpstr[256];
6434 		int j;
6435 
6436 		bzero(&(&ccb->ccb_h)[1],
6437 		      sizeof(union ccb) - sizeof(struct ccb_hdr));
6438 
6439 		ccb->ccb_h.status = CAM_REQ_INPROG;
6440 		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6441 
6442 		smp_discover(&ccb->smpio,
6443 			     retry_count,
6444 			     /*cbfcnp*/ NULL,
6445 			     disrequest,
6446 			     sizeof(*disrequest),
6447 			     (uint8_t *)disresponse,
6448 			     sizeof(*disresponse),
6449 			     long_response,
6450 			     /*ignore_zone_group*/ 0,
6451 			     /*phy*/ i,
6452 			     timeout);
6453 
6454 		if (((retval = cam_send_ccb(device, ccb)) < 0)
6455 		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
6456 		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
6457 			const char warnstr[] = "error sending command";
6458 
6459 			if (retval < 0)
6460 				warn(warnstr);
6461 			else
6462 				warnx(warnstr);
6463 
6464 			if (arglist & CAM_ARG_VERBOSE) {
6465 				cam_error_print(device, ccb, CAM_ESF_ALL,
6466 						CAM_EPF_ALL, stderr);
6467 			}
6468 			retval = 1;
6469 			goto bailout;
6470 		}
6471 
6472 		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
6473 			if (quiet == 0)
6474 				fprintf(stdout, "%3d  <vacant>\n", i);
6475 			continue;
6476 		}
6477 
6478 		item = findsasdevice(&devlist,
6479 			scsi_8btou64(disresponse->attached_sas_address));
6480 
6481 		if ((quiet == 0)
6482 		 || (item != NULL)) {
6483 			fprintf(stdout, "%3d  0x%016jx", i,
6484 				(uintmax_t)scsi_8btou64(
6485 				disresponse->attached_sas_address));
6486 			if (item == NULL) {
6487 				fprintf(stdout, "\n");
6488 				continue;
6489 			}
6490 		} else if (quiet != 0)
6491 			continue;
6492 
6493 		dev_match = &item->dev_match;
6494 
6495 		if (dev_match->protocol == PROTO_SCSI) {
6496 			cam_strvis(vendor, dev_match->inq_data.vendor,
6497 				   sizeof(dev_match->inq_data.vendor),
6498 				   sizeof(vendor));
6499 			cam_strvis(product, dev_match->inq_data.product,
6500 				   sizeof(dev_match->inq_data.product),
6501 				   sizeof(product));
6502 			cam_strvis(revision, dev_match->inq_data.revision,
6503 				   sizeof(dev_match->inq_data.revision),
6504 				   sizeof(revision));
6505 			sprintf(tmpstr, "<%s %s %s>", vendor, product,
6506 				revision);
6507 		} else if ((dev_match->protocol == PROTO_ATA)
6508 			|| (dev_match->protocol == PROTO_SATAPM)) {
6509 			cam_strvis(product, dev_match->ident_data.model,
6510 				   sizeof(dev_match->ident_data.model),
6511 				   sizeof(product));
6512 			cam_strvis(revision, dev_match->ident_data.revision,
6513 				   sizeof(dev_match->ident_data.revision),
6514 				   sizeof(revision));
6515 			sprintf(tmpstr, "<%s %s>", product, revision);
6516 		} else {
6517 			sprintf(tmpstr, "<>");
6518 		}
6519 		fprintf(stdout, "   %-33s ", tmpstr);
6520 
6521 		/*
6522 		 * If we have 0 periphs, that's a bug...
6523 		 */
6524 		if (item->num_periphs == 0) {
6525 			fprintf(stdout, "\n");
6526 			continue;
6527 		}
6528 
6529 		fprintf(stdout, "(");
6530 		for (j = 0; j < item->num_periphs; j++) {
6531 			if (j > 0)
6532 				fprintf(stdout, ",");
6533 
6534 			fprintf(stdout, "%s%d",
6535 				item->periph_matches[j].periph_name,
6536 				item->periph_matches[j].unit_number);
6537 
6538 		}
6539 		fprintf(stdout, ")\n");
6540 	}
6541 bailout:
6542 	if (ccb != NULL)
6543 		cam_freeccb(ccb);
6544 
6545 	free(rgrequest);
6546 
6547 	free(rgresponse);
6548 
6549 	free(disrequest);
6550 
6551 	free(disresponse);
6552 
6553 	freebusdevlist(&devlist);
6554 
6555 	return (retval);
6556 }
6557 
6558 static int
6559 atapm(struct cam_device *device, int argc, char **argv,
6560 		 char *combinedopt, int retry_count, int timeout)
6561 {
6562 	union ccb *ccb;
6563 	int retval = 0;
6564 	int t = -1;
6565 	int c;
6566 	u_char cmd, sc;
6567 
6568 	ccb = cam_getccb(device);
6569 
6570 	if (ccb == NULL) {
6571 		warnx("%s: error allocating ccb", __func__);
6572 		return (1);
6573 	}
6574 
6575 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6576 		switch (c) {
6577 		case 't':
6578 			t = atoi(optarg);
6579 			break;
6580 		default:
6581 			break;
6582 		}
6583 	}
6584 	if (strcmp(argv[1], "idle") == 0) {
6585 		if (t == -1)
6586 			cmd = ATA_IDLE_IMMEDIATE;
6587 		else
6588 			cmd = ATA_IDLE_CMD;
6589 	} else if (strcmp(argv[1], "standby") == 0) {
6590 		if (t == -1)
6591 			cmd = ATA_STANDBY_IMMEDIATE;
6592 		else
6593 			cmd = ATA_STANDBY_CMD;
6594 	} else {
6595 		cmd = ATA_SLEEP;
6596 		t = -1;
6597 	}
6598 
6599 	if (t < 0)
6600 		sc = 0;
6601 	else if (t <= (240 * 5))
6602 		sc = (t + 4) / 5;
6603 	else if (t <= (252 * 5))
6604 		/* special encoding for 21 minutes */
6605 		sc = 252;
6606 	else if (t <= (11 * 30 * 60))
6607 		sc = (t - 1) / (30 * 60) + 241;
6608 	else
6609 		sc = 253;
6610 
6611 	cam_fill_ataio(&ccb->ataio,
6612 		      retry_count,
6613 		      NULL,
6614 		      /*flags*/CAM_DIR_NONE,
6615 		      MSG_SIMPLE_Q_TAG,
6616 		      /*data_ptr*/NULL,
6617 		      /*dxfer_len*/0,
6618 		      timeout ? timeout : 30 * 1000);
6619 	ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
6620 
6621 	/* Disable freezing the device queue */
6622 	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6623 
6624 	if (arglist & CAM_ARG_ERR_RECOVER)
6625 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6626 
6627 	if (cam_send_ccb(device, ccb) < 0) {
6628 		warn("error sending command");
6629 
6630 		if (arglist & CAM_ARG_VERBOSE)
6631 			cam_error_print(device, ccb, CAM_ESF_ALL,
6632 					CAM_EPF_ALL, stderr);
6633 
6634 		retval = 1;
6635 		goto bailout;
6636 	}
6637 
6638 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6639 		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6640 		retval = 1;
6641 		goto bailout;
6642 	}
6643 bailout:
6644 	cam_freeccb(ccb);
6645 	return (retval);
6646 }
6647 
6648 #endif /* MINIMALISTIC */
6649 
6650 void
6651 usage(int printlong)
6652 {
6653 
6654 	fprintf(printlong ? stdout : stderr,
6655 "usage:  camcontrol <command>  [device id][generic args][command args]\n"
6656 "        camcontrol devlist    [-v]\n"
6657 #ifndef MINIMALISTIC
6658 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
6659 "        camcontrol tur        [dev_id][generic args]\n"
6660 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
6661 "        camcontrol identify   [dev_id][generic args] [-v]\n"
6662 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
6663 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
6664 "                              [-q] [-s]\n"
6665 "        camcontrol start      [dev_id][generic args]\n"
6666 "        camcontrol stop       [dev_id][generic args]\n"
6667 "        camcontrol load       [dev_id][generic args]\n"
6668 "        camcontrol eject      [dev_id][generic args]\n"
6669 #endif /* MINIMALISTIC */
6670 "        camcontrol rescan     <all | bus[:target:lun]>\n"
6671 "        camcontrol reset      <all | bus[:target:lun]>\n"
6672 #ifndef MINIMALISTIC
6673 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
6674 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
6675 "                              [-P pagectl][-e | -b][-d]\n"
6676 "        camcontrol cmd        [dev_id][generic args]\n"
6677 "                              <-a cmd [args] | -c cmd [args]>\n"
6678 "                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
6679 "        camcontrol smpcmd     [dev_id][generic args]\n"
6680 "                              <-r len fmt [args]> <-R len fmt [args]>\n"
6681 "        camcontrol smprg      [dev_id][generic args][-l]\n"
6682 "        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
6683 "                              [-o operation][-d name][-m rate][-M rate]\n"
6684 "                              [-T pp_timeout][-a enable|disable]\n"
6685 "                              [-A enable|disable][-s enable|disable]\n"
6686 "                              [-S enable|disable]\n"
6687 "        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
6688 "        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
6689 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
6690 "                              <all|bus[:target[:lun]]|off>\n"
6691 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
6692 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
6693 "                              [-D <enable|disable>][-M mode][-O offset]\n"
6694 "                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
6695 "                              [-U][-W bus_width]\n"
6696 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
6697 "        camcontrol idle       [dev_id][generic args][-t time]\n"
6698 "        camcontrol standby    [dev_id][generic args][-t time]\n"
6699 "        camcontrol sleep      [dev_id][generic args]\n"
6700 "        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
6701 "        camcontrol security   [dev_id][generic args]\n"
6702 "                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
6703 "                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
6704 "                              [-U <user|master>] [-y]\n"
6705 #endif /* MINIMALISTIC */
6706 "        camcontrol help\n");
6707 	if (!printlong)
6708 		return;
6709 #ifndef MINIMALISTIC
6710 	fprintf(stdout,
6711 "Specify one of the following options:\n"
6712 "devlist     list all CAM devices\n"
6713 "periphlist  list all CAM peripheral drivers attached to a device\n"
6714 "tur         send a test unit ready to the named device\n"
6715 "inquiry     send a SCSI inquiry command to the named device\n"
6716 "identify    send a ATA identify command to the named device\n"
6717 "reportluns  send a SCSI report luns command to the device\n"
6718 "readcap     send a SCSI read capacity command to the device\n"
6719 "start       send a Start Unit command to the device\n"
6720 "stop        send a Stop Unit command to the device\n"
6721 "load        send a Start Unit command to the device with the load bit set\n"
6722 "eject       send a Stop Unit command to the device with the eject bit set\n"
6723 "rescan      rescan all busses, the given bus, or bus:target:lun\n"
6724 "reset       reset all busses, the given bus, or bus:target:lun\n"
6725 "defects     read the defect list of the specified device\n"
6726 "modepage    display or edit (-e) the given mode page\n"
6727 "cmd         send the given SCSI command, may need -i or -o as well\n"
6728 "smpcmd      send the given SMP command, requires -o and -i\n"
6729 "smprg       send the SMP Report General command\n"
6730 "smppc       send the SMP PHY Control command, requires -p\n"
6731 "smpphylist  display phys attached to a SAS expander\n"
6732 "smpmaninfo  send the SMP Report Manufacturer Info command\n"
6733 "debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
6734 "tags        report or set the number of transaction slots for a device\n"
6735 "negotiate   report or set device negotiation parameters\n"
6736 "format      send the SCSI FORMAT UNIT command to the named device\n"
6737 "idle        send the ATA IDLE command to the named device\n"
6738 "standby     send the ATA STANDBY command to the named device\n"
6739 "sleep       send the ATA SLEEP command to the named device\n"
6740 "fwdownload  program firmware of the named device with the given image"
6741 "security    report or send ATA security commands to the named device\n"
6742 "help        this message\n"
6743 "Device Identifiers:\n"
6744 "bus:target        specify the bus and target, lun defaults to 0\n"
6745 "bus:target:lun    specify the bus, target and lun\n"
6746 "deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
6747 "Generic arguments:\n"
6748 "-v                be verbose, print out sense information\n"
6749 "-t timeout        command timeout in seconds, overrides default timeout\n"
6750 "-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
6751 "-u unit           specify unit number, e.g. \"0\", \"5\"\n"
6752 "-E                have the kernel attempt to perform SCSI error recovery\n"
6753 "-C count          specify the SCSI command retry count (needs -E to work)\n"
6754 "modepage arguments:\n"
6755 "-l                list all available mode pages\n"
6756 "-m page           specify the mode page to view or edit\n"
6757 "-e                edit the specified mode page\n"
6758 "-b                force view to binary mode\n"
6759 "-d                disable block descriptors for mode sense\n"
6760 "-P pgctl          page control field 0-3\n"
6761 "defects arguments:\n"
6762 "-f format         specify defect list format (block, bfi or phys)\n"
6763 "-G                get the grown defect list\n"
6764 "-P                get the permanent defect list\n"
6765 "inquiry arguments:\n"
6766 "-D                get the standard inquiry data\n"
6767 "-S                get the serial number\n"
6768 "-R                get the transfer rate, etc.\n"
6769 "reportluns arguments:\n"
6770 "-c                only report a count of available LUNs\n"
6771 "-l                only print out luns, and not a count\n"
6772 "-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
6773 "readcap arguments\n"
6774 "-b                only report the blocksize\n"
6775 "-h                human readable device size, base 2\n"
6776 "-H                human readable device size, base 10\n"
6777 "-N                print the number of blocks instead of last block\n"
6778 "-q                quiet, print numbers only\n"
6779 "-s                only report the last block/device size\n"
6780 "cmd arguments:\n"
6781 "-c cdb [args]     specify the SCSI CDB\n"
6782 "-i len fmt        specify input data and input data format\n"
6783 "-o len fmt [args] specify output data and output data fmt\n"
6784 "smpcmd arguments:\n"
6785 "-r len fmt [args] specify the SMP command to be sent\n"
6786 "-R len fmt [args] specify SMP response format\n"
6787 "smprg arguments:\n"
6788 "-l                specify the long response format\n"
6789 "smppc arguments:\n"
6790 "-p phy            specify the PHY to operate on\n"
6791 "-l                specify the long request/response format\n"
6792 "-o operation      specify the phy control operation\n"
6793 "-d name           set the attached device name\n"
6794 "-m rate           set the minimum physical link rate\n"
6795 "-M rate           set the maximum physical link rate\n"
6796 "-T pp_timeout     set the partial pathway timeout value\n"
6797 "-a enable|disable enable or disable SATA slumber\n"
6798 "-A enable|disable enable or disable SATA partial phy power\n"
6799 "-s enable|disable enable or disable SAS slumber\n"
6800 "-S enable|disable enable or disable SAS partial phy power\n"
6801 "smpphylist arguments:\n"
6802 "-l                specify the long response format\n"
6803 "-q                only print phys with attached devices\n"
6804 "smpmaninfo arguments:\n"
6805 "-l                specify the long response format\n"
6806 "debug arguments:\n"
6807 "-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
6808 "-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
6809 "-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
6810 "-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
6811 "tags arguments:\n"
6812 "-N tags           specify the number of tags to use for this device\n"
6813 "-q                be quiet, don't report the number of tags\n"
6814 "-v                report a number of tag-related parameters\n"
6815 "negotiate arguments:\n"
6816 "-a                send a test unit ready after negotiation\n"
6817 "-c                report/set current negotiation settings\n"
6818 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
6819 "-M mode           set ATA mode\n"
6820 "-O offset         set command delay offset\n"
6821 "-q                be quiet, don't report anything\n"
6822 "-R syncrate       synchronization rate in MHz\n"
6823 "-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
6824 "-U                report/set user negotiation settings\n"
6825 "-W bus_width      set the bus width in bits (8, 16 or 32)\n"
6826 "-v                also print a Path Inquiry CCB for the controller\n"
6827 "format arguments:\n"
6828 "-q                be quiet, don't print status messages\n"
6829 "-r                run in report only mode\n"
6830 "-w                don't send immediate format command\n"
6831 "-y                don't ask any questions\n"
6832 "idle/standby arguments:\n"
6833 "-t <arg>          number of seconds before respective state.\n"
6834 "fwdownload arguments:\n"
6835 "-f fw_image       path to firmware image file\n"
6836 "-y                don't ask any questions\n"
6837 "-s                run in simulation mode\n"
6838 "-v                print info for every firmware segment sent to device\n"
6839 "security arguments:\n"
6840 "-d pwd            disable security using the given password for the selected\n"
6841 "                  user\n"
6842 "-e pwd            erase the device using the given pwd for the selected user\n"
6843 "-f                freeze the security configuration of the specified device\n"
6844 "-h pwd            enhanced erase the device using the given pwd for the\n"
6845 "                  selected user\n"
6846 "-k pwd            unlock the device using the given pwd for the selected\n"
6847 "                  user\n"
6848 "-l <high|maximum> specifies which security level to set: high or maximum\n"
6849 "-q                be quiet, do not print any status messages\n"
6850 "-s pwd            password the device (enable security) using the given\n"
6851 "                  pwd for the selected user\n"
6852 "-T timeout        overrides the timeout (seconds) used for erase operation\n"
6853 "-U <user|master>  specifies which user to set: user or master\n"
6854 "-y                don't ask any questions\n"
6855 );
6856 #endif /* MINIMALISTIC */
6857 }
6858 
6859 int
6860 main(int argc, char **argv)
6861 {
6862 	int c;
6863 	char *device = NULL;
6864 	int unit = 0;
6865 	struct cam_device *cam_dev = NULL;
6866 	int timeout = 0, retry_count = 1;
6867 	camcontrol_optret optreturn;
6868 	char *tstr;
6869 	const char *mainopt = "C:En:t:u:v";
6870 	const char *subopt = NULL;
6871 	char combinedopt[256];
6872 	int error = 0, optstart = 2;
6873 	int devopen = 1;
6874 #ifndef MINIMALISTIC
6875 	int bus, target, lun;
6876 #endif /* MINIMALISTIC */
6877 
6878 	cmdlist = CAM_CMD_NONE;
6879 	arglist = CAM_ARG_NONE;
6880 
6881 	if (argc < 2) {
6882 		usage(0);
6883 		exit(1);
6884 	}
6885 
6886 	/*
6887 	 * Get the base option.
6888 	 */
6889 	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
6890 
6891 	if (optreturn == CC_OR_AMBIGUOUS) {
6892 		warnx("ambiguous option %s", argv[1]);
6893 		usage(0);
6894 		exit(1);
6895 	} else if (optreturn == CC_OR_NOT_FOUND) {
6896 		warnx("option %s not found", argv[1]);
6897 		usage(0);
6898 		exit(1);
6899 	}
6900 
6901 	/*
6902 	 * Ahh, getopt(3) is a pain.
6903 	 *
6904 	 * This is a gross hack.  There really aren't many other good
6905 	 * options (excuse the pun) for parsing options in a situation like
6906 	 * this.  getopt is kinda braindead, so you end up having to run
6907 	 * through the options twice, and give each invocation of getopt
6908 	 * the option string for the other invocation.
6909 	 *
6910 	 * You would think that you could just have two groups of options.
6911 	 * The first group would get parsed by the first invocation of
6912 	 * getopt, and the second group would get parsed by the second
6913 	 * invocation of getopt.  It doesn't quite work out that way.  When
6914 	 * the first invocation of getopt finishes, it leaves optind pointing
6915 	 * to the argument _after_ the first argument in the second group.
6916 	 * So when the second invocation of getopt comes around, it doesn't
6917 	 * recognize the first argument it gets and then bails out.
6918 	 *
6919 	 * A nice alternative would be to have a flag for getopt that says
6920 	 * "just keep parsing arguments even when you encounter an unknown
6921 	 * argument", but there isn't one.  So there's no real clean way to
6922 	 * easily parse two sets of arguments without having one invocation
6923 	 * of getopt know about the other.
6924 	 *
6925 	 * Without this hack, the first invocation of getopt would work as
6926 	 * long as the generic arguments are first, but the second invocation
6927 	 * (in the subfunction) would fail in one of two ways.  In the case
6928 	 * where you don't set optreset, it would fail because optind may be
6929 	 * pointing to the argument after the one it should be pointing at.
6930 	 * In the case where you do set optreset, and reset optind, it would
6931 	 * fail because getopt would run into the first set of options, which
6932 	 * it doesn't understand.
6933 	 *
6934 	 * All of this would "sort of" work if you could somehow figure out
6935 	 * whether optind had been incremented one option too far.  The
6936 	 * mechanics of that, however, are more daunting than just giving
6937 	 * both invocations all of the expect options for either invocation.
6938 	 *
6939 	 * Needless to say, I wouldn't mind if someone invented a better
6940 	 * (non-GPL!) command line parsing interface than getopt.  I
6941 	 * wouldn't mind if someone added more knobs to getopt to make it
6942 	 * work better.  Who knows, I may talk myself into doing it someday,
6943 	 * if the standards weenies let me.  As it is, it just leads to
6944 	 * hackery like this and causes people to avoid it in some cases.
6945 	 *
6946 	 * KDM, September 8th, 1998
6947 	 */
6948 	if (subopt != NULL)
6949 		sprintf(combinedopt, "%s%s", mainopt, subopt);
6950 	else
6951 		sprintf(combinedopt, "%s", mainopt);
6952 
6953 	/*
6954 	 * For these options we do not parse optional device arguments and
6955 	 * we do not open a passthrough device.
6956 	 */
6957 	if ((cmdlist == CAM_CMD_RESCAN)
6958 	 || (cmdlist == CAM_CMD_RESET)
6959 	 || (cmdlist == CAM_CMD_DEVTREE)
6960 	 || (cmdlist == CAM_CMD_USAGE)
6961 	 || (cmdlist == CAM_CMD_DEBUG))
6962 		devopen = 0;
6963 
6964 #ifndef MINIMALISTIC
6965 	if ((devopen == 1)
6966 	 && (argc > 2 && argv[2][0] != '-')) {
6967 		char name[30];
6968 		int rv;
6969 
6970 		if (isdigit(argv[2][0])) {
6971 			/* device specified as bus:target[:lun] */
6972 			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
6973 			if (rv < 2)
6974 				errx(1, "numeric device specification must "
6975 				     "be either bus:target, or "
6976 				     "bus:target:lun");
6977 			/* default to 0 if lun was not specified */
6978 			if ((arglist & CAM_ARG_LUN) == 0) {
6979 				lun = 0;
6980 				arglist |= CAM_ARG_LUN;
6981 			}
6982 			optstart++;
6983 		} else {
6984 			if (cam_get_device(argv[2], name, sizeof name, &unit)
6985 			    == -1)
6986 				errx(1, "%s", cam_errbuf);
6987 			device = strdup(name);
6988 			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
6989 			optstart++;
6990 		}
6991 	}
6992 #endif /* MINIMALISTIC */
6993 	/*
6994 	 * Start getopt processing at argv[2/3], since we've already
6995 	 * accepted argv[1..2] as the command name, and as a possible
6996 	 * device name.
6997 	 */
6998 	optind = optstart;
6999 
7000 	/*
7001 	 * Now we run through the argument list looking for generic
7002 	 * options, and ignoring options that possibly belong to
7003 	 * subfunctions.
7004 	 */
7005 	while ((c = getopt(argc, argv, combinedopt))!= -1){
7006 		switch(c) {
7007 			case 'C':
7008 				retry_count = strtol(optarg, NULL, 0);
7009 				if (retry_count < 0)
7010 					errx(1, "retry count %d is < 0",
7011 					     retry_count);
7012 				arglist |= CAM_ARG_RETRIES;
7013 				break;
7014 			case 'E':
7015 				arglist |= CAM_ARG_ERR_RECOVER;
7016 				break;
7017 			case 'n':
7018 				arglist |= CAM_ARG_DEVICE;
7019 				tstr = optarg;
7020 				while (isspace(*tstr) && (*tstr != '\0'))
7021 					tstr++;
7022 				device = (char *)strdup(tstr);
7023 				break;
7024 			case 't':
7025 				timeout = strtol(optarg, NULL, 0);
7026 				if (timeout < 0)
7027 					errx(1, "invalid timeout %d", timeout);
7028 				/* Convert the timeout from seconds to ms */
7029 				timeout *= 1000;
7030 				arglist |= CAM_ARG_TIMEOUT;
7031 				break;
7032 			case 'u':
7033 				arglist |= CAM_ARG_UNIT;
7034 				unit = strtol(optarg, NULL, 0);
7035 				break;
7036 			case 'v':
7037 				arglist |= CAM_ARG_VERBOSE;
7038 				break;
7039 			default:
7040 				break;
7041 		}
7042 	}
7043 
7044 #ifndef MINIMALISTIC
7045 	/*
7046 	 * For most commands we'll want to open the passthrough device
7047 	 * associated with the specified device.  In the case of the rescan
7048 	 * commands, we don't use a passthrough device at all, just the
7049 	 * transport layer device.
7050 	 */
7051 	if (devopen == 1) {
7052 		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
7053 		 && (((arglist & CAM_ARG_DEVICE) == 0)
7054 		  || ((arglist & CAM_ARG_UNIT) == 0))) {
7055 			errx(1, "subcommand \"%s\" requires a valid device "
7056 			     "identifier", argv[1]);
7057 		}
7058 
7059 		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
7060 				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
7061 				cam_open_spec_device(device,unit,O_RDWR,NULL)))
7062 		     == NULL)
7063 			errx(1,"%s", cam_errbuf);
7064 	}
7065 #endif /* MINIMALISTIC */
7066 
7067 	/*
7068 	 * Reset optind to 2, and reset getopt, so these routines can parse
7069 	 * the arguments again.
7070 	 */
7071 	optind = optstart;
7072 	optreset = 1;
7073 
7074 	switch(cmdlist) {
7075 #ifndef MINIMALISTIC
7076 		case CAM_CMD_DEVLIST:
7077 			error = getdevlist(cam_dev);
7078 			break;
7079 #endif /* MINIMALISTIC */
7080 		case CAM_CMD_DEVTREE:
7081 			error = getdevtree();
7082 			break;
7083 #ifndef MINIMALISTIC
7084 		case CAM_CMD_TUR:
7085 			error = testunitready(cam_dev, retry_count, timeout, 0);
7086 			break;
7087 		case CAM_CMD_INQUIRY:
7088 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
7089 					      retry_count, timeout);
7090 			break;
7091 		case CAM_CMD_IDENTIFY:
7092 			error = ataidentify(cam_dev, retry_count, timeout);
7093 			break;
7094 		case CAM_CMD_STARTSTOP:
7095 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
7096 					  arglist & CAM_ARG_EJECT, retry_count,
7097 					  timeout);
7098 			break;
7099 #endif /* MINIMALISTIC */
7100 		case CAM_CMD_RESCAN:
7101 			error = dorescan_or_reset(argc, argv, 1);
7102 			break;
7103 		case CAM_CMD_RESET:
7104 			error = dorescan_or_reset(argc, argv, 0);
7105 			break;
7106 #ifndef MINIMALISTIC
7107 		case CAM_CMD_READ_DEFECTS:
7108 			error = readdefects(cam_dev, argc, argv, combinedopt,
7109 					    retry_count, timeout);
7110 			break;
7111 		case CAM_CMD_MODE_PAGE:
7112 			modepage(cam_dev, argc, argv, combinedopt,
7113 				 retry_count, timeout);
7114 			break;
7115 		case CAM_CMD_SCSI_CMD:
7116 			error = scsicmd(cam_dev, argc, argv, combinedopt,
7117 					retry_count, timeout);
7118 			break;
7119 		case CAM_CMD_SMP_CMD:
7120 			error = smpcmd(cam_dev, argc, argv, combinedopt,
7121 				       retry_count, timeout);
7122 			break;
7123 		case CAM_CMD_SMP_RG:
7124 			error = smpreportgeneral(cam_dev, argc, argv,
7125 						 combinedopt, retry_count,
7126 						 timeout);
7127 			break;
7128 		case CAM_CMD_SMP_PC:
7129 			error = smpphycontrol(cam_dev, argc, argv, combinedopt,
7130 					      retry_count, timeout);
7131 			break;
7132 		case CAM_CMD_SMP_PHYLIST:
7133 			error = smpphylist(cam_dev, argc, argv, combinedopt,
7134 					   retry_count, timeout);
7135 			break;
7136 		case CAM_CMD_SMP_MANINFO:
7137 			error = smpmaninfo(cam_dev, argc, argv, combinedopt,
7138 					   retry_count, timeout);
7139 			break;
7140 		case CAM_CMD_DEBUG:
7141 			error = camdebug(argc, argv, combinedopt);
7142 			break;
7143 		case CAM_CMD_TAG:
7144 			error = tagcontrol(cam_dev, argc, argv, combinedopt);
7145 			break;
7146 		case CAM_CMD_RATE:
7147 			error = ratecontrol(cam_dev, retry_count, timeout,
7148 					    argc, argv, combinedopt);
7149 			break;
7150 		case CAM_CMD_FORMAT:
7151 			error = scsiformat(cam_dev, argc, argv,
7152 					   combinedopt, retry_count, timeout);
7153 			break;
7154 		case CAM_CMD_REPORTLUNS:
7155 			error = scsireportluns(cam_dev, argc, argv,
7156 					       combinedopt, retry_count,
7157 					       timeout);
7158 			break;
7159 		case CAM_CMD_READCAP:
7160 			error = scsireadcapacity(cam_dev, argc, argv,
7161 						 combinedopt, retry_count,
7162 						 timeout);
7163 			break;
7164 		case CAM_CMD_IDLE:
7165 		case CAM_CMD_STANDBY:
7166 		case CAM_CMD_SLEEP:
7167 			error = atapm(cam_dev, argc, argv,
7168 				      combinedopt, retry_count, timeout);
7169 			break;
7170 		case CAM_CMD_SECURITY:
7171 			error = atasecurity(cam_dev, retry_count, timeout,
7172 					    argc, argv, combinedopt);
7173 			break;
7174 		case CAM_CMD_DOWNLOAD_FW:
7175 			error = fwdownload(cam_dev, argc, argv, combinedopt,
7176 			    arglist & CAM_ARG_VERBOSE, retry_count, timeout,
7177 			    get_disk_type(cam_dev));
7178 			break;
7179 #endif /* MINIMALISTIC */
7180 		case CAM_CMD_USAGE:
7181 			usage(1);
7182 			break;
7183 		default:
7184 			usage(0);
7185 			error = 1;
7186 			break;
7187 	}
7188 
7189 	if (cam_dev != NULL)
7190 		cam_close_device(cam_dev);
7191 
7192 	exit(error);
7193 }
7194