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