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