camcontrol.c revision 350774
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 350774 2019-08-08 18:48:48Z 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 : 1000,
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	default:
5197		*devtype = CC_DT_UNKNOWN;
5198		goto bailout;
5199		break; /*NOTREACHED*/
5200	}
5201
5202	/*
5203	 * Check for the ATA Information VPD page (0x89).  If this is an
5204	 * ATA device behind a SCSI to ATA translation layer, this VPD page
5205	 * should be present.
5206	 *
5207	 * If that VPD page isn't present, or we get an error back from the
5208	 * INQUIRY command, we'll just treat it as a normal SCSI device.
5209	 */
5210	retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5211				  timeout, verbosemode);
5212	if (retval == 1)
5213		*devtype = CC_DT_ATA_BEHIND_SCSI;
5214	else
5215		*devtype = CC_DT_SCSI;
5216
5217	retval = 0;
5218
5219bailout:
5220	return (retval);
5221}
5222
5223int
5224build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5225    uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5226    uint16_t sector_count, uint64_t lba, uint8_t command, uint32_t auxiliary,
5227    uint8_t *data_ptr, uint32_t dxfer_len, uint8_t *cdb_storage,
5228    size_t cdb_storage_len, uint8_t sense_len, uint32_t timeout,
5229    int is48bit, camcontrol_devtype devtype)
5230{
5231	int retval = 0;
5232
5233	if (devtype == CC_DT_ATA) {
5234		cam_fill_ataio(&ccb->ataio,
5235		    /*retries*/ retry_count,
5236		    /*cbfcnp*/ NULL,
5237		    /*flags*/ flags,
5238		    /*tag_action*/ tag_action,
5239		    /*data_ptr*/ data_ptr,
5240		    /*dxfer_len*/ dxfer_len,
5241		    /*timeout*/ timeout);
5242		if (is48bit || lba > ATA_MAX_28BIT_LBA)
5243			ata_48bit_cmd(&ccb->ataio, command, features, lba,
5244			    sector_count);
5245		else
5246			ata_28bit_cmd(&ccb->ataio, command, features, lba,
5247			    sector_count);
5248
5249		if (auxiliary != 0) {
5250			ccb->ataio.ata_flags |= ATA_FLAG_AUX;
5251			ccb->ataio.aux = auxiliary;
5252		}
5253
5254		if (ata_flags & AP_FLAG_CHK_COND)
5255			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
5256
5257		if ((protocol & AP_PROTO_MASK) == AP_PROTO_DMA)
5258			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
5259		else if ((protocol & AP_PROTO_MASK) == AP_PROTO_FPDMA)
5260			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
5261	} else {
5262		if (is48bit || lba > ATA_MAX_28BIT_LBA)
5263			protocol |= AP_EXTEND;
5264
5265		retval = scsi_ata_pass(&ccb->csio,
5266		    /*retries*/ retry_count,
5267		    /*cbfcnp*/ NULL,
5268		    /*flags*/ flags,
5269		    /*tag_action*/ tag_action,
5270		    /*protocol*/ protocol,
5271		    /*ata_flags*/ ata_flags,
5272		    /*features*/ features,
5273		    /*sector_count*/ sector_count,
5274		    /*lba*/ lba,
5275		    /*command*/ command,
5276		    /*device*/ 0,
5277		    /*icc*/ 0,
5278		    /*auxiliary*/ auxiliary,
5279		    /*control*/ 0,
5280		    /*data_ptr*/ data_ptr,
5281		    /*dxfer_len*/ dxfer_len,
5282		    /*cdb_storage*/ cdb_storage,
5283		    /*cdb_storage_len*/ cdb_storage_len,
5284		    /*minimum_cmd_size*/ 0,
5285		    /*sense_len*/ sense_len,
5286		    /*timeout*/ timeout);
5287	}
5288
5289	return (retval);
5290}
5291
5292int
5293get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
5294	       uint16_t *count, uint64_t *lba, uint8_t *device, uint8_t *status)
5295{
5296	int retval = 0;
5297
5298	switch (ccb->ccb_h.func_code) {
5299	case XPT_SCSI_IO: {
5300		uint8_t opcode;
5301		int error_code = 0, sense_key = 0, asc = 0, ascq = 0;
5302
5303		/*
5304		 * In this case, we have SCSI ATA PASS-THROUGH command, 12
5305		 * or 16 byte, and need to see what
5306		 */
5307		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
5308			opcode = ccb->csio.cdb_io.cdb_ptr[0];
5309		else
5310			opcode = ccb->csio.cdb_io.cdb_bytes[0];
5311		if ((opcode != ATA_PASS_12)
5312		 && (opcode != ATA_PASS_16)) {
5313			retval = 1;
5314			warnx("%s: unsupported opcode %02x", __func__, opcode);
5315			goto bailout;
5316		}
5317
5318		retval = scsi_extract_sense_ccb(ccb, &error_code, &sense_key,
5319						&asc, &ascq);
5320		/* Note: the _ccb() variant returns 0 for an error */
5321		if (retval == 0) {
5322			retval = 1;
5323			goto bailout;
5324		} else
5325			retval = 0;
5326
5327		switch (error_code) {
5328		case SSD_DESC_CURRENT_ERROR:
5329		case SSD_DESC_DEFERRED_ERROR: {
5330			struct scsi_sense_data_desc *sense;
5331			struct scsi_sense_ata_ret_desc *desc;
5332			uint8_t *desc_ptr;
5333
5334			sense = (struct scsi_sense_data_desc *)
5335			    &ccb->csio.sense_data;
5336
5337			desc_ptr = scsi_find_desc(sense, ccb->csio.sense_len -
5338			    ccb->csio.sense_resid, SSD_DESC_ATA);
5339			if (desc_ptr == NULL) {
5340				cam_error_print(dev, ccb, CAM_ESF_ALL,
5341				    CAM_EPF_ALL, stderr);
5342				retval = 1;
5343				goto bailout;
5344			}
5345			desc = (struct scsi_sense_ata_ret_desc *)desc_ptr;
5346
5347			*error = desc->error;
5348			*count = (desc->count_15_8 << 8) |
5349				  desc->count_7_0;
5350			*lba = ((uint64_t)desc->lba_47_40 << 40) |
5351			       ((uint64_t)desc->lba_39_32 << 32) |
5352			       ((uint64_t)desc->lba_31_24 << 24) |
5353			       (desc->lba_23_16 << 16) |
5354			       (desc->lba_15_8  <<  8) |
5355				desc->lba_7_0;
5356			*device = desc->device;
5357			*status = desc->status;
5358
5359			/*
5360			 * If the extend bit isn't set, the result is for a
5361			 * 12-byte ATA PASS-THROUGH command or a 16 or 32 byte
5362			 * command without the extend bit set.  This means
5363			 * that the device is supposed to return 28-bit
5364			 * status.  The count field is only 8 bits, and the
5365			 * LBA field is only 8 bits.
5366			 */
5367			if ((desc->flags & SSD_DESC_ATA_FLAG_EXTEND) == 0){
5368				*count &= 0xff;
5369				*lba &= 0x0fffffff;
5370			}
5371			break;
5372		}
5373		case SSD_CURRENT_ERROR:
5374		case SSD_DEFERRED_ERROR: {
5375#if 0
5376			struct scsi_sense_data_fixed *sense;
5377#endif
5378			/*
5379			 * XXX KDM need to support fixed sense data.
5380			 */
5381			warnx("%s: Fixed sense data not supported yet",
5382			    __func__);
5383			retval = 1;
5384			goto bailout;
5385			break; /*NOTREACHED*/
5386		}
5387		default:
5388			retval = 1;
5389			goto bailout;
5390			break;
5391		}
5392
5393		break;
5394	}
5395	case XPT_ATA_IO: {
5396		struct ata_res *res;
5397
5398		/*
5399		 * In this case, we have an ATA command, and we need to
5400		 * fill in the requested values from the result register
5401		 * set.
5402		 */
5403		res = &ccb->ataio.res;
5404		*error = res->error;
5405		*status = res->status;
5406		*device = res->device;
5407		*count = res->sector_count;
5408		*lba = (res->lba_high << 16) |
5409		       (res->lba_mid << 8) |
5410		       (res->lba_low);
5411		if (res->flags & CAM_ATAIO_48BIT) {
5412			*count |= (res->sector_count_exp << 8);
5413			*lba |= ((uint64_t)res->lba_low_exp << 24) |
5414				((uint64_t)res->lba_mid_exp << 32) |
5415				((uint64_t)res->lba_high_exp << 40);
5416		} else {
5417			*lba |= (res->device & 0xf) << 24;
5418		}
5419		break;
5420	}
5421	default:
5422		retval = 1;
5423		break;
5424	}
5425bailout:
5426	return (retval);
5427}
5428
5429static void
5430cpi_print(struct ccb_pathinq *cpi)
5431{
5432	char adapter_str[1024];
5433	uint64_t i;
5434
5435	snprintf(adapter_str, sizeof(adapter_str),
5436		 "%s%d:", cpi->dev_name, cpi->unit_number);
5437
5438	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5439		cpi->version_num);
5440
5441	for (i = 1; i < UINT8_MAX; i = i << 1) {
5442		const char *str;
5443
5444		if ((i & cpi->hba_inquiry) == 0)
5445			continue;
5446
5447		fprintf(stdout, "%s supports ", adapter_str);
5448
5449		switch(i) {
5450		case PI_MDP_ABLE:
5451			str = "MDP message";
5452			break;
5453		case PI_WIDE_32:
5454			str = "32 bit wide SCSI";
5455			break;
5456		case PI_WIDE_16:
5457			str = "16 bit wide SCSI";
5458			break;
5459		case PI_SDTR_ABLE:
5460			str = "SDTR message";
5461			break;
5462		case PI_LINKED_CDB:
5463			str = "linked CDBs";
5464			break;
5465		case PI_TAG_ABLE:
5466			str = "tag queue messages";
5467			break;
5468		case PI_SOFT_RST:
5469			str = "soft reset alternative";
5470			break;
5471		case PI_SATAPM:
5472			str = "SATA Port Multiplier";
5473			break;
5474		default:
5475			str = "unknown PI bit set";
5476			break;
5477		}
5478		fprintf(stdout, "%s\n", str);
5479	}
5480
5481	for (i = 1; i < UINT32_MAX; i = i << 1) {
5482		const char *str;
5483
5484		if ((i & cpi->hba_misc) == 0)
5485			continue;
5486
5487		fprintf(stdout, "%s ", adapter_str);
5488
5489		switch(i) {
5490		case PIM_ATA_EXT:
5491			str = "can understand ata_ext requests";
5492			break;
5493		case PIM_EXTLUNS:
5494			str = "64bit extended LUNs supported";
5495			break;
5496		case PIM_SCANHILO:
5497			str = "bus scans from high ID to low ID";
5498			break;
5499		case PIM_NOREMOVE:
5500			str = "removable devices not included in scan";
5501			break;
5502		case PIM_NOINITIATOR:
5503			str = "initiator role not supported";
5504			break;
5505		case PIM_NOBUSRESET:
5506			str = "user has disabled initial BUS RESET or"
5507			      " controller is in target/mixed mode";
5508			break;
5509		case PIM_NO_6_BYTE:
5510			str = "do not send 6-byte commands";
5511			break;
5512		case PIM_SEQSCAN:
5513			str = "scan bus sequentially";
5514			break;
5515		case PIM_UNMAPPED:
5516			str = "unmapped I/O supported";
5517			break;
5518		case PIM_NOSCAN:
5519			str = "does its own scanning";
5520			break;
5521		default:
5522			str = "unknown PIM bit set";
5523			break;
5524		}
5525		fprintf(stdout, "%s\n", str);
5526	}
5527
5528	for (i = 1; i < UINT16_MAX; i = i << 1) {
5529		const char *str;
5530
5531		if ((i & cpi->target_sprt) == 0)
5532			continue;
5533
5534		fprintf(stdout, "%s supports ", adapter_str);
5535		switch(i) {
5536		case PIT_PROCESSOR:
5537			str = "target mode processor mode";
5538			break;
5539		case PIT_PHASE:
5540			str = "target mode phase cog. mode";
5541			break;
5542		case PIT_DISCONNECT:
5543			str = "disconnects in target mode";
5544			break;
5545		case PIT_TERM_IO:
5546			str = "terminate I/O message in target mode";
5547			break;
5548		case PIT_GRP_6:
5549			str = "group 6 commands in target mode";
5550			break;
5551		case PIT_GRP_7:
5552			str = "group 7 commands in target mode";
5553			break;
5554		default:
5555			str = "unknown PIT bit set";
5556			break;
5557		}
5558
5559		fprintf(stdout, "%s\n", str);
5560	}
5561	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5562		cpi->hba_eng_cnt);
5563	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5564		cpi->max_target);
5565	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5566		cpi->max_lun);
5567	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5568		adapter_str, cpi->hpath_id);
5569	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5570		cpi->initiator_id);
5571	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5572	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5573	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5574	    adapter_str, cpi->hba_vendor);
5575	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5576	    adapter_str, cpi->hba_device);
5577	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5578	    adapter_str, cpi->hba_subvendor);
5579	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5580	    adapter_str, cpi->hba_subdevice);
5581	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5582	fprintf(stdout, "%s base transfer speed: ", adapter_str);
5583	if (cpi->base_transfer_speed > 1000)
5584		fprintf(stdout, "%d.%03dMB/sec\n",
5585			cpi->base_transfer_speed / 1000,
5586			cpi->base_transfer_speed % 1000);
5587	else
5588		fprintf(stdout, "%dKB/sec\n",
5589			(cpi->base_transfer_speed % 1000) * 1000);
5590	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5591	    adapter_str, cpi->maxio);
5592}
5593
5594static int
5595get_print_cts(struct cam_device *device, int user_settings, int quiet,
5596	      struct ccb_trans_settings *cts)
5597{
5598	int retval;
5599	union ccb *ccb;
5600
5601	retval = 0;
5602	ccb = cam_getccb(device);
5603
5604	if (ccb == NULL) {
5605		warnx("get_print_cts: error allocating ccb");
5606		return (1);
5607	}
5608
5609	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5610
5611	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5612
5613	if (user_settings == 0)
5614		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5615	else
5616		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5617
5618	if (cam_send_ccb(device, ccb) < 0) {
5619		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5620		if (arglist & CAM_ARG_VERBOSE)
5621			cam_error_print(device, ccb, CAM_ESF_ALL,
5622					CAM_EPF_ALL, stderr);
5623		retval = 1;
5624		goto get_print_cts_bailout;
5625	}
5626
5627	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5628		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5629		if (arglist & CAM_ARG_VERBOSE)
5630			cam_error_print(device, ccb, CAM_ESF_ALL,
5631					CAM_EPF_ALL, stderr);
5632		retval = 1;
5633		goto get_print_cts_bailout;
5634	}
5635
5636	if (quiet == 0)
5637		cts_print(device, &ccb->cts);
5638
5639	if (cts != NULL)
5640		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5641
5642get_print_cts_bailout:
5643
5644	cam_freeccb(ccb);
5645
5646	return (retval);
5647}
5648
5649static int
5650ratecontrol(struct cam_device *device, int task_attr, int retry_count,
5651	    int timeout, int argc, char **argv, char *combinedopt)
5652{
5653	int c;
5654	union ccb *ccb;
5655	int user_settings = 0;
5656	int retval = 0;
5657	int disc_enable = -1, tag_enable = -1;
5658	int mode = -1;
5659	int offset = -1;
5660	double syncrate = -1;
5661	int bus_width = -1;
5662	int quiet = 0;
5663	int change_settings = 0, send_tur = 0;
5664	struct ccb_pathinq cpi;
5665
5666	ccb = cam_getccb(device);
5667	if (ccb == NULL) {
5668		warnx("ratecontrol: error allocating ccb");
5669		return (1);
5670	}
5671	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5672		switch(c){
5673		case 'a':
5674			send_tur = 1;
5675			break;
5676		case 'c':
5677			user_settings = 0;
5678			break;
5679		case 'D':
5680			if (strncasecmp(optarg, "enable", 6) == 0)
5681				disc_enable = 1;
5682			else if (strncasecmp(optarg, "disable", 7) == 0)
5683				disc_enable = 0;
5684			else {
5685				warnx("-D argument \"%s\" is unknown", optarg);
5686				retval = 1;
5687				goto ratecontrol_bailout;
5688			}
5689			change_settings = 1;
5690			break;
5691		case 'M':
5692			mode = ata_string2mode(optarg);
5693			if (mode < 0) {
5694				warnx("unknown mode '%s'", optarg);
5695				retval = 1;
5696				goto ratecontrol_bailout;
5697			}
5698			change_settings = 1;
5699			break;
5700		case 'O':
5701			offset = strtol(optarg, NULL, 0);
5702			if (offset < 0) {
5703				warnx("offset value %d is < 0", offset);
5704				retval = 1;
5705				goto ratecontrol_bailout;
5706			}
5707			change_settings = 1;
5708			break;
5709		case 'q':
5710			quiet++;
5711			break;
5712		case 'R':
5713			syncrate = atof(optarg);
5714			if (syncrate < 0) {
5715				warnx("sync rate %f is < 0", syncrate);
5716				retval = 1;
5717				goto ratecontrol_bailout;
5718			}
5719			change_settings = 1;
5720			break;
5721		case 'T':
5722			if (strncasecmp(optarg, "enable", 6) == 0)
5723				tag_enable = 1;
5724			else if (strncasecmp(optarg, "disable", 7) == 0)
5725				tag_enable = 0;
5726			else {
5727				warnx("-T argument \"%s\" is unknown", optarg);
5728				retval = 1;
5729				goto ratecontrol_bailout;
5730			}
5731			change_settings = 1;
5732			break;
5733		case 'U':
5734			user_settings = 1;
5735			break;
5736		case 'W':
5737			bus_width = strtol(optarg, NULL, 0);
5738			if (bus_width < 0) {
5739				warnx("bus width %d is < 0", bus_width);
5740				retval = 1;
5741				goto ratecontrol_bailout;
5742			}
5743			change_settings = 1;
5744			break;
5745		default:
5746			break;
5747		}
5748	}
5749	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
5750	/*
5751	 * Grab path inquiry information, so we can determine whether
5752	 * or not the initiator is capable of the things that the user
5753	 * requests.
5754	 */
5755	ccb->ccb_h.func_code = XPT_PATH_INQ;
5756	if (cam_send_ccb(device, ccb) < 0) {
5757		perror("error sending XPT_PATH_INQ CCB");
5758		if (arglist & CAM_ARG_VERBOSE) {
5759			cam_error_print(device, ccb, CAM_ESF_ALL,
5760					CAM_EPF_ALL, stderr);
5761		}
5762		retval = 1;
5763		goto ratecontrol_bailout;
5764	}
5765	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5766		warnx("XPT_PATH_INQ CCB failed");
5767		if (arglist & CAM_ARG_VERBOSE) {
5768			cam_error_print(device, ccb, CAM_ESF_ALL,
5769					CAM_EPF_ALL, stderr);
5770		}
5771		retval = 1;
5772		goto ratecontrol_bailout;
5773	}
5774	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5775	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5776	if (quiet == 0) {
5777		fprintf(stdout, "%s parameters:\n",
5778		    user_settings ? "User" : "Current");
5779	}
5780	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5781	if (retval != 0)
5782		goto ratecontrol_bailout;
5783
5784	if (arglist & CAM_ARG_VERBOSE)
5785		cpi_print(&cpi);
5786
5787	if (change_settings) {
5788		int didsettings = 0;
5789		struct ccb_trans_settings_spi *spi = NULL;
5790		struct ccb_trans_settings_pata *pata = NULL;
5791		struct ccb_trans_settings_sata *sata = NULL;
5792		struct ccb_trans_settings_ata *ata = NULL;
5793		struct ccb_trans_settings_scsi *scsi = NULL;
5794
5795		if (ccb->cts.transport == XPORT_SPI)
5796			spi = &ccb->cts.xport_specific.spi;
5797		if (ccb->cts.transport == XPORT_ATA)
5798			pata = &ccb->cts.xport_specific.ata;
5799		if (ccb->cts.transport == XPORT_SATA)
5800			sata = &ccb->cts.xport_specific.sata;
5801		if (ccb->cts.protocol == PROTO_ATA)
5802			ata = &ccb->cts.proto_specific.ata;
5803		if (ccb->cts.protocol == PROTO_SCSI)
5804			scsi = &ccb->cts.proto_specific.scsi;
5805		ccb->cts.xport_specific.valid = 0;
5806		ccb->cts.proto_specific.valid = 0;
5807		if (spi && disc_enable != -1) {
5808			spi->valid |= CTS_SPI_VALID_DISC;
5809			if (disc_enable == 0)
5810				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5811			else
5812				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5813			didsettings++;
5814		}
5815		if (tag_enable != -1) {
5816			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5817				warnx("HBA does not support tagged queueing, "
5818				      "so you cannot modify tag settings");
5819				retval = 1;
5820				goto ratecontrol_bailout;
5821			}
5822			if (ata) {
5823				ata->valid |= CTS_SCSI_VALID_TQ;
5824				if (tag_enable == 0)
5825					ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5826				else
5827					ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5828				didsettings++;
5829			} else if (scsi) {
5830				scsi->valid |= CTS_SCSI_VALID_TQ;
5831				if (tag_enable == 0)
5832					scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5833				else
5834					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5835				didsettings++;
5836			}
5837		}
5838		if (spi && offset != -1) {
5839			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5840				warnx("HBA is not capable of changing offset");
5841				retval = 1;
5842				goto ratecontrol_bailout;
5843			}
5844			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5845			spi->sync_offset = offset;
5846			didsettings++;
5847		}
5848		if (spi && syncrate != -1) {
5849			int prelim_sync_period;
5850
5851			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5852				warnx("HBA is not capable of changing "
5853				      "transfer rates");
5854				retval = 1;
5855				goto ratecontrol_bailout;
5856			}
5857			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5858			/*
5859			 * The sync rate the user gives us is in MHz.
5860			 * We need to translate it into KHz for this
5861			 * calculation.
5862			 */
5863			syncrate *= 1000;
5864			/*
5865			 * Next, we calculate a "preliminary" sync period
5866			 * in tenths of a nanosecond.
5867			 */
5868			if (syncrate == 0)
5869				prelim_sync_period = 0;
5870			else
5871				prelim_sync_period = 10000000 / syncrate;
5872			spi->sync_period =
5873				scsi_calc_syncparam(prelim_sync_period);
5874			didsettings++;
5875		}
5876		if (sata && syncrate != -1) {
5877			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5878				warnx("HBA is not capable of changing "
5879				      "transfer rates");
5880				retval = 1;
5881				goto ratecontrol_bailout;
5882			}
5883			if  (!user_settings) {
5884				warnx("You can modify only user rate "
5885				    "settings for SATA");
5886				retval = 1;
5887				goto ratecontrol_bailout;
5888			}
5889			sata->revision = ata_speed2revision(syncrate * 100);
5890			if (sata->revision < 0) {
5891				warnx("Invalid rate %f", syncrate);
5892				retval = 1;
5893				goto ratecontrol_bailout;
5894			}
5895			sata->valid |= CTS_SATA_VALID_REVISION;
5896			didsettings++;
5897		}
5898		if ((pata || sata) && mode != -1) {
5899			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5900				warnx("HBA is not capable of changing "
5901				      "transfer rates");
5902				retval = 1;
5903				goto ratecontrol_bailout;
5904			}
5905			if  (!user_settings) {
5906				warnx("You can modify only user mode "
5907				    "settings for ATA/SATA");
5908				retval = 1;
5909				goto ratecontrol_bailout;
5910			}
5911			if (pata) {
5912				pata->mode = mode;
5913				pata->valid |= CTS_ATA_VALID_MODE;
5914			} else {
5915				sata->mode = mode;
5916				sata->valid |= CTS_SATA_VALID_MODE;
5917			}
5918			didsettings++;
5919		}
5920		/*
5921		 * The bus_width argument goes like this:
5922		 * 0 == 8 bit
5923		 * 1 == 16 bit
5924		 * 2 == 32 bit
5925		 * Therefore, if you shift the number of bits given on the
5926		 * command line right by 4, you should get the correct
5927		 * number.
5928		 */
5929		if (spi && bus_width != -1) {
5930			/*
5931			 * We might as well validate things here with a
5932			 * decipherable error message, rather than what
5933			 * will probably be an indecipherable error message
5934			 * by the time it gets back to us.
5935			 */
5936			if ((bus_width == 16)
5937			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5938				warnx("HBA does not support 16 bit bus width");
5939				retval = 1;
5940				goto ratecontrol_bailout;
5941			} else if ((bus_width == 32)
5942				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5943				warnx("HBA does not support 32 bit bus width");
5944				retval = 1;
5945				goto ratecontrol_bailout;
5946			} else if ((bus_width != 8)
5947				&& (bus_width != 16)
5948				&& (bus_width != 32)) {
5949				warnx("Invalid bus width %d", bus_width);
5950				retval = 1;
5951				goto ratecontrol_bailout;
5952			}
5953			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5954			spi->bus_width = bus_width >> 4;
5955			didsettings++;
5956		}
5957		if  (didsettings == 0) {
5958			goto ratecontrol_bailout;
5959		}
5960		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5961		if (cam_send_ccb(device, ccb) < 0) {
5962			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5963			if (arglist & CAM_ARG_VERBOSE) {
5964				cam_error_print(device, ccb, CAM_ESF_ALL,
5965						CAM_EPF_ALL, stderr);
5966			}
5967			retval = 1;
5968			goto ratecontrol_bailout;
5969		}
5970		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5971			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5972			if (arglist & CAM_ARG_VERBOSE) {
5973				cam_error_print(device, ccb, CAM_ESF_ALL,
5974						CAM_EPF_ALL, stderr);
5975			}
5976			retval = 1;
5977			goto ratecontrol_bailout;
5978		}
5979	}
5980	if (send_tur) {
5981		retval = testunitready(device, task_attr, retry_count, timeout,
5982				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5983		/*
5984		 * If the TUR didn't succeed, just bail.
5985		 */
5986		if (retval != 0) {
5987			if (quiet == 0)
5988				fprintf(stderr, "Test Unit Ready failed\n");
5989			goto ratecontrol_bailout;
5990		}
5991	}
5992	if ((change_settings || send_tur) && !quiet &&
5993	    (ccb->cts.transport == XPORT_ATA ||
5994	     ccb->cts.transport == XPORT_SATA || send_tur)) {
5995		fprintf(stdout, "New parameters:\n");
5996		retval = get_print_cts(device, user_settings, 0, NULL);
5997	}
5998
5999ratecontrol_bailout:
6000	cam_freeccb(ccb);
6001	return (retval);
6002}
6003
6004static int
6005scsiformat(struct cam_device *device, int argc, char **argv,
6006	   char *combinedopt, int task_attr, int retry_count, int timeout)
6007{
6008	union ccb *ccb;
6009	int c;
6010	int ycount = 0, quiet = 0;
6011	int error = 0, retval = 0;
6012	int use_timeout = 10800 * 1000;
6013	int immediate = 1;
6014	struct format_defect_list_header fh;
6015	u_int8_t *data_ptr = NULL;
6016	u_int32_t dxfer_len = 0;
6017	u_int8_t byte2 = 0;
6018	int num_warnings = 0;
6019	int reportonly = 0;
6020
6021	ccb = cam_getccb(device);
6022
6023	if (ccb == NULL) {
6024		warnx("scsiformat: error allocating ccb");
6025		return (1);
6026	}
6027
6028	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6029
6030	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6031		switch(c) {
6032		case 'q':
6033			quiet++;
6034			break;
6035		case 'r':
6036			reportonly = 1;
6037			break;
6038		case 'w':
6039			immediate = 0;
6040			break;
6041		case 'y':
6042			ycount++;
6043			break;
6044		}
6045	}
6046
6047	if (reportonly)
6048		goto doreport;
6049
6050	if (quiet == 0) {
6051		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6052			"following device:\n");
6053
6054		error = scsidoinquiry(device, argc, argv, combinedopt,
6055				      task_attr, retry_count, timeout);
6056
6057		if (error != 0) {
6058			warnx("scsiformat: error sending inquiry");
6059			goto scsiformat_bailout;
6060		}
6061	}
6062
6063	if (ycount == 0) {
6064		if (!get_confirmation()) {
6065			error = 1;
6066			goto scsiformat_bailout;
6067		}
6068	}
6069
6070	if (timeout != 0)
6071		use_timeout = timeout;
6072
6073	if (quiet == 0) {
6074		fprintf(stdout, "Current format timeout is %d seconds\n",
6075			use_timeout / 1000);
6076	}
6077
6078	/*
6079	 * If the user hasn't disabled questions and didn't specify a
6080	 * timeout on the command line, ask them if they want the current
6081	 * timeout.
6082	 */
6083	if ((ycount == 0)
6084	 && (timeout == 0)) {
6085		char str[1024];
6086		int new_timeout = 0;
6087
6088		fprintf(stdout, "Enter new timeout in seconds or press\n"
6089			"return to keep the current timeout [%d] ",
6090			use_timeout / 1000);
6091
6092		if (fgets(str, sizeof(str), stdin) != NULL) {
6093			if (str[0] != '\0')
6094				new_timeout = atoi(str);
6095		}
6096
6097		if (new_timeout != 0) {
6098			use_timeout = new_timeout * 1000;
6099			fprintf(stdout, "Using new timeout value %d\n",
6100				use_timeout / 1000);
6101		}
6102	}
6103
6104	/*
6105	 * Keep this outside the if block below to silence any unused
6106	 * variable warnings.
6107	 */
6108	bzero(&fh, sizeof(fh));
6109
6110	/*
6111	 * If we're in immediate mode, we've got to include the format
6112	 * header
6113	 */
6114	if (immediate != 0) {
6115		fh.byte2 = FU_DLH_IMMED;
6116		data_ptr = (u_int8_t *)&fh;
6117		dxfer_len = sizeof(fh);
6118		byte2 = FU_FMT_DATA;
6119	} else if (quiet == 0) {
6120		fprintf(stdout, "Formatting...");
6121		fflush(stdout);
6122	}
6123
6124	scsi_format_unit(&ccb->csio,
6125			 /* retries */ retry_count,
6126			 /* cbfcnp */ NULL,
6127			 /* tag_action */ task_attr,
6128			 /* byte2 */ byte2,
6129			 /* ileave */ 0,
6130			 /* data_ptr */ data_ptr,
6131			 /* dxfer_len */ dxfer_len,
6132			 /* sense_len */ SSD_FULL_SIZE,
6133			 /* timeout */ use_timeout);
6134
6135	/* Disable freezing the device queue */
6136	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6137
6138	if (arglist & CAM_ARG_ERR_RECOVER)
6139		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6140
6141	if (((retval = cam_send_ccb(device, ccb)) < 0)
6142	 || ((immediate == 0)
6143	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
6144		const char errstr[] = "error sending format command";
6145
6146		if (retval < 0)
6147			warn(errstr);
6148		else
6149			warnx(errstr);
6150
6151		if (arglist & CAM_ARG_VERBOSE) {
6152			cam_error_print(device, ccb, CAM_ESF_ALL,
6153					CAM_EPF_ALL, stderr);
6154		}
6155		error = 1;
6156		goto scsiformat_bailout;
6157	}
6158
6159	/*
6160	 * If we ran in non-immediate mode, we already checked for errors
6161	 * above and printed out any necessary information.  If we're in
6162	 * immediate mode, we need to loop through and get status
6163	 * information periodically.
6164	 */
6165	if (immediate == 0) {
6166		if (quiet == 0) {
6167			fprintf(stdout, "Format Complete\n");
6168		}
6169		goto scsiformat_bailout;
6170	}
6171
6172doreport:
6173	do {
6174		cam_status status;
6175
6176		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6177
6178		/*
6179		 * There's really no need to do error recovery or
6180		 * retries here, since we're just going to sit in a
6181		 * loop and wait for the device to finish formatting.
6182		 */
6183		scsi_test_unit_ready(&ccb->csio,
6184				     /* retries */ 0,
6185				     /* cbfcnp */ NULL,
6186				     /* tag_action */ task_attr,
6187				     /* sense_len */ SSD_FULL_SIZE,
6188				     /* timeout */ 5000);
6189
6190		/* Disable freezing the device queue */
6191		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6192
6193		retval = cam_send_ccb(device, ccb);
6194
6195		/*
6196		 * If we get an error from the ioctl, bail out.  SCSI
6197		 * errors are expected.
6198		 */
6199		if (retval < 0) {
6200			warn("error sending CAMIOCOMMAND ioctl");
6201			if (arglist & CAM_ARG_VERBOSE) {
6202				cam_error_print(device, ccb, CAM_ESF_ALL,
6203						CAM_EPF_ALL, stderr);
6204			}
6205			error = 1;
6206			goto scsiformat_bailout;
6207		}
6208
6209		status = ccb->ccb_h.status & CAM_STATUS_MASK;
6210
6211		if ((status != CAM_REQ_CMP)
6212		 && (status == CAM_SCSI_STATUS_ERROR)
6213		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6214			struct scsi_sense_data *sense;
6215			int error_code, sense_key, asc, ascq;
6216
6217			sense = &ccb->csio.sense_data;
6218			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6219			    ccb->csio.sense_resid, &error_code, &sense_key,
6220			    &asc, &ascq, /*show_errors*/ 1);
6221
6222			/*
6223			 * According to the SCSI-2 and SCSI-3 specs, a
6224			 * drive that is in the middle of a format should
6225			 * return NOT READY with an ASC of "logical unit
6226			 * not ready, format in progress".  The sense key
6227			 * specific bytes will then be a progress indicator.
6228			 */
6229			if ((sense_key == SSD_KEY_NOT_READY)
6230			 && (asc == 0x04) && (ascq == 0x04)) {
6231				uint8_t sks[3];
6232
6233				if ((scsi_get_sks(sense, ccb->csio.sense_len -
6234				     ccb->csio.sense_resid, sks) == 0)
6235				 && (quiet == 0)) {
6236					uint32_t val;
6237					u_int64_t percentage;
6238
6239					val = scsi_2btoul(&sks[1]);
6240					percentage = 10000ull * val;
6241
6242					fprintf(stdout,
6243						"\rFormatting:  %ju.%02u %% "
6244						"(%u/%d) done",
6245						(uintmax_t)(percentage /
6246						(0x10000 * 100)),
6247						(unsigned)((percentage /
6248						0x10000) % 100),
6249						val, 0x10000);
6250					fflush(stdout);
6251				} else if ((quiet == 0)
6252					&& (++num_warnings <= 1)) {
6253					warnx("Unexpected SCSI Sense Key "
6254					      "Specific value returned "
6255					      "during format:");
6256					scsi_sense_print(device, &ccb->csio,
6257							 stderr);
6258					warnx("Unable to print status "
6259					      "information, but format will "
6260					      "proceed.");
6261					warnx("will exit when format is "
6262					      "complete");
6263				}
6264				sleep(1);
6265			} else {
6266				warnx("Unexpected SCSI error during format");
6267				cam_error_print(device, ccb, CAM_ESF_ALL,
6268						CAM_EPF_ALL, stderr);
6269				error = 1;
6270				goto scsiformat_bailout;
6271			}
6272
6273		} else if (status != CAM_REQ_CMP) {
6274			warnx("Unexpected CAM status %#x", status);
6275			if (arglist & CAM_ARG_VERBOSE)
6276				cam_error_print(device, ccb, CAM_ESF_ALL,
6277						CAM_EPF_ALL, stderr);
6278			error = 1;
6279			goto scsiformat_bailout;
6280		}
6281
6282	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6283
6284	if (quiet == 0)
6285		fprintf(stdout, "\nFormat Complete\n");
6286
6287scsiformat_bailout:
6288
6289	cam_freeccb(ccb);
6290
6291	return (error);
6292}
6293
6294static int
6295scsisanitize(struct cam_device *device, int argc, char **argv,
6296	     char *combinedopt, int task_attr, int retry_count, int timeout)
6297{
6298	union ccb *ccb;
6299	u_int8_t action = 0;
6300	int c;
6301	int ycount = 0, quiet = 0;
6302	int error = 0, retval = 0;
6303	int use_timeout = 10800 * 1000;
6304	int immediate = 1;
6305	int invert = 0;
6306	int passes = 0;
6307	int ause = 0;
6308	int fd = -1;
6309	const char *pattern = NULL;
6310	u_int8_t *data_ptr = NULL;
6311	u_int32_t dxfer_len = 0;
6312	u_int8_t byte2 = 0;
6313	int num_warnings = 0;
6314	int reportonly = 0;
6315
6316	ccb = cam_getccb(device);
6317
6318	if (ccb == NULL) {
6319		warnx("scsisanitize: error allocating ccb");
6320		return (1);
6321	}
6322
6323	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6324
6325	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6326		switch(c) {
6327		case 'a':
6328			if (strcasecmp(optarg, "overwrite") == 0)
6329				action = SSZ_SERVICE_ACTION_OVERWRITE;
6330			else if (strcasecmp(optarg, "block") == 0)
6331				action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6332			else if (strcasecmp(optarg, "crypto") == 0)
6333				action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6334			else if (strcasecmp(optarg, "exitfailure") == 0)
6335				action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6336			else {
6337				warnx("invalid service operation \"%s\"",
6338				      optarg);
6339				error = 1;
6340				goto scsisanitize_bailout;
6341			}
6342			break;
6343		case 'c':
6344			passes = strtol(optarg, NULL, 0);
6345			if (passes < 1 || passes > 31) {
6346				warnx("invalid passes value %d", passes);
6347				error = 1;
6348				goto scsisanitize_bailout;
6349			}
6350			break;
6351		case 'I':
6352			invert = 1;
6353			break;
6354		case 'P':
6355			pattern = optarg;
6356			break;
6357		case 'q':
6358			quiet++;
6359			break;
6360		case 'U':
6361			ause = 1;
6362			break;
6363		case 'r':
6364			reportonly = 1;
6365			break;
6366		case 'w':
6367			immediate = 0;
6368			break;
6369		case 'y':
6370			ycount++;
6371			break;
6372		}
6373	}
6374
6375	if (reportonly)
6376		goto doreport;
6377
6378	if (action == 0) {
6379		warnx("an action is required");
6380		error = 1;
6381		goto scsisanitize_bailout;
6382	} else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6383		struct scsi_sanitize_parameter_list *pl;
6384		struct stat sb;
6385		ssize_t sz, amt;
6386
6387		if (pattern == NULL) {
6388			warnx("overwrite action requires -P argument");
6389			error = 1;
6390			goto scsisanitize_bailout;
6391		}
6392		fd = open(pattern, O_RDONLY);
6393		if (fd < 0) {
6394			warn("cannot open pattern file %s", pattern);
6395			error = 1;
6396			goto scsisanitize_bailout;
6397		}
6398		if (fstat(fd, &sb) < 0) {
6399			warn("cannot stat pattern file %s", pattern);
6400			error = 1;
6401			goto scsisanitize_bailout;
6402		}
6403		sz = sb.st_size;
6404		if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6405			warnx("pattern file size exceeds maximum value %d",
6406			      SSZPL_MAX_PATTERN_LENGTH);
6407			error = 1;
6408			goto scsisanitize_bailout;
6409		}
6410		dxfer_len = sizeof(*pl) + sz;
6411		data_ptr = calloc(1, dxfer_len);
6412		if (data_ptr == NULL) {
6413			warnx("cannot allocate parameter list buffer");
6414			error = 1;
6415			goto scsisanitize_bailout;
6416		}
6417
6418		amt = read(fd, data_ptr + sizeof(*pl), sz);
6419		if (amt < 0) {
6420			warn("cannot read pattern file");
6421			error = 1;
6422			goto scsisanitize_bailout;
6423		} else if (amt != sz) {
6424			warnx("short pattern file read");
6425			error = 1;
6426			goto scsisanitize_bailout;
6427		}
6428
6429		pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6430		if (passes == 0)
6431			pl->byte1 = 1;
6432		else
6433			pl->byte1 = passes;
6434		if (invert != 0)
6435			pl->byte1 |= SSZPL_INVERT;
6436		scsi_ulto2b(sz, pl->length);
6437	} else {
6438		const char *arg;
6439
6440		if (passes != 0)
6441			arg = "-c";
6442		else if (invert != 0)
6443			arg = "-I";
6444		else if (pattern != NULL)
6445			arg = "-P";
6446		else
6447			arg = NULL;
6448		if (arg != NULL) {
6449			warnx("%s argument only valid with overwrite "
6450			      "operation", arg);
6451			error = 1;
6452			goto scsisanitize_bailout;
6453		}
6454	}
6455
6456	if (quiet == 0) {
6457		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6458			"following device:\n");
6459
6460		error = scsidoinquiry(device, argc, argv, combinedopt,
6461				      task_attr, retry_count, timeout);
6462
6463		if (error != 0) {
6464			warnx("scsisanitize: error sending inquiry");
6465			goto scsisanitize_bailout;
6466		}
6467	}
6468
6469	if (ycount == 0) {
6470		if (!get_confirmation()) {
6471			error = 1;
6472			goto scsisanitize_bailout;
6473		}
6474	}
6475
6476	if (timeout != 0)
6477		use_timeout = timeout;
6478
6479	if (quiet == 0) {
6480		fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6481			use_timeout / 1000);
6482	}
6483
6484	/*
6485	 * If the user hasn't disabled questions and didn't specify a
6486	 * timeout on the command line, ask them if they want the current
6487	 * timeout.
6488	 */
6489	if ((ycount == 0)
6490	 && (timeout == 0)) {
6491		char str[1024];
6492		int new_timeout = 0;
6493
6494		fprintf(stdout, "Enter new timeout in seconds or press\n"
6495			"return to keep the current timeout [%d] ",
6496			use_timeout / 1000);
6497
6498		if (fgets(str, sizeof(str), stdin) != NULL) {
6499			if (str[0] != '\0')
6500				new_timeout = atoi(str);
6501		}
6502
6503		if (new_timeout != 0) {
6504			use_timeout = new_timeout * 1000;
6505			fprintf(stdout, "Using new timeout value %d\n",
6506				use_timeout / 1000);
6507		}
6508	}
6509
6510	byte2 = action;
6511	if (ause != 0)
6512		byte2 |= SSZ_UNRESTRICTED_EXIT;
6513	if (immediate != 0)
6514		byte2 |= SSZ_IMMED;
6515
6516	scsi_sanitize(&ccb->csio,
6517		      /* retries */ retry_count,
6518		      /* cbfcnp */ NULL,
6519		      /* tag_action */ task_attr,
6520		      /* byte2 */ byte2,
6521		      /* control */ 0,
6522		      /* data_ptr */ data_ptr,
6523		      /* dxfer_len */ dxfer_len,
6524		      /* sense_len */ SSD_FULL_SIZE,
6525		      /* timeout */ use_timeout);
6526
6527	/* Disable freezing the device queue */
6528	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6529
6530	if (arglist & CAM_ARG_ERR_RECOVER)
6531		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6532
6533	if (cam_send_ccb(device, ccb) < 0) {
6534		warn("error sending sanitize command");
6535		error = 1;
6536		goto scsisanitize_bailout;
6537	}
6538
6539	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6540		struct scsi_sense_data *sense;
6541		int error_code, sense_key, asc, ascq;
6542
6543		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6544		    CAM_SCSI_STATUS_ERROR) {
6545			sense = &ccb->csio.sense_data;
6546			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6547			    ccb->csio.sense_resid, &error_code, &sense_key,
6548			    &asc, &ascq, /*show_errors*/ 1);
6549
6550			if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6551			    asc == 0x20 && ascq == 0x00)
6552				warnx("sanitize is not supported by "
6553				      "this device");
6554			else
6555				warnx("error sanitizing this device");
6556		} else
6557			warnx("error sanitizing this device");
6558
6559		if (arglist & CAM_ARG_VERBOSE) {
6560			cam_error_print(device, ccb, CAM_ESF_ALL,
6561					CAM_EPF_ALL, stderr);
6562		}
6563		error = 1;
6564		goto scsisanitize_bailout;
6565	}
6566
6567	/*
6568	 * If we ran in non-immediate mode, we already checked for errors
6569	 * above and printed out any necessary information.  If we're in
6570	 * immediate mode, we need to loop through and get status
6571	 * information periodically.
6572	 */
6573	if (immediate == 0) {
6574		if (quiet == 0) {
6575			fprintf(stdout, "Sanitize Complete\n");
6576		}
6577		goto scsisanitize_bailout;
6578	}
6579
6580doreport:
6581	do {
6582		cam_status status;
6583
6584		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6585
6586		/*
6587		 * There's really no need to do error recovery or
6588		 * retries here, since we're just going to sit in a
6589		 * loop and wait for the device to finish sanitizing.
6590		 */
6591		scsi_test_unit_ready(&ccb->csio,
6592				     /* retries */ 0,
6593				     /* cbfcnp */ NULL,
6594				     /* tag_action */ task_attr,
6595				     /* sense_len */ SSD_FULL_SIZE,
6596				     /* timeout */ 5000);
6597
6598		/* Disable freezing the device queue */
6599		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6600
6601		retval = cam_send_ccb(device, ccb);
6602
6603		/*
6604		 * If we get an error from the ioctl, bail out.  SCSI
6605		 * errors are expected.
6606		 */
6607		if (retval < 0) {
6608			warn("error sending CAMIOCOMMAND ioctl");
6609			if (arglist & CAM_ARG_VERBOSE) {
6610				cam_error_print(device, ccb, CAM_ESF_ALL,
6611						CAM_EPF_ALL, stderr);
6612			}
6613			error = 1;
6614			goto scsisanitize_bailout;
6615		}
6616
6617		status = ccb->ccb_h.status & CAM_STATUS_MASK;
6618
6619		if ((status != CAM_REQ_CMP)
6620		 && (status == CAM_SCSI_STATUS_ERROR)
6621		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6622			struct scsi_sense_data *sense;
6623			int error_code, sense_key, asc, ascq;
6624
6625			sense = &ccb->csio.sense_data;
6626			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6627			    ccb->csio.sense_resid, &error_code, &sense_key,
6628			    &asc, &ascq, /*show_errors*/ 1);
6629
6630			/*
6631			 * According to the SCSI-3 spec, a drive that is in the
6632			 * middle of a sanitize should return NOT READY with an
6633			 * ASC of "logical unit not ready, sanitize in
6634			 * progress". The sense key specific bytes will then
6635			 * be a progress indicator.
6636			 */
6637			if ((sense_key == SSD_KEY_NOT_READY)
6638			 && (asc == 0x04) && (ascq == 0x1b)) {
6639				uint8_t sks[3];
6640
6641				if ((scsi_get_sks(sense, ccb->csio.sense_len -
6642				     ccb->csio.sense_resid, sks) == 0)
6643				 && (quiet == 0)) {
6644					int val;
6645					u_int64_t percentage;
6646
6647					val = scsi_2btoul(&sks[1]);
6648					percentage = 10000 * val;
6649
6650					fprintf(stdout,
6651						"\rSanitizing:  %ju.%02u %% "
6652						"(%d/%d) done",
6653						(uintmax_t)(percentage /
6654						(0x10000 * 100)),
6655						(unsigned)((percentage /
6656						0x10000) % 100),
6657						val, 0x10000);
6658					fflush(stdout);
6659				} else if ((quiet == 0)
6660					&& (++num_warnings <= 1)) {
6661					warnx("Unexpected SCSI Sense Key "
6662					      "Specific value returned "
6663					      "during sanitize:");
6664					scsi_sense_print(device, &ccb->csio,
6665							 stderr);
6666					warnx("Unable to print status "
6667					      "information, but sanitze will "
6668					      "proceed.");
6669					warnx("will exit when sanitize is "
6670					      "complete");
6671				}
6672				sleep(1);
6673			} else {
6674				warnx("Unexpected SCSI error during sanitize");
6675				cam_error_print(device, ccb, CAM_ESF_ALL,
6676						CAM_EPF_ALL, stderr);
6677				error = 1;
6678				goto scsisanitize_bailout;
6679			}
6680
6681		} else if (status != CAM_REQ_CMP) {
6682			warnx("Unexpected CAM status %#x", status);
6683			if (arglist & CAM_ARG_VERBOSE)
6684				cam_error_print(device, ccb, CAM_ESF_ALL,
6685						CAM_EPF_ALL, stderr);
6686			error = 1;
6687			goto scsisanitize_bailout;
6688		}
6689	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6690
6691	if (quiet == 0)
6692		fprintf(stdout, "\nSanitize Complete\n");
6693
6694scsisanitize_bailout:
6695	if (fd >= 0)
6696		close(fd);
6697	if (data_ptr != NULL)
6698		free(data_ptr);
6699	cam_freeccb(ccb);
6700
6701	return (error);
6702}
6703
6704static int
6705scsireportluns(struct cam_device *device, int argc, char **argv,
6706	       char *combinedopt, int task_attr, int retry_count, int timeout)
6707{
6708	union ccb *ccb;
6709	int c, countonly, lunsonly;
6710	struct scsi_report_luns_data *lundata;
6711	int alloc_len;
6712	uint8_t report_type;
6713	uint32_t list_len, i, j;
6714	int retval;
6715
6716	retval = 0;
6717	lundata = NULL;
6718	report_type = RPL_REPORT_DEFAULT;
6719	ccb = cam_getccb(device);
6720
6721	if (ccb == NULL) {
6722		warnx("%s: error allocating ccb", __func__);
6723		return (1);
6724	}
6725
6726	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6727
6728	countonly = 0;
6729	lunsonly = 0;
6730
6731	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6732		switch (c) {
6733		case 'c':
6734			countonly++;
6735			break;
6736		case 'l':
6737			lunsonly++;
6738			break;
6739		case 'r':
6740			if (strcasecmp(optarg, "default") == 0)
6741				report_type = RPL_REPORT_DEFAULT;
6742			else if (strcasecmp(optarg, "wellknown") == 0)
6743				report_type = RPL_REPORT_WELLKNOWN;
6744			else if (strcasecmp(optarg, "all") == 0)
6745				report_type = RPL_REPORT_ALL;
6746			else {
6747				warnx("%s: invalid report type \"%s\"",
6748				      __func__, optarg);
6749				retval = 1;
6750				goto bailout;
6751			}
6752			break;
6753		default:
6754			break;
6755		}
6756	}
6757
6758	if ((countonly != 0)
6759	 && (lunsonly != 0)) {
6760		warnx("%s: you can only specify one of -c or -l", __func__);
6761		retval = 1;
6762		goto bailout;
6763	}
6764	/*
6765	 * According to SPC-4, the allocation length must be at least 16
6766	 * bytes -- enough for the header and one LUN.
6767	 */
6768	alloc_len = sizeof(*lundata) + 8;
6769
6770retry:
6771
6772	lundata = malloc(alloc_len);
6773
6774	if (lundata == NULL) {
6775		warn("%s: error mallocing %d bytes", __func__, alloc_len);
6776		retval = 1;
6777		goto bailout;
6778	}
6779
6780	scsi_report_luns(&ccb->csio,
6781			 /*retries*/ retry_count,
6782			 /*cbfcnp*/ NULL,
6783			 /*tag_action*/ task_attr,
6784			 /*select_report*/ report_type,
6785			 /*rpl_buf*/ lundata,
6786			 /*alloc_len*/ alloc_len,
6787			 /*sense_len*/ SSD_FULL_SIZE,
6788			 /*timeout*/ timeout ? timeout : 5000);
6789
6790	/* Disable freezing the device queue */
6791	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6792
6793	if (arglist & CAM_ARG_ERR_RECOVER)
6794		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6795
6796	if (cam_send_ccb(device, ccb) < 0) {
6797		warn("error sending REPORT LUNS command");
6798
6799		if (arglist & CAM_ARG_VERBOSE)
6800			cam_error_print(device, ccb, CAM_ESF_ALL,
6801					CAM_EPF_ALL, stderr);
6802
6803		retval = 1;
6804		goto bailout;
6805	}
6806
6807	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6808		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6809		retval = 1;
6810		goto bailout;
6811	}
6812
6813
6814	list_len = scsi_4btoul(lundata->length);
6815
6816	/*
6817	 * If we need to list the LUNs, and our allocation
6818	 * length was too short, reallocate and retry.
6819	 */
6820	if ((countonly == 0)
6821	 && (list_len > (alloc_len - sizeof(*lundata)))) {
6822		alloc_len = list_len + sizeof(*lundata);
6823		free(lundata);
6824		goto retry;
6825	}
6826
6827	if (lunsonly == 0)
6828		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6829			((list_len / 8) > 1) ? "s" : "");
6830
6831	if (countonly != 0)
6832		goto bailout;
6833
6834	for (i = 0; i < (list_len / 8); i++) {
6835		int no_more;
6836
6837		no_more = 0;
6838		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6839			if (j != 0)
6840				fprintf(stdout, ",");
6841			switch (lundata->luns[i].lundata[j] &
6842				RPL_LUNDATA_ATYP_MASK) {
6843			case RPL_LUNDATA_ATYP_PERIPH:
6844				if ((lundata->luns[i].lundata[j] &
6845				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6846					fprintf(stdout, "%d:",
6847						lundata->luns[i].lundata[j] &
6848						RPL_LUNDATA_PERIPH_BUS_MASK);
6849				else if ((j == 0)
6850				      && ((lundata->luns[i].lundata[j+2] &
6851					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6852					no_more = 1;
6853
6854				fprintf(stdout, "%d",
6855					lundata->luns[i].lundata[j+1]);
6856				break;
6857			case RPL_LUNDATA_ATYP_FLAT: {
6858				uint8_t tmplun[2];
6859				tmplun[0] = lundata->luns[i].lundata[j] &
6860					RPL_LUNDATA_FLAT_LUN_MASK;
6861				tmplun[1] = lundata->luns[i].lundata[j+1];
6862
6863				fprintf(stdout, "%d", scsi_2btoul(tmplun));
6864				no_more = 1;
6865				break;
6866			}
6867			case RPL_LUNDATA_ATYP_LUN:
6868				fprintf(stdout, "%d:%d:%d",
6869					(lundata->luns[i].lundata[j+1] &
6870					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6871					lundata->luns[i].lundata[j] &
6872					RPL_LUNDATA_LUN_TARG_MASK,
6873					lundata->luns[i].lundata[j+1] &
6874					RPL_LUNDATA_LUN_LUN_MASK);
6875				break;
6876			case RPL_LUNDATA_ATYP_EXTLUN: {
6877				int field_len_code, eam_code;
6878
6879				eam_code = lundata->luns[i].lundata[j] &
6880					RPL_LUNDATA_EXT_EAM_MASK;
6881				field_len_code = (lundata->luns[i].lundata[j] &
6882					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6883
6884				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6885				 && (field_len_code == 0x00)) {
6886					fprintf(stdout, "%d",
6887						lundata->luns[i].lundata[j+1]);
6888				} else if ((eam_code ==
6889					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6890					&& (field_len_code == 0x03)) {
6891					uint8_t tmp_lun[8];
6892
6893					/*
6894					 * This format takes up all 8 bytes.
6895					 * If we aren't starting at offset 0,
6896					 * that's a bug.
6897					 */
6898					if (j != 0) {
6899						fprintf(stdout, "Invalid "
6900							"offset %d for "
6901							"Extended LUN not "
6902							"specified format", j);
6903						no_more = 1;
6904						break;
6905					}
6906					bzero(tmp_lun, sizeof(tmp_lun));
6907					bcopy(&lundata->luns[i].lundata[j+1],
6908					      &tmp_lun[1], sizeof(tmp_lun) - 1);
6909					fprintf(stdout, "%#jx",
6910					       (intmax_t)scsi_8btou64(tmp_lun));
6911					no_more = 1;
6912				} else {
6913					fprintf(stderr, "Unknown Extended LUN"
6914						"Address method %#x, length "
6915						"code %#x", eam_code,
6916						field_len_code);
6917					no_more = 1;
6918				}
6919				break;
6920			}
6921			default:
6922				fprintf(stderr, "Unknown LUN address method "
6923					"%#x\n", lundata->luns[i].lundata[0] &
6924					RPL_LUNDATA_ATYP_MASK);
6925				break;
6926			}
6927			/*
6928			 * For the flat addressing method, there are no
6929			 * other levels after it.
6930			 */
6931			if (no_more != 0)
6932				break;
6933		}
6934		fprintf(stdout, "\n");
6935	}
6936
6937bailout:
6938
6939	cam_freeccb(ccb);
6940
6941	free(lundata);
6942
6943	return (retval);
6944}
6945
6946static int
6947scsireadcapacity(struct cam_device *device, int argc, char **argv,
6948		 char *combinedopt, int task_attr, int retry_count, int timeout)
6949{
6950	union ccb *ccb;
6951	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten, longonly;
6952	struct scsi_read_capacity_data rcap;
6953	struct scsi_read_capacity_data_long rcaplong;
6954	uint64_t maxsector;
6955	uint32_t block_len;
6956	int retval;
6957	int c;
6958
6959	blocksizeonly = 0;
6960	humanize = 0;
6961	longonly = 0;
6962	numblocks = 0;
6963	quiet = 0;
6964	sizeonly = 0;
6965	baseten = 0;
6966	retval = 0;
6967
6968	ccb = cam_getccb(device);
6969
6970	if (ccb == NULL) {
6971		warnx("%s: error allocating ccb", __func__);
6972		return (1);
6973	}
6974
6975	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6976
6977	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6978		switch (c) {
6979		case 'b':
6980			blocksizeonly++;
6981			break;
6982		case 'h':
6983			humanize++;
6984			baseten = 0;
6985			break;
6986		case 'H':
6987			humanize++;
6988			baseten++;
6989			break;
6990		case 'l':
6991			longonly++;
6992			break;
6993		case 'N':
6994			numblocks++;
6995			break;
6996		case 'q':
6997			quiet++;
6998			break;
6999		case 's':
7000			sizeonly++;
7001			break;
7002		default:
7003			break;
7004		}
7005	}
7006
7007	if ((blocksizeonly != 0)
7008	 && (numblocks != 0)) {
7009		warnx("%s: you can only specify one of -b or -N", __func__);
7010		retval = 1;
7011		goto bailout;
7012	}
7013
7014	if ((blocksizeonly != 0)
7015	 && (sizeonly != 0)) {
7016		warnx("%s: you can only specify one of -b or -s", __func__);
7017		retval = 1;
7018		goto bailout;
7019	}
7020
7021	if ((humanize != 0)
7022	 && (quiet != 0)) {
7023		warnx("%s: you can only specify one of -h/-H or -q", __func__);
7024		retval = 1;
7025		goto bailout;
7026	}
7027
7028	if ((humanize != 0)
7029	 && (blocksizeonly != 0)) {
7030		warnx("%s: you can only specify one of -h/-H or -b", __func__);
7031		retval = 1;
7032		goto bailout;
7033	}
7034
7035	if (longonly != 0)
7036		goto long_only;
7037
7038	scsi_read_capacity(&ccb->csio,
7039			   /*retries*/ retry_count,
7040			   /*cbfcnp*/ NULL,
7041			   /*tag_action*/ task_attr,
7042			   &rcap,
7043			   SSD_FULL_SIZE,
7044			   /*timeout*/ timeout ? timeout : 5000);
7045
7046	/* Disable freezing the device queue */
7047	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7048
7049	if (arglist & CAM_ARG_ERR_RECOVER)
7050		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7051
7052	if (cam_send_ccb(device, ccb) < 0) {
7053		warn("error sending READ CAPACITY command");
7054
7055		if (arglist & CAM_ARG_VERBOSE)
7056			cam_error_print(device, ccb, CAM_ESF_ALL,
7057					CAM_EPF_ALL, stderr);
7058
7059		retval = 1;
7060		goto bailout;
7061	}
7062
7063	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7064		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7065		retval = 1;
7066		goto bailout;
7067	}
7068
7069	maxsector = scsi_4btoul(rcap.addr);
7070	block_len = scsi_4btoul(rcap.length);
7071
7072	/*
7073	 * A last block of 2^32-1 means that the true capacity is over 2TB,
7074	 * and we need to issue the long READ CAPACITY to get the real
7075	 * capacity.  Otherwise, we're all set.
7076	 */
7077	if (maxsector != 0xffffffff)
7078		goto do_print;
7079
7080long_only:
7081	scsi_read_capacity_16(&ccb->csio,
7082			      /*retries*/ retry_count,
7083			      /*cbfcnp*/ NULL,
7084			      /*tag_action*/ task_attr,
7085			      /*lba*/ 0,
7086			      /*reladdr*/ 0,
7087			      /*pmi*/ 0,
7088			      /*rcap_buf*/ (uint8_t *)&rcaplong,
7089			      /*rcap_buf_len*/ sizeof(rcaplong),
7090			      /*sense_len*/ SSD_FULL_SIZE,
7091			      /*timeout*/ timeout ? timeout : 5000);
7092
7093	/* Disable freezing the device queue */
7094	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7095
7096	if (arglist & CAM_ARG_ERR_RECOVER)
7097		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7098
7099	if (cam_send_ccb(device, ccb) < 0) {
7100		warn("error sending READ CAPACITY (16) command");
7101
7102		if (arglist & CAM_ARG_VERBOSE)
7103			cam_error_print(device, ccb, CAM_ESF_ALL,
7104					CAM_EPF_ALL, stderr);
7105
7106		retval = 1;
7107		goto bailout;
7108	}
7109
7110	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7111		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7112		retval = 1;
7113		goto bailout;
7114	}
7115
7116	maxsector = scsi_8btou64(rcaplong.addr);
7117	block_len = scsi_4btoul(rcaplong.length);
7118
7119do_print:
7120	if (blocksizeonly == 0) {
7121		/*
7122		 * Humanize implies !quiet, and also implies numblocks.
7123		 */
7124		if (humanize != 0) {
7125			char tmpstr[6];
7126			int64_t tmpbytes;
7127			int ret;
7128
7129			tmpbytes = (maxsector + 1) * block_len;
7130			ret = humanize_number(tmpstr, sizeof(tmpstr),
7131					      tmpbytes, "", HN_AUTOSCALE,
7132					      HN_B | HN_DECIMAL |
7133					      ((baseten != 0) ?
7134					      HN_DIVISOR_1000 : 0));
7135			if (ret == -1) {
7136				warnx("%s: humanize_number failed!", __func__);
7137				retval = 1;
7138				goto bailout;
7139			}
7140			fprintf(stdout, "Device Size: %s%s", tmpstr,
7141				(sizeonly == 0) ?  ", " : "\n");
7142		} else if (numblocks != 0) {
7143			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7144				"Blocks: " : "", (uintmax_t)maxsector + 1,
7145				(sizeonly == 0) ? ", " : "\n");
7146		} else {
7147			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7148				"Last Block: " : "", (uintmax_t)maxsector,
7149				(sizeonly == 0) ? ", " : "\n");
7150		}
7151	}
7152	if (sizeonly == 0)
7153		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
7154			"Block Length: " : "", block_len, (quiet == 0) ?
7155			" bytes" : "");
7156bailout:
7157	cam_freeccb(ccb);
7158
7159	return (retval);
7160}
7161
7162static int
7163smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
7164       int retry_count, int timeout)
7165{
7166	int c, error = 0;
7167	union ccb *ccb;
7168	uint8_t *smp_request = NULL, *smp_response = NULL;
7169	int request_size = 0, response_size = 0;
7170	int fd_request = 0, fd_response = 0;
7171	char *datastr = NULL;
7172	struct get_hook hook;
7173	int retval;
7174	int flags = 0;
7175
7176	/*
7177	 * Note that at the moment we don't support sending SMP CCBs to
7178	 * devices that aren't probed by CAM.
7179	 */
7180	ccb = cam_getccb(device);
7181	if (ccb == NULL) {
7182		warnx("%s: error allocating CCB", __func__);
7183		return (1);
7184	}
7185
7186	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7187
7188	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7189		switch (c) {
7190		case 'R':
7191			arglist |= CAM_ARG_CMD_IN;
7192			response_size = strtol(optarg, NULL, 0);
7193			if (response_size <= 0) {
7194				warnx("invalid number of response bytes %d",
7195				      response_size);
7196				error = 1;
7197				goto smpcmd_bailout;
7198			}
7199			hook.argc = argc - optind;
7200			hook.argv = argv + optind;
7201			hook.got = 0;
7202			optind++;
7203			datastr = cget(&hook, NULL);
7204			/*
7205			 * If the user supplied "-" instead of a format, he
7206			 * wants the data to be written to stdout.
7207			 */
7208			if ((datastr != NULL)
7209			 && (datastr[0] == '-'))
7210				fd_response = 1;
7211
7212			smp_response = (u_int8_t *)malloc(response_size);
7213			if (smp_response == NULL) {
7214				warn("can't malloc memory for SMP response");
7215				error = 1;
7216				goto smpcmd_bailout;
7217			}
7218			break;
7219		case 'r':
7220			arglist |= CAM_ARG_CMD_OUT;
7221			request_size = strtol(optarg, NULL, 0);
7222			if (request_size <= 0) {
7223				warnx("invalid number of request bytes %d",
7224				      request_size);
7225				error = 1;
7226				goto smpcmd_bailout;
7227			}
7228			hook.argc = argc - optind;
7229			hook.argv = argv + optind;
7230			hook.got = 0;
7231			datastr = cget(&hook, NULL);
7232			smp_request = (u_int8_t *)malloc(request_size);
7233			if (smp_request == NULL) {
7234				warn("can't malloc memory for SMP request");
7235				error = 1;
7236				goto smpcmd_bailout;
7237			}
7238			bzero(smp_request, request_size);
7239			/*
7240			 * If the user supplied "-" instead of a format, he
7241			 * wants the data to be read from stdin.
7242			 */
7243			if ((datastr != NULL)
7244			 && (datastr[0] == '-'))
7245				fd_request = 1;
7246			else
7247				buff_encode_visit(smp_request, request_size,
7248						  datastr,
7249						  iget, &hook);
7250			optind += hook.got;
7251			break;
7252		default:
7253			break;
7254		}
7255	}
7256
7257	/*
7258	 * If fd_data is set, and we're writing to the device, we need to
7259	 * read the data the user wants written from stdin.
7260	 */
7261	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
7262		ssize_t amt_read;
7263		int amt_to_read = request_size;
7264		u_int8_t *buf_ptr = smp_request;
7265
7266		for (amt_read = 0; amt_to_read > 0;
7267		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
7268			if (amt_read == -1) {
7269				warn("error reading data from stdin");
7270				error = 1;
7271				goto smpcmd_bailout;
7272			}
7273			amt_to_read -= amt_read;
7274			buf_ptr += amt_read;
7275		}
7276	}
7277
7278	if (((arglist & CAM_ARG_CMD_IN) == 0)
7279	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
7280		warnx("%s: need both the request (-r) and response (-R) "
7281		      "arguments", __func__);
7282		error = 1;
7283		goto smpcmd_bailout;
7284	}
7285
7286	flags |= CAM_DEV_QFRZDIS;
7287
7288	cam_fill_smpio(&ccb->smpio,
7289		       /*retries*/ retry_count,
7290		       /*cbfcnp*/ NULL,
7291		       /*flags*/ flags,
7292		       /*smp_request*/ smp_request,
7293		       /*smp_request_len*/ request_size,
7294		       /*smp_response*/ smp_response,
7295		       /*smp_response_len*/ response_size,
7296		       /*timeout*/ timeout ? timeout : 5000);
7297
7298	ccb->smpio.flags = SMP_FLAG_NONE;
7299
7300	if (((retval = cam_send_ccb(device, ccb)) < 0)
7301	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7302		const char warnstr[] = "error sending command";
7303
7304		if (retval < 0)
7305			warn(warnstr);
7306		else
7307			warnx(warnstr);
7308
7309		if (arglist & CAM_ARG_VERBOSE) {
7310			cam_error_print(device, ccb, CAM_ESF_ALL,
7311					CAM_EPF_ALL, stderr);
7312		}
7313	}
7314
7315	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
7316	 && (response_size > 0)) {
7317		if (fd_response == 0) {
7318			buff_decode_visit(smp_response, response_size,
7319					  datastr, arg_put, NULL);
7320			fprintf(stdout, "\n");
7321		} else {
7322			ssize_t amt_written;
7323			int amt_to_write = response_size;
7324			u_int8_t *buf_ptr = smp_response;
7325
7326			for (amt_written = 0; (amt_to_write > 0) &&
7327			     (amt_written = write(STDOUT_FILENO, buf_ptr,
7328						  amt_to_write)) > 0;){
7329				amt_to_write -= amt_written;
7330				buf_ptr += amt_written;
7331			}
7332			if (amt_written == -1) {
7333				warn("error writing data to stdout");
7334				error = 1;
7335				goto smpcmd_bailout;
7336			} else if ((amt_written == 0)
7337				&& (amt_to_write > 0)) {
7338				warnx("only wrote %u bytes out of %u",
7339				      response_size - amt_to_write,
7340				      response_size);
7341			}
7342		}
7343	}
7344smpcmd_bailout:
7345	if (ccb != NULL)
7346		cam_freeccb(ccb);
7347
7348	if (smp_request != NULL)
7349		free(smp_request);
7350
7351	if (smp_response != NULL)
7352		free(smp_response);
7353
7354	return (error);
7355}
7356
7357static int
7358smpreportgeneral(struct cam_device *device, int argc, char **argv,
7359		 char *combinedopt, int retry_count, int timeout)
7360{
7361	union ccb *ccb;
7362	struct smp_report_general_request *request = NULL;
7363	struct smp_report_general_response *response = NULL;
7364	struct sbuf *sb = NULL;
7365	int error = 0;
7366	int c, long_response = 0;
7367	int retval;
7368
7369	/*
7370	 * Note that at the moment we don't support sending SMP CCBs to
7371	 * devices that aren't probed by CAM.
7372	 */
7373	ccb = cam_getccb(device);
7374	if (ccb == NULL) {
7375		warnx("%s: error allocating CCB", __func__);
7376		return (1);
7377	}
7378
7379	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7380
7381	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7382		switch (c) {
7383		case 'l':
7384			long_response = 1;
7385			break;
7386		default:
7387			break;
7388		}
7389	}
7390	request = malloc(sizeof(*request));
7391	if (request == NULL) {
7392		warn("%s: unable to allocate %zd bytes", __func__,
7393		     sizeof(*request));
7394		error = 1;
7395		goto bailout;
7396	}
7397
7398	response = malloc(sizeof(*response));
7399	if (response == NULL) {
7400		warn("%s: unable to allocate %zd bytes", __func__,
7401		     sizeof(*response));
7402		error = 1;
7403		goto bailout;
7404	}
7405
7406try_long:
7407	smp_report_general(&ccb->smpio,
7408			   retry_count,
7409			   /*cbfcnp*/ NULL,
7410			   request,
7411			   /*request_len*/ sizeof(*request),
7412			   (uint8_t *)response,
7413			   /*response_len*/ sizeof(*response),
7414			   /*long_response*/ long_response,
7415			   timeout);
7416
7417	if (((retval = cam_send_ccb(device, ccb)) < 0)
7418	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7419		const char warnstr[] = "error sending command";
7420
7421		if (retval < 0)
7422			warn(warnstr);
7423		else
7424			warnx(warnstr);
7425
7426		if (arglist & CAM_ARG_VERBOSE) {
7427			cam_error_print(device, ccb, CAM_ESF_ALL,
7428					CAM_EPF_ALL, stderr);
7429		}
7430		error = 1;
7431		goto bailout;
7432	}
7433
7434	/*
7435	 * If the device supports the long response bit, try again and see
7436	 * if we can get all of the data.
7437	 */
7438	if ((response->long_response & SMP_RG_LONG_RESPONSE)
7439	 && (long_response == 0)) {
7440		ccb->ccb_h.status = CAM_REQ_INPROG;
7441		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7442		long_response = 1;
7443		goto try_long;
7444	}
7445
7446	/*
7447	 * XXX KDM detect and decode SMP errors here.
7448	 */
7449	sb = sbuf_new_auto();
7450	if (sb == NULL) {
7451		warnx("%s: error allocating sbuf", __func__);
7452		goto bailout;
7453	}
7454
7455	smp_report_general_sbuf(response, sizeof(*response), sb);
7456
7457	if (sbuf_finish(sb) != 0) {
7458		warnx("%s: sbuf_finish", __func__);
7459		goto bailout;
7460	}
7461
7462	printf("%s", sbuf_data(sb));
7463
7464bailout:
7465	if (ccb != NULL)
7466		cam_freeccb(ccb);
7467
7468	if (request != NULL)
7469		free(request);
7470
7471	if (response != NULL)
7472		free(response);
7473
7474	if (sb != NULL)
7475		sbuf_delete(sb);
7476
7477	return (error);
7478}
7479
7480static struct camcontrol_opts phy_ops[] = {
7481	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7482	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7483	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7484	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7485	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7486	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7487	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7488	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7489	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7490	{NULL, 0, 0, NULL}
7491};
7492
7493static int
7494smpphycontrol(struct cam_device *device, int argc, char **argv,
7495	      char *combinedopt, int retry_count, int timeout)
7496{
7497	union ccb *ccb;
7498	struct smp_phy_control_request *request = NULL;
7499	struct smp_phy_control_response *response = NULL;
7500	int long_response = 0;
7501	int retval = 0;
7502	int phy = -1;
7503	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7504	int phy_op_set = 0;
7505	uint64_t attached_dev_name = 0;
7506	int dev_name_set = 0;
7507	uint32_t min_plr = 0, max_plr = 0;
7508	uint32_t pp_timeout_val = 0;
7509	int slumber_partial = 0;
7510	int set_pp_timeout_val = 0;
7511	int c;
7512
7513	/*
7514	 * Note that at the moment we don't support sending SMP CCBs to
7515	 * devices that aren't probed by CAM.
7516	 */
7517	ccb = cam_getccb(device);
7518	if (ccb == NULL) {
7519		warnx("%s: error allocating CCB", __func__);
7520		return (1);
7521	}
7522
7523	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7524
7525	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7526		switch (c) {
7527		case 'a':
7528		case 'A':
7529		case 's':
7530		case 'S': {
7531			int enable = -1;
7532
7533			if (strcasecmp(optarg, "enable") == 0)
7534				enable = 1;
7535			else if (strcasecmp(optarg, "disable") == 0)
7536				enable = 2;
7537			else {
7538				warnx("%s: Invalid argument %s", __func__,
7539				      optarg);
7540				retval = 1;
7541				goto bailout;
7542			}
7543			switch (c) {
7544			case 's':
7545				slumber_partial |= enable <<
7546						   SMP_PC_SAS_SLUMBER_SHIFT;
7547				break;
7548			case 'S':
7549				slumber_partial |= enable <<
7550						   SMP_PC_SAS_PARTIAL_SHIFT;
7551				break;
7552			case 'a':
7553				slumber_partial |= enable <<
7554						   SMP_PC_SATA_SLUMBER_SHIFT;
7555				break;
7556			case 'A':
7557				slumber_partial |= enable <<
7558						   SMP_PC_SATA_PARTIAL_SHIFT;
7559				break;
7560			default:
7561				warnx("%s: programmer error", __func__);
7562				retval = 1;
7563				goto bailout;
7564				break; /*NOTREACHED*/
7565			}
7566			break;
7567		}
7568		case 'd':
7569			attached_dev_name = (uintmax_t)strtoumax(optarg,
7570								 NULL,0);
7571			dev_name_set = 1;
7572			break;
7573		case 'l':
7574			long_response = 1;
7575			break;
7576		case 'm':
7577			/*
7578			 * We don't do extensive checking here, so this
7579			 * will continue to work when new speeds come out.
7580			 */
7581			min_plr = strtoul(optarg, NULL, 0);
7582			if ((min_plr == 0)
7583			 || (min_plr > 0xf)) {
7584				warnx("%s: invalid link rate %x",
7585				      __func__, min_plr);
7586				retval = 1;
7587				goto bailout;
7588			}
7589			break;
7590		case 'M':
7591			/*
7592			 * We don't do extensive checking here, so this
7593			 * will continue to work when new speeds come out.
7594			 */
7595			max_plr = strtoul(optarg, NULL, 0);
7596			if ((max_plr == 0)
7597			 || (max_plr > 0xf)) {
7598				warnx("%s: invalid link rate %x",
7599				      __func__, max_plr);
7600				retval = 1;
7601				goto bailout;
7602			}
7603			break;
7604		case 'o': {
7605			camcontrol_optret optreturn;
7606			cam_argmask argnums;
7607			const char *subopt;
7608
7609			if (phy_op_set != 0) {
7610				warnx("%s: only one phy operation argument "
7611				      "(-o) allowed", __func__);
7612				retval = 1;
7613				goto bailout;
7614			}
7615
7616			phy_op_set = 1;
7617
7618			/*
7619			 * Allow the user to specify the phy operation
7620			 * numerically, as well as with a name.  This will
7621			 * future-proof it a bit, so options that are added
7622			 * in future specs can be used.
7623			 */
7624			if (isdigit(optarg[0])) {
7625				phy_operation = strtoul(optarg, NULL, 0);
7626				if ((phy_operation == 0)
7627				 || (phy_operation > 0xff)) {
7628					warnx("%s: invalid phy operation %#x",
7629					      __func__, phy_operation);
7630					retval = 1;
7631					goto bailout;
7632				}
7633				break;
7634			}
7635			optreturn = getoption(phy_ops, optarg, &phy_operation,
7636					      &argnums, &subopt);
7637
7638			if (optreturn == CC_OR_AMBIGUOUS) {
7639				warnx("%s: ambiguous option %s", __func__,
7640				      optarg);
7641				usage(0);
7642				retval = 1;
7643				goto bailout;
7644			} else if (optreturn == CC_OR_NOT_FOUND) {
7645				warnx("%s: option %s not found", __func__,
7646				      optarg);
7647				usage(0);
7648				retval = 1;
7649				goto bailout;
7650			}
7651			break;
7652		}
7653		case 'p':
7654			phy = atoi(optarg);
7655			break;
7656		case 'T':
7657			pp_timeout_val = strtoul(optarg, NULL, 0);
7658			if (pp_timeout_val > 15) {
7659				warnx("%s: invalid partial pathway timeout "
7660				      "value %u, need a value less than 16",
7661				      __func__, pp_timeout_val);
7662				retval = 1;
7663				goto bailout;
7664			}
7665			set_pp_timeout_val = 1;
7666			break;
7667		default:
7668			break;
7669		}
7670	}
7671
7672	if (phy == -1) {
7673		warnx("%s: a PHY (-p phy) argument is required",__func__);
7674		retval = 1;
7675		goto bailout;
7676	}
7677
7678	if (((dev_name_set != 0)
7679	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7680	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7681	  && (dev_name_set == 0))) {
7682		warnx("%s: -d name and -o setdevname arguments both "
7683		      "required to set device name", __func__);
7684		retval = 1;
7685		goto bailout;
7686	}
7687
7688	request = malloc(sizeof(*request));
7689	if (request == NULL) {
7690		warn("%s: unable to allocate %zd bytes", __func__,
7691		     sizeof(*request));
7692		retval = 1;
7693		goto bailout;
7694	}
7695
7696	response = malloc(sizeof(*response));
7697	if (response == NULL) {
7698		warn("%s: unable to allocate %zd bytes", __func__,
7699		     sizeof(*response));
7700		retval = 1;
7701		goto bailout;
7702	}
7703
7704	smp_phy_control(&ccb->smpio,
7705			retry_count,
7706			/*cbfcnp*/ NULL,
7707			request,
7708			sizeof(*request),
7709			(uint8_t *)response,
7710			sizeof(*response),
7711			long_response,
7712			/*expected_exp_change_count*/ 0,
7713			phy,
7714			phy_operation,
7715			(set_pp_timeout_val != 0) ? 1 : 0,
7716			attached_dev_name,
7717			min_plr,
7718			max_plr,
7719			slumber_partial,
7720			pp_timeout_val,
7721			timeout);
7722
7723	if (((retval = cam_send_ccb(device, ccb)) < 0)
7724	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7725		const char warnstr[] = "error sending command";
7726
7727		if (retval < 0)
7728			warn(warnstr);
7729		else
7730			warnx(warnstr);
7731
7732		if (arglist & CAM_ARG_VERBOSE) {
7733			/*
7734			 * Use CAM_EPF_NORMAL so we only get one line of
7735			 * SMP command decoding.
7736			 */
7737			cam_error_print(device, ccb, CAM_ESF_ALL,
7738					CAM_EPF_NORMAL, stderr);
7739		}
7740		retval = 1;
7741		goto bailout;
7742	}
7743
7744	/* XXX KDM print out something here for success? */
7745bailout:
7746	if (ccb != NULL)
7747		cam_freeccb(ccb);
7748
7749	if (request != NULL)
7750		free(request);
7751
7752	if (response != NULL)
7753		free(response);
7754
7755	return (retval);
7756}
7757
7758static int
7759smpmaninfo(struct cam_device *device, int argc, char **argv,
7760	   char *combinedopt, int retry_count, int timeout)
7761{
7762	union ccb *ccb;
7763	struct smp_report_manuf_info_request request;
7764	struct smp_report_manuf_info_response response;
7765	struct sbuf *sb = NULL;
7766	int long_response = 0;
7767	int retval = 0;
7768	int c;
7769
7770	/*
7771	 * Note that at the moment we don't support sending SMP CCBs to
7772	 * devices that aren't probed by CAM.
7773	 */
7774	ccb = cam_getccb(device);
7775	if (ccb == NULL) {
7776		warnx("%s: error allocating CCB", __func__);
7777		return (1);
7778	}
7779
7780	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7781
7782	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7783		switch (c) {
7784		case 'l':
7785			long_response = 1;
7786			break;
7787		default:
7788			break;
7789		}
7790	}
7791	bzero(&request, sizeof(request));
7792	bzero(&response, sizeof(response));
7793
7794	smp_report_manuf_info(&ccb->smpio,
7795			      retry_count,
7796			      /*cbfcnp*/ NULL,
7797			      &request,
7798			      sizeof(request),
7799			      (uint8_t *)&response,
7800			      sizeof(response),
7801			      long_response,
7802			      timeout);
7803
7804	if (((retval = cam_send_ccb(device, ccb)) < 0)
7805	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7806		const char warnstr[] = "error sending command";
7807
7808		if (retval < 0)
7809			warn(warnstr);
7810		else
7811			warnx(warnstr);
7812
7813		if (arglist & CAM_ARG_VERBOSE) {
7814			cam_error_print(device, ccb, CAM_ESF_ALL,
7815					CAM_EPF_ALL, stderr);
7816		}
7817		retval = 1;
7818		goto bailout;
7819	}
7820
7821	sb = sbuf_new_auto();
7822	if (sb == NULL) {
7823		warnx("%s: error allocating sbuf", __func__);
7824		goto bailout;
7825	}
7826
7827	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7828
7829	if (sbuf_finish(sb) != 0) {
7830		warnx("%s: sbuf_finish", __func__);
7831		goto bailout;
7832	}
7833
7834	printf("%s", sbuf_data(sb));
7835
7836bailout:
7837
7838	if (ccb != NULL)
7839		cam_freeccb(ccb);
7840
7841	if (sb != NULL)
7842		sbuf_delete(sb);
7843
7844	return (retval);
7845}
7846
7847static int
7848getdevid(struct cam_devitem *item)
7849{
7850	int retval = 0;
7851	union ccb *ccb = NULL;
7852
7853	struct cam_device *dev;
7854
7855	dev = cam_open_btl(item->dev_match.path_id,
7856			   item->dev_match.target_id,
7857			   item->dev_match.target_lun, O_RDWR, NULL);
7858
7859	if (dev == NULL) {
7860		warnx("%s", cam_errbuf);
7861		retval = 1;
7862		goto bailout;
7863	}
7864
7865	item->device_id_len = 0;
7866
7867	ccb = cam_getccb(dev);
7868	if (ccb == NULL) {
7869		warnx("%s: error allocating CCB", __func__);
7870		retval = 1;
7871		goto bailout;
7872	}
7873
7874	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai);
7875
7876	/*
7877	 * On the first try, we just probe for the size of the data, and
7878	 * then allocate that much memory and try again.
7879	 */
7880retry:
7881	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7882	ccb->ccb_h.flags = CAM_DIR_IN;
7883	ccb->cdai.flags = CDAI_FLAG_NONE;
7884	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7885	ccb->cdai.bufsiz = item->device_id_len;
7886	if (item->device_id_len != 0)
7887		ccb->cdai.buf = (uint8_t *)item->device_id;
7888
7889	if (cam_send_ccb(dev, ccb) < 0) {
7890		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7891		retval = 1;
7892		goto bailout;
7893	}
7894
7895	if (ccb->ccb_h.status != CAM_REQ_CMP) {
7896		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7897		retval = 1;
7898		goto bailout;
7899	}
7900
7901	if (item->device_id_len == 0) {
7902		/*
7903		 * This is our first time through.  Allocate the buffer,
7904		 * and then go back to get the data.
7905		 */
7906		if (ccb->cdai.provsiz == 0) {
7907			warnx("%s: invalid .provsiz field returned with "
7908			     "XPT_GDEV_ADVINFO CCB", __func__);
7909			retval = 1;
7910			goto bailout;
7911		}
7912		item->device_id_len = ccb->cdai.provsiz;
7913		item->device_id = malloc(item->device_id_len);
7914		if (item->device_id == NULL) {
7915			warn("%s: unable to allocate %d bytes", __func__,
7916			     item->device_id_len);
7917			retval = 1;
7918			goto bailout;
7919		}
7920		ccb->ccb_h.status = CAM_REQ_INPROG;
7921		goto retry;
7922	}
7923
7924bailout:
7925	if (dev != NULL)
7926		cam_close_device(dev);
7927
7928	if (ccb != NULL)
7929		cam_freeccb(ccb);
7930
7931	return (retval);
7932}
7933
7934/*
7935 * XXX KDM merge this code with getdevtree()?
7936 */
7937static int
7938buildbusdevlist(struct cam_devlist *devlist)
7939{
7940	union ccb ccb;
7941	int bufsize, fd = -1;
7942	struct dev_match_pattern *patterns;
7943	struct cam_devitem *item = NULL;
7944	int skip_device = 0;
7945	int retval = 0;
7946
7947	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7948		warn("couldn't open %s", XPT_DEVICE);
7949		return (1);
7950	}
7951
7952	bzero(&ccb, sizeof(union ccb));
7953
7954	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7955	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7956	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7957
7958	ccb.ccb_h.func_code = XPT_DEV_MATCH;
7959	bufsize = sizeof(struct dev_match_result) * 100;
7960	ccb.cdm.match_buf_len = bufsize;
7961	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7962	if (ccb.cdm.matches == NULL) {
7963		warnx("can't malloc memory for matches");
7964		close(fd);
7965		return (1);
7966	}
7967	ccb.cdm.num_matches = 0;
7968	ccb.cdm.num_patterns = 2;
7969	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7970		ccb.cdm.num_patterns;
7971
7972	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7973	if (patterns == NULL) {
7974		warnx("can't malloc memory for patterns");
7975		retval = 1;
7976		goto bailout;
7977	}
7978
7979	ccb.cdm.patterns = patterns;
7980	bzero(patterns, ccb.cdm.pattern_buf_len);
7981
7982	patterns[0].type = DEV_MATCH_DEVICE;
7983	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7984	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7985	patterns[1].type = DEV_MATCH_PERIPH;
7986	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7987	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7988
7989	/*
7990	 * We do the ioctl multiple times if necessary, in case there are
7991	 * more than 100 nodes in the EDT.
7992	 */
7993	do {
7994		unsigned int i;
7995
7996		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7997			warn("error sending CAMIOCOMMAND ioctl");
7998			retval = 1;
7999			goto bailout;
8000		}
8001
8002		if ((ccb.ccb_h.status != CAM_REQ_CMP)
8003		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
8004		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
8005			warnx("got CAM error %#x, CDM error %d\n",
8006			      ccb.ccb_h.status, ccb.cdm.status);
8007			retval = 1;
8008			goto bailout;
8009		}
8010
8011		for (i = 0; i < ccb.cdm.num_matches; i++) {
8012			switch (ccb.cdm.matches[i].type) {
8013			case DEV_MATCH_DEVICE: {
8014				struct device_match_result *dev_result;
8015
8016				dev_result =
8017				     &ccb.cdm.matches[i].result.device_result;
8018
8019				if (dev_result->flags &
8020				    DEV_RESULT_UNCONFIGURED) {
8021					skip_device = 1;
8022					break;
8023				} else
8024					skip_device = 0;
8025
8026				item = malloc(sizeof(*item));
8027				if (item == NULL) {
8028					warn("%s: unable to allocate %zd bytes",
8029					     __func__, sizeof(*item));
8030					retval = 1;
8031					goto bailout;
8032				}
8033				bzero(item, sizeof(*item));
8034				bcopy(dev_result, &item->dev_match,
8035				      sizeof(*dev_result));
8036				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
8037						   links);
8038
8039				if (getdevid(item) != 0) {
8040					retval = 1;
8041					goto bailout;
8042				}
8043				break;
8044			}
8045			case DEV_MATCH_PERIPH: {
8046				struct periph_match_result *periph_result;
8047
8048				periph_result =
8049				      &ccb.cdm.matches[i].result.periph_result;
8050
8051				if (skip_device != 0)
8052					break;
8053				item->num_periphs++;
8054				item->periph_matches = realloc(
8055					item->periph_matches,
8056					item->num_periphs *
8057					sizeof(struct periph_match_result));
8058				if (item->periph_matches == NULL) {
8059					warn("%s: error allocating periph "
8060					     "list", __func__);
8061					retval = 1;
8062					goto bailout;
8063				}
8064				bcopy(periph_result, &item->periph_matches[
8065				      item->num_periphs - 1],
8066				      sizeof(*periph_result));
8067				break;
8068			}
8069			default:
8070				fprintf(stderr, "%s: unexpected match "
8071					"type %d\n", __func__,
8072					ccb.cdm.matches[i].type);
8073				retval = 1;
8074				goto bailout;
8075				break; /*NOTREACHED*/
8076			}
8077		}
8078	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
8079		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
8080bailout:
8081
8082	if (fd != -1)
8083		close(fd);
8084
8085	free(patterns);
8086
8087	free(ccb.cdm.matches);
8088
8089	if (retval != 0)
8090		freebusdevlist(devlist);
8091
8092	return (retval);
8093}
8094
8095static void
8096freebusdevlist(struct cam_devlist *devlist)
8097{
8098	struct cam_devitem *item, *item2;
8099
8100	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
8101		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
8102			      links);
8103		free(item->device_id);
8104		free(item->periph_matches);
8105		free(item);
8106	}
8107}
8108
8109static struct cam_devitem *
8110findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
8111{
8112	struct cam_devitem *item;
8113
8114	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
8115		struct scsi_vpd_id_descriptor *idd;
8116
8117		/*
8118		 * XXX KDM look for LUN IDs as well?
8119		 */
8120		idd = scsi_get_devid(item->device_id,
8121					   item->device_id_len,
8122					   scsi_devid_is_sas_target);
8123		if (idd == NULL)
8124			continue;
8125
8126		if (scsi_8btou64(idd->identifier) == sasaddr)
8127			return (item);
8128	}
8129
8130	return (NULL);
8131}
8132
8133static int
8134smpphylist(struct cam_device *device, int argc, char **argv,
8135	   char *combinedopt, int retry_count, int timeout)
8136{
8137	struct smp_report_general_request *rgrequest = NULL;
8138	struct smp_report_general_response *rgresponse = NULL;
8139	struct smp_discover_request *disrequest = NULL;
8140	struct smp_discover_response *disresponse = NULL;
8141	struct cam_devlist devlist;
8142	union ccb *ccb;
8143	int long_response = 0;
8144	int num_phys = 0;
8145	int quiet = 0;
8146	int retval;
8147	int i, c;
8148
8149	/*
8150	 * Note that at the moment we don't support sending SMP CCBs to
8151	 * devices that aren't probed by CAM.
8152	 */
8153	ccb = cam_getccb(device);
8154	if (ccb == NULL) {
8155		warnx("%s: error allocating CCB", __func__);
8156		return (1);
8157	}
8158
8159	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8160	STAILQ_INIT(&devlist.dev_queue);
8161
8162	rgrequest = malloc(sizeof(*rgrequest));
8163	if (rgrequest == NULL) {
8164		warn("%s: unable to allocate %zd bytes", __func__,
8165		     sizeof(*rgrequest));
8166		retval = 1;
8167		goto bailout;
8168	}
8169
8170	rgresponse = malloc(sizeof(*rgresponse));
8171	if (rgresponse == NULL) {
8172		warn("%s: unable to allocate %zd bytes", __func__,
8173		     sizeof(*rgresponse));
8174		retval = 1;
8175		goto bailout;
8176	}
8177
8178	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8179		switch (c) {
8180		case 'l':
8181			long_response = 1;
8182			break;
8183		case 'q':
8184			quiet = 1;
8185			break;
8186		default:
8187			break;
8188		}
8189	}
8190
8191	smp_report_general(&ccb->smpio,
8192			   retry_count,
8193			   /*cbfcnp*/ NULL,
8194			   rgrequest,
8195			   /*request_len*/ sizeof(*rgrequest),
8196			   (uint8_t *)rgresponse,
8197			   /*response_len*/ sizeof(*rgresponse),
8198			   /*long_response*/ long_response,
8199			   timeout);
8200
8201	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8202
8203	if (((retval = cam_send_ccb(device, ccb)) < 0)
8204	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8205		const char warnstr[] = "error sending command";
8206
8207		if (retval < 0)
8208			warn(warnstr);
8209		else
8210			warnx(warnstr);
8211
8212		if (arglist & CAM_ARG_VERBOSE) {
8213			cam_error_print(device, ccb, CAM_ESF_ALL,
8214					CAM_EPF_ALL, stderr);
8215		}
8216		retval = 1;
8217		goto bailout;
8218	}
8219
8220	num_phys = rgresponse->num_phys;
8221
8222	if (num_phys == 0) {
8223		if (quiet == 0)
8224			fprintf(stdout, "%s: No Phys reported\n", __func__);
8225		retval = 1;
8226		goto bailout;
8227	}
8228
8229	devlist.path_id = device->path_id;
8230
8231	retval = buildbusdevlist(&devlist);
8232	if (retval != 0)
8233		goto bailout;
8234
8235	if (quiet == 0) {
8236		fprintf(stdout, "%d PHYs:\n", num_phys);
8237		fprintf(stdout, "PHY  Attached SAS Address\n");
8238	}
8239
8240	disrequest = malloc(sizeof(*disrequest));
8241	if (disrequest == NULL) {
8242		warn("%s: unable to allocate %zd bytes", __func__,
8243		     sizeof(*disrequest));
8244		retval = 1;
8245		goto bailout;
8246	}
8247
8248	disresponse = malloc(sizeof(*disresponse));
8249	if (disresponse == NULL) {
8250		warn("%s: unable to allocate %zd bytes", __func__,
8251		     sizeof(*disresponse));
8252		retval = 1;
8253		goto bailout;
8254	}
8255
8256	for (i = 0; i < num_phys; i++) {
8257		struct cam_devitem *item;
8258		struct device_match_result *dev_match;
8259		char vendor[16], product[48], revision[16];
8260		char tmpstr[256];
8261		int j;
8262
8263		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8264
8265		ccb->ccb_h.status = CAM_REQ_INPROG;
8266		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8267
8268		smp_discover(&ccb->smpio,
8269			     retry_count,
8270			     /*cbfcnp*/ NULL,
8271			     disrequest,
8272			     sizeof(*disrequest),
8273			     (uint8_t *)disresponse,
8274			     sizeof(*disresponse),
8275			     long_response,
8276			     /*ignore_zone_group*/ 0,
8277			     /*phy*/ i,
8278			     timeout);
8279
8280		if (((retval = cam_send_ccb(device, ccb)) < 0)
8281		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
8282		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
8283			const char warnstr[] = "error sending command";
8284
8285			if (retval < 0)
8286				warn(warnstr);
8287			else
8288				warnx(warnstr);
8289
8290			if (arglist & CAM_ARG_VERBOSE) {
8291				cam_error_print(device, ccb, CAM_ESF_ALL,
8292						CAM_EPF_ALL, stderr);
8293			}
8294			retval = 1;
8295			goto bailout;
8296		}
8297
8298		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
8299			if (quiet == 0)
8300				fprintf(stdout, "%3d  <vacant>\n", i);
8301			continue;
8302		}
8303
8304		if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
8305			item = NULL;
8306		} else {
8307			item = findsasdevice(&devlist,
8308			    scsi_8btou64(disresponse->attached_sas_address));
8309		}
8310
8311		if ((quiet == 0)
8312		 || (item != NULL)) {
8313			fprintf(stdout, "%3d  0x%016jx", i,
8314				(uintmax_t)scsi_8btou64(
8315				disresponse->attached_sas_address));
8316			if (item == NULL) {
8317				fprintf(stdout, "\n");
8318				continue;
8319			}
8320		} else if (quiet != 0)
8321			continue;
8322
8323		dev_match = &item->dev_match;
8324
8325		if (dev_match->protocol == PROTO_SCSI) {
8326			cam_strvis(vendor, dev_match->inq_data.vendor,
8327				   sizeof(dev_match->inq_data.vendor),
8328				   sizeof(vendor));
8329			cam_strvis(product, dev_match->inq_data.product,
8330				   sizeof(dev_match->inq_data.product),
8331				   sizeof(product));
8332			cam_strvis(revision, dev_match->inq_data.revision,
8333				   sizeof(dev_match->inq_data.revision),
8334				   sizeof(revision));
8335			sprintf(tmpstr, "<%s %s %s>", vendor, product,
8336				revision);
8337		} else if ((dev_match->protocol == PROTO_ATA)
8338			|| (dev_match->protocol == PROTO_SATAPM)) {
8339			cam_strvis(product, dev_match->ident_data.model,
8340				   sizeof(dev_match->ident_data.model),
8341				   sizeof(product));
8342			cam_strvis(revision, dev_match->ident_data.revision,
8343				   sizeof(dev_match->ident_data.revision),
8344				   sizeof(revision));
8345			sprintf(tmpstr, "<%s %s>", product, revision);
8346		} else {
8347			sprintf(tmpstr, "<>");
8348		}
8349		fprintf(stdout, "   %-33s ", tmpstr);
8350
8351		/*
8352		 * If we have 0 periphs, that's a bug...
8353		 */
8354		if (item->num_periphs == 0) {
8355			fprintf(stdout, "\n");
8356			continue;
8357		}
8358
8359		fprintf(stdout, "(");
8360		for (j = 0; j < item->num_periphs; j++) {
8361			if (j > 0)
8362				fprintf(stdout, ",");
8363
8364			fprintf(stdout, "%s%d",
8365				item->periph_matches[j].periph_name,
8366				item->periph_matches[j].unit_number);
8367
8368		}
8369		fprintf(stdout, ")\n");
8370	}
8371bailout:
8372	if (ccb != NULL)
8373		cam_freeccb(ccb);
8374
8375	free(rgrequest);
8376
8377	free(rgresponse);
8378
8379	free(disrequest);
8380
8381	free(disresponse);
8382
8383	freebusdevlist(&devlist);
8384
8385	return (retval);
8386}
8387
8388static int
8389atapm_proc_resp(struct cam_device *device, union ccb *ccb)
8390{
8391    struct ata_res *res;
8392
8393    res = &ccb->ataio.res;
8394    if (res->status & ATA_STATUS_ERROR) {
8395        if (arglist & CAM_ARG_VERBOSE) {
8396            cam_error_print(device, ccb, CAM_ESF_ALL,
8397                    CAM_EPF_ALL, stderr);
8398            printf("error = 0x%02x, sector_count = 0x%04x, "
8399                   "device = 0x%02x, status = 0x%02x\n",
8400                   res->error, res->sector_count,
8401                   res->device, res->status);
8402        }
8403
8404        return (1);
8405    }
8406
8407    if (arglist & CAM_ARG_VERBOSE) {
8408        fprintf(stdout, "%s%d: Raw native check power data:\n",
8409            device->device_name, device->dev_unit_num);
8410        /* res is 4 byte aligned */
8411        dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
8412
8413        printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
8414               "status = 0x%02x\n", res->error, res->sector_count,
8415               res->device, res->status);
8416    }
8417
8418    printf("%s%d: ", device->device_name, device->dev_unit_num);
8419    switch (res->sector_count) {
8420    case 0x00:
8421       printf("Standby mode\n");
8422       break;
8423    case 0x40:
8424       printf("NV Cache Power Mode and the spindle is spun down or spinning down\n");
8425       break;
8426    case 0x41:
8427       printf("NV Cache Power Mode and the spindle is spun up or spinning up\n");
8428       break;
8429    case 0x80:
8430       printf("Idle mode\n");
8431       break;
8432    case 0xff:
8433       printf("Active or Idle mode\n");
8434       break;
8435    default:
8436       printf("Unknown mode 0x%02x\n", res->sector_count);
8437       break;
8438    }
8439
8440    return (0);
8441}
8442
8443static int
8444atapm(struct cam_device *device, int argc, char **argv,
8445		 char *combinedopt, int retry_count, int timeout)
8446{
8447	union ccb *ccb;
8448	int retval = 0;
8449	int t = -1;
8450	int c;
8451	u_int8_t ata_flags = 0;
8452	u_char cmd, sc;
8453
8454	ccb = cam_getccb(device);
8455
8456	if (ccb == NULL) {
8457		warnx("%s: error allocating ccb", __func__);
8458		return (1);
8459	}
8460
8461	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8462		switch (c) {
8463		case 't':
8464			t = atoi(optarg);
8465			break;
8466		default:
8467			break;
8468		}
8469	}
8470	if (strcmp(argv[1], "idle") == 0) {
8471		if (t == -1)
8472			cmd = ATA_IDLE_IMMEDIATE;
8473		else
8474			cmd = ATA_IDLE_CMD;
8475	} else if (strcmp(argv[1], "standby") == 0) {
8476		if (t == -1)
8477			cmd = ATA_STANDBY_IMMEDIATE;
8478		else
8479			cmd = ATA_STANDBY_CMD;
8480	} else if (strcmp(argv[1], "powermode") == 0) {
8481		cmd = ATA_CHECK_POWER_MODE;
8482		ata_flags = AP_FLAG_CHK_COND;
8483		t = -1;
8484	} else {
8485		cmd = ATA_SLEEP;
8486		t = -1;
8487	}
8488
8489	if (t < 0)
8490		sc = 0;
8491	else if (t <= (240 * 5))
8492		sc = (t + 4) / 5;
8493	else if (t <= (252 * 5))
8494		/* special encoding for 21 minutes */
8495		sc = 252;
8496	else if (t <= (11 * 30 * 60))
8497		sc = (t - 1) / (30 * 60) + 241;
8498	else
8499		sc = 253;
8500
8501	retval = ata_do_cmd(device,
8502	    ccb,
8503	    /*retries*/retry_count,
8504	    /*flags*/CAM_DIR_NONE,
8505	    /*protocol*/AP_PROTO_NON_DATA,
8506	    /*ata_flags*/ata_flags,
8507	    /*tag_action*/MSG_SIMPLE_Q_TAG,
8508	    /*command*/cmd,
8509	    /*features*/0,
8510	    /*lba*/0,
8511	    /*sector_count*/sc,
8512	    /*data_ptr*/NULL,
8513	    /*dxfer_len*/0,
8514	    /*timeout*/timeout ? timeout : 30 * 1000,
8515	    /*quiet*/1);
8516
8517	cam_freeccb(ccb);
8518
8519	if (retval || cmd != ATA_CHECK_POWER_MODE)
8520		return (retval);
8521
8522	return (atapm_proc_resp(device, ccb));
8523}
8524
8525static int
8526ataaxm(struct cam_device *device, int argc, char **argv,
8527		 char *combinedopt, int retry_count, int timeout)
8528{
8529	union ccb *ccb;
8530	int retval = 0;
8531	int l = -1;
8532	int c;
8533	u_char cmd, sc;
8534
8535	ccb = cam_getccb(device);
8536
8537	if (ccb == NULL) {
8538		warnx("%s: error allocating ccb", __func__);
8539		return (1);
8540	}
8541
8542	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8543		switch (c) {
8544		case 'l':
8545			l = atoi(optarg);
8546			break;
8547		default:
8548			break;
8549		}
8550	}
8551	sc = 0;
8552	if (strcmp(argv[1], "apm") == 0) {
8553		if (l == -1)
8554			cmd = 0x85;
8555		else {
8556			cmd = 0x05;
8557			sc = l;
8558		}
8559	} else /* aam */ {
8560		if (l == -1)
8561			cmd = 0xC2;
8562		else {
8563			cmd = 0x42;
8564			sc = l;
8565		}
8566	}
8567
8568	retval = ata_do_28bit_cmd(device,
8569	    ccb,
8570	    /*retries*/retry_count,
8571	    /*flags*/CAM_DIR_NONE,
8572	    /*protocol*/AP_PROTO_NON_DATA,
8573	    /*tag_action*/MSG_SIMPLE_Q_TAG,
8574	    /*command*/ATA_SETFEATURES,
8575	    /*features*/cmd,
8576	    /*lba*/0,
8577	    /*sector_count*/sc,
8578	    /*data_ptr*/NULL,
8579	    /*dxfer_len*/0,
8580	    /*timeout*/timeout ? timeout : 30 * 1000,
8581	    /*quiet*/1);
8582
8583	cam_freeccb(ccb);
8584	return (retval);
8585}
8586
8587int
8588scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8589	       int show_sa_errors, int sa_set, int service_action,
8590	       int timeout_desc, int task_attr, int retry_count, int timeout,
8591	       int verbosemode, uint32_t *fill_len, uint8_t **data_ptr)
8592{
8593	union ccb *ccb = NULL;
8594	uint8_t *buf = NULL;
8595	uint32_t alloc_len = 0, num_opcodes;
8596	uint32_t valid_len = 0;
8597	uint32_t avail_len = 0;
8598	struct scsi_report_supported_opcodes_all *all_hdr;
8599	struct scsi_report_supported_opcodes_one *one;
8600	int options = 0;
8601	int retval = 0;
8602
8603	/*
8604	 * Make it clear that we haven't yet allocated or filled anything.
8605	 */
8606	*fill_len = 0;
8607	*data_ptr = NULL;
8608
8609	ccb = cam_getccb(device);
8610	if (ccb == NULL) {
8611		warnx("couldn't allocate CCB");
8612		retval = 1;
8613		goto bailout;
8614	}
8615
8616	/* cam_getccb cleans up the header, caller has to zero the payload */
8617	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8618
8619	if (opcode_set != 0) {
8620		options |= RSO_OPTIONS_OC;
8621		num_opcodes = 1;
8622		alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8623	} else {
8624		num_opcodes = 256;
8625		alloc_len = sizeof(*all_hdr) + (num_opcodes *
8626		    sizeof(struct scsi_report_supported_opcodes_descr));
8627	}
8628
8629	if (timeout_desc != 0) {
8630		options |= RSO_RCTD;
8631		alloc_len += num_opcodes *
8632		    sizeof(struct scsi_report_supported_opcodes_timeout);
8633	}
8634
8635	if (sa_set != 0) {
8636		options |= RSO_OPTIONS_OC_SA;
8637		if (show_sa_errors != 0)
8638			options &= ~RSO_OPTIONS_OC;
8639	}
8640
8641retry_alloc:
8642	if (buf != NULL) {
8643		free(buf);
8644		buf = NULL;
8645	}
8646
8647	buf = malloc(alloc_len);
8648	if (buf == NULL) {
8649		warn("Unable to allocate %u bytes", alloc_len);
8650		retval = 1;
8651		goto bailout;
8652	}
8653	bzero(buf, alloc_len);
8654
8655	scsi_report_supported_opcodes(&ccb->csio,
8656				      /*retries*/ retry_count,
8657				      /*cbfcnp*/ NULL,
8658				      /*tag_action*/ task_attr,
8659				      /*options*/ options,
8660				      /*req_opcode*/ opcode,
8661				      /*req_service_action*/ service_action,
8662				      /*data_ptr*/ buf,
8663				      /*dxfer_len*/ alloc_len,
8664				      /*sense_len*/ SSD_FULL_SIZE,
8665				      /*timeout*/ timeout ? timeout : 10000);
8666
8667	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8668
8669	if (retry_count != 0)
8670		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
8671
8672	if (cam_send_ccb(device, ccb) < 0) {
8673		perror("error sending REPORT SUPPORTED OPERATION CODES");
8674		retval = 1;
8675		goto bailout;
8676	}
8677
8678	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8679		if (verbosemode != 0)
8680			cam_error_print(device, ccb, CAM_ESF_ALL,
8681					CAM_EPF_ALL, stderr);
8682		retval = 1;
8683		goto bailout;
8684	}
8685
8686	valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
8687
8688	if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
8689	 && (valid_len >= sizeof(*all_hdr))) {
8690		all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
8691		avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
8692	} else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
8693		&& (valid_len >= sizeof(*one))) {
8694		uint32_t cdb_length;
8695
8696		one = (struct scsi_report_supported_opcodes_one *)buf;
8697		cdb_length = scsi_2btoul(one->cdb_length);
8698		avail_len = sizeof(*one) + cdb_length;
8699		if (one->support & RSO_ONE_CTDP) {
8700			struct scsi_report_supported_opcodes_timeout *td;
8701
8702			td = (struct scsi_report_supported_opcodes_timeout *)
8703			    &buf[avail_len];
8704			if (valid_len >= (avail_len + sizeof(td->length))) {
8705				avail_len += scsi_2btoul(td->length) +
8706				    sizeof(td->length);
8707			} else {
8708				avail_len += sizeof(*td);
8709			}
8710		}
8711	}
8712
8713	/*
8714	 * avail_len could be zero if we didn't get enough data back from
8715	 * thet target to determine
8716	 */
8717	if ((avail_len != 0)
8718	 && (avail_len > valid_len)) {
8719		alloc_len = avail_len;
8720		goto retry_alloc;
8721	}
8722
8723	*fill_len = valid_len;
8724	*data_ptr = buf;
8725bailout:
8726	if (retval != 0)
8727		free(buf);
8728
8729	cam_freeccb(ccb);
8730
8731	return (retval);
8732}
8733
8734static int
8735scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
8736		   int req_sa, uint8_t *buf, uint32_t valid_len)
8737{
8738	struct scsi_report_supported_opcodes_one *one;
8739	struct scsi_report_supported_opcodes_timeout *td;
8740	uint32_t cdb_len = 0, td_len = 0;
8741	const char *op_desc = NULL;
8742	unsigned int i;
8743	int retval = 0;
8744
8745	one = (struct scsi_report_supported_opcodes_one *)buf;
8746
8747	/*
8748	 * If we don't have the full single opcode descriptor, no point in
8749	 * continuing.
8750	 */
8751	if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8752	    cdb_length)) {
8753		warnx("Only %u bytes returned, not enough to verify support",
8754		      valid_len);
8755		retval = 1;
8756		goto bailout;
8757	}
8758
8759	op_desc = scsi_op_desc(req_opcode, &device->inq_data);
8760
8761	printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
8762	       req_opcode);
8763	if (sa_set != 0)
8764		printf(", SA 0x%x", req_sa);
8765	printf(": ");
8766
8767	switch (one->support & RSO_ONE_SUP_MASK) {
8768	case RSO_ONE_SUP_UNAVAIL:
8769		printf("No command support information currently available\n");
8770		break;
8771	case RSO_ONE_SUP_NOT_SUP:
8772		printf("Command not supported\n");
8773		retval = 1;
8774		goto bailout;
8775		break; /*NOTREACHED*/
8776	case RSO_ONE_SUP_AVAIL:
8777		printf("Command is supported, complies with a SCSI standard\n");
8778		break;
8779	case RSO_ONE_SUP_VENDOR:
8780		printf("Command is supported, vendor-specific "
8781		       "implementation\n");
8782		break;
8783	default:
8784		printf("Unknown command support flags 0x%#x\n",
8785		       one->support & RSO_ONE_SUP_MASK);
8786		break;
8787	}
8788
8789	/*
8790	 * If we don't have the CDB length, it isn't exactly an error, the
8791	 * command probably isn't supported.
8792	 */
8793	if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8794	    cdb_usage))
8795		goto bailout;
8796
8797	cdb_len = scsi_2btoul(one->cdb_length);
8798
8799	/*
8800	 * If our valid data doesn't include the full reported length,
8801	 * return.  The caller should have detected this and adjusted his
8802	 * allocation length to get all of the available data.
8803	 */
8804	if (valid_len < sizeof(*one) + cdb_len) {
8805		retval = 1;
8806		goto bailout;
8807	}
8808
8809	/*
8810	 * If all we have is the opcode, there is no point in printing out
8811	 * the usage bitmap.
8812	 */
8813	if (cdb_len <= 1) {
8814		retval = 1;
8815		goto bailout;
8816	}
8817
8818	printf("CDB usage bitmap:");
8819	for (i = 0; i < cdb_len; i++) {
8820		printf(" %02x", one->cdb_usage[i]);
8821	}
8822	printf("\n");
8823
8824	/*
8825	 * If we don't have a timeout descriptor, we're done.
8826	 */
8827	if ((one->support & RSO_ONE_CTDP) == 0)
8828		goto bailout;
8829
8830	/*
8831	 * If we don't have enough valid length to include the timeout
8832	 * descriptor length, we're done.
8833	 */
8834	if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
8835		goto bailout;
8836
8837	td = (struct scsi_report_supported_opcodes_timeout *)
8838	    &buf[sizeof(*one) + cdb_len];
8839	td_len = scsi_2btoul(td->length);
8840	td_len += sizeof(td->length);
8841
8842	/*
8843	 * If we don't have the full timeout descriptor, we're done.
8844	 */
8845	if (td_len < sizeof(*td))
8846		goto bailout;
8847
8848	/*
8849	 * If we don't have enough valid length to contain the full timeout
8850	 * descriptor, we're done.
8851	 */
8852	if (valid_len < (sizeof(*one) + cdb_len + td_len))
8853		goto bailout;
8854
8855	printf("Timeout information:\n");
8856	printf("Command-specific:    0x%02x\n", td->cmd_specific);
8857	printf("Nominal timeout:     %u seconds\n",
8858	       scsi_4btoul(td->nominal_time));
8859	printf("Recommended timeout: %u seconds\n",
8860	       scsi_4btoul(td->recommended_time));
8861
8862bailout:
8863	return (retval);
8864}
8865
8866static int
8867scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
8868		 uint32_t valid_len)
8869{
8870	struct scsi_report_supported_opcodes_all *hdr;
8871	struct scsi_report_supported_opcodes_descr *desc;
8872	uint32_t avail_len = 0, used_len = 0;
8873	uint8_t *cur_ptr;
8874	int retval = 0;
8875
8876	if (valid_len < sizeof(*hdr)) {
8877		warnx("%s: not enough returned data (%u bytes) opcode list",
8878		      __func__, valid_len);
8879		retval = 1;
8880		goto bailout;
8881	}
8882	hdr = (struct scsi_report_supported_opcodes_all *)buf;
8883	avail_len = scsi_4btoul(hdr->length);
8884	avail_len += sizeof(hdr->length);
8885	/*
8886	 * Take the lesser of the amount of data the drive claims is
8887	 * available, and the amount of data the HBA says was returned.
8888	 */
8889	avail_len = MIN(avail_len, valid_len);
8890
8891	used_len = sizeof(hdr->length);
8892
8893	printf("%-6s %4s %8s ",
8894	       "Opcode", "SA", "CDB len" );
8895
8896	if (td_req != 0)
8897		printf("%5s %6s %6s ", "CS", "Nom", "Rec");
8898	printf(" Description\n");
8899
8900	while ((avail_len - used_len) > sizeof(*desc)) {
8901		struct scsi_report_supported_opcodes_timeout *td;
8902		uint32_t td_len;
8903		const char *op_desc = NULL;
8904
8905		cur_ptr = &buf[used_len];
8906		desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
8907
8908		op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
8909		if (op_desc == NULL)
8910			op_desc = "UNKNOWN";
8911
8912		printf("0x%02x   %#4x %8u ", desc->opcode,
8913		       scsi_2btoul(desc->service_action),
8914		       scsi_2btoul(desc->cdb_length));
8915
8916		used_len += sizeof(*desc);
8917
8918		if ((desc->flags & RSO_CTDP) == 0) {
8919			printf(" %s\n", op_desc);
8920			continue;
8921		}
8922
8923		/*
8924		 * If we don't have enough space to fit a timeout
8925		 * descriptor, then we're done.
8926		 */
8927		if (avail_len - used_len < sizeof(*td)) {
8928			used_len = avail_len;
8929			printf(" %s\n", op_desc);
8930			continue;
8931		}
8932		cur_ptr = &buf[used_len];
8933		td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
8934		td_len = scsi_2btoul(td->length);
8935		td_len += sizeof(td->length);
8936
8937		used_len += td_len;
8938		/*
8939		 * If the given timeout descriptor length is less than what
8940		 * we understand, skip it.
8941		 */
8942		if (td_len < sizeof(*td)) {
8943			printf(" %s\n", op_desc);
8944			continue;
8945		}
8946
8947		printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
8948		       scsi_4btoul(td->nominal_time),
8949		       scsi_4btoul(td->recommended_time), op_desc);
8950	}
8951bailout:
8952	return (retval);
8953}
8954
8955static int
8956scsiopcodes(struct cam_device *device, int argc, char **argv,
8957	    char *combinedopt, int task_attr, int retry_count, int timeout,
8958	    int verbosemode)
8959{
8960	int c;
8961	uint32_t opcode = 0, service_action = 0;
8962	int td_set = 0, opcode_set = 0, sa_set = 0;
8963	int show_sa_errors = 1;
8964	uint32_t valid_len = 0;
8965	uint8_t *buf = NULL;
8966	char *endptr;
8967	int retval = 0;
8968
8969	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8970		switch (c) {
8971		case 'N':
8972			show_sa_errors = 0;
8973			break;
8974		case 'o':
8975			opcode = strtoul(optarg, &endptr, 0);
8976			if (*endptr != '\0') {
8977				warnx("Invalid opcode \"%s\", must be a number",
8978				      optarg);
8979				retval = 1;
8980				goto bailout;
8981			}
8982			if (opcode > 0xff) {
8983				warnx("Invalid opcode 0x%#x, must be between"
8984				      "0 and 0xff inclusive", opcode);
8985				retval = 1;
8986				goto bailout;
8987			}
8988			opcode_set = 1;
8989			break;
8990		case 's':
8991			service_action = strtoul(optarg, &endptr, 0);
8992			if (*endptr != '\0') {
8993				warnx("Invalid service action \"%s\", must "
8994				      "be a number", optarg);
8995				retval = 1;
8996				goto bailout;
8997			}
8998			if (service_action > 0xffff) {
8999				warnx("Invalid service action 0x%#x, must "
9000				      "be between 0 and 0xffff inclusive",
9001				      service_action);
9002				retval = 1;
9003			}
9004			sa_set = 1;
9005			break;
9006		case 'T':
9007			td_set = 1;
9008			break;
9009		default:
9010			break;
9011		}
9012	}
9013
9014	if ((sa_set != 0)
9015	 && (opcode_set == 0)) {
9016		warnx("You must specify an opcode with -o if a service "
9017		      "action is given");
9018		retval = 1;
9019		goto bailout;
9020	}
9021	retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
9022				sa_set, service_action, td_set, task_attr,
9023				retry_count, timeout, verbosemode, &valid_len,
9024				&buf);
9025	if (retval != 0)
9026		goto bailout;
9027
9028	if ((opcode_set != 0)
9029	 || (sa_set != 0)) {
9030		retval = scsiprintoneopcode(device, opcode, sa_set,
9031					    service_action, buf, valid_len);
9032	} else {
9033		retval = scsiprintopcodes(device, td_set, buf, valid_len);
9034	}
9035
9036bailout:
9037	free(buf);
9038
9039	return (retval);
9040}
9041
9042#endif /* MINIMALISTIC */
9043
9044static int
9045scsireprobe(struct cam_device *device)
9046{
9047	union ccb *ccb;
9048	int retval = 0;
9049
9050	ccb = cam_getccb(device);
9051
9052	if (ccb == NULL) {
9053		warnx("%s: error allocating ccb", __func__);
9054		return (1);
9055	}
9056
9057	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
9058
9059	ccb->ccb_h.func_code = XPT_REPROBE_LUN;
9060
9061	if (cam_send_ccb(device, ccb) < 0) {
9062		warn("error sending XPT_REPROBE_LUN CCB");
9063		retval = 1;
9064		goto bailout;
9065	}
9066
9067	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
9068		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
9069		retval = 1;
9070		goto bailout;
9071	}
9072
9073bailout:
9074	cam_freeccb(ccb);
9075
9076	return (retval);
9077}
9078
9079void
9080usage(int printlong)
9081{
9082
9083	fprintf(printlong ? stdout : stderr,
9084"usage:  camcontrol <command>  [device id][generic args][command args]\n"
9085"        camcontrol devlist    [-b] [-v]\n"
9086#ifndef MINIMALISTIC
9087"        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
9088"        camcontrol tur        [dev_id][generic args]\n"
9089"        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
9090"        camcontrol identify   [dev_id][generic args] [-v]\n"
9091"        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
9092"        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
9093"                              [-q] [-s] [-l]\n"
9094"        camcontrol start      [dev_id][generic args]\n"
9095"        camcontrol stop       [dev_id][generic args]\n"
9096"        camcontrol load       [dev_id][generic args]\n"
9097"        camcontrol eject      [dev_id][generic args]\n"
9098"        camcontrol reprobe    [dev_id][generic args]\n"
9099#endif /* MINIMALISTIC */
9100"        camcontrol rescan     <all | bus[:target:lun] | dev_id>\n"
9101"        camcontrol reset      <all | bus[:target:lun] | dev_id>\n"
9102#ifndef MINIMALISTIC
9103"        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
9104"                              [-q][-s][-S offset][-X]\n"
9105"        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
9106"                              [-P pagectl][-e | -b][-d]\n"
9107"        camcontrol cmd        [dev_id][generic args]\n"
9108"                              <-a cmd [args] | -c cmd [args]>\n"
9109"                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
9110"        camcontrol smpcmd     [dev_id][generic args]\n"
9111"                              <-r len fmt [args]> <-R len fmt [args]>\n"
9112"        camcontrol smprg      [dev_id][generic args][-l]\n"
9113"        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
9114"                              [-o operation][-d name][-m rate][-M rate]\n"
9115"                              [-T pp_timeout][-a enable|disable]\n"
9116"                              [-A enable|disable][-s enable|disable]\n"
9117"                              [-S enable|disable]\n"
9118"        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
9119"        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
9120"        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
9121"                              <all|bus[:target[:lun]]|off>\n"
9122"        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
9123"        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
9124"                              [-D <enable|disable>][-M mode][-O offset]\n"
9125"                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
9126"                              [-U][-W bus_width]\n"
9127"        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
9128"        camcontrol sanitize   [dev_id][generic args]\n"
9129"                              [-a overwrite|block|crypto|exitfailure]\n"
9130"                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
9131"                              [-y]\n"
9132"        camcontrol idle       [dev_id][generic args][-t time]\n"
9133"        camcontrol standby    [dev_id][generic args][-t time]\n"
9134"        camcontrol sleep      [dev_id][generic args]\n"
9135"        camcontrol powermode  [dev_id][generic args]\n"
9136"        camcontrol apm        [dev_id][generic args][-l level]\n"
9137"        camcontrol aam        [dev_id][generic args][-l level]\n"
9138"        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
9139"                              [-s][-y]\n"
9140"        camcontrol security   [dev_id][generic args]\n"
9141"                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
9142"                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
9143"                              [-U <user|master>] [-y]\n"
9144"        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
9145"                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
9146"        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
9147"                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
9148"                              [-s scope][-S][-T type][-U]\n"
9149"        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
9150"                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
9151"                              [-p part][-s start][-T type][-V vol]\n"
9152"        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
9153"                              [-N][-T]\n"
9154"        camcontrol zone       [dev_id][generic args]<-c cmd> [-a] [-l LBA]\n"
9155"                              [-o rep_opts] [-P print_opts]\n"
9156"        camcontrol epc        [dev_id][generic_args]<-c cmd> [-d] [-D] [-e]\n"
9157"                              [-H] [-p power_cond] [-P] [-r rst_src] [-s]\n"
9158"                              [-S power_src] [-T timer]\n"
9159"        camcontrol timestamp  [dev_id][generic_args] <-r [-f format|-m|-U]>|\n"
9160"                              <-s <-f format -T time | -U >>\n"
9161"                              \n"
9162#endif /* MINIMALISTIC */
9163"        camcontrol help\n");
9164	if (!printlong)
9165		return;
9166#ifndef MINIMALISTIC
9167	fprintf(stdout,
9168"Specify one of the following options:\n"
9169"devlist     list all CAM devices\n"
9170"periphlist  list all CAM peripheral drivers attached to a device\n"
9171"tur         send a test unit ready to the named device\n"
9172"inquiry     send a SCSI inquiry command to the named device\n"
9173"identify    send a ATA identify command to the named device\n"
9174"reportluns  send a SCSI report luns command to the device\n"
9175"readcap     send a SCSI read capacity command to the device\n"
9176"start       send a Start Unit command to the device\n"
9177"stop        send a Stop Unit command to the device\n"
9178"load        send a Start Unit command to the device with the load bit set\n"
9179"eject       send a Stop Unit command to the device with the eject bit set\n"
9180"reprobe     update capacity information of the given device\n"
9181"rescan      rescan all buses, the given bus, bus:target:lun or device\n"
9182"reset       reset all buses, the given bus, bus:target:lun or device\n"
9183"defects     read the defect list of the specified device\n"
9184"modepage    display or edit (-e) the given mode page\n"
9185"cmd         send the given SCSI command, may need -i or -o as well\n"
9186"smpcmd      send the given SMP command, requires -o and -i\n"
9187"smprg       send the SMP Report General command\n"
9188"smppc       send the SMP PHY Control command, requires -p\n"
9189"smpphylist  display phys attached to a SAS expander\n"
9190"smpmaninfo  send the SMP Report Manufacturer Info command\n"
9191"debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
9192"tags        report or set the number of transaction slots for a device\n"
9193"negotiate   report or set device negotiation parameters\n"
9194"format      send the SCSI FORMAT UNIT command to the named device\n"
9195"sanitize    send the SCSI SANITIZE command to the named device\n"
9196"idle        send the ATA IDLE command to the named device\n"
9197"standby     send the ATA STANDBY command to the named device\n"
9198"sleep       send the ATA SLEEP command to the named device\n"
9199"powermode   send the ATA CHECK POWER MODE command to the named device\n"
9200"fwdownload  program firmware of the named device with the given image\n"
9201"security    report or send ATA security commands to the named device\n"
9202"persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
9203"attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
9204"opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
9205"zone        manage Zoned Block (Shingled) devices\n"
9206"epc         send ATA Extended Power Conditions commands\n"
9207"timestamp   report or set the device's timestamp\n"
9208"help        this message\n"
9209"Device Identifiers:\n"
9210"bus:target        specify the bus and target, lun defaults to 0\n"
9211"bus:target:lun    specify the bus, target and lun\n"
9212"deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
9213"Generic arguments:\n"
9214"-v                be verbose, print out sense information\n"
9215"-t timeout        command timeout in seconds, overrides default timeout\n"
9216"-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
9217"-u unit           specify unit number, e.g. \"0\", \"5\"\n"
9218"-E                have the kernel attempt to perform SCSI error recovery\n"
9219"-C count          specify the SCSI command retry count (needs -E to work)\n"
9220"-Q task_attr      specify ordered, simple or head tag type for SCSI cmds\n"
9221"modepage arguments:\n"
9222"-l                list all available mode pages\n"
9223"-m page           specify the mode page to view or edit\n"
9224"-e                edit the specified mode page\n"
9225"-b                force view to binary mode\n"
9226"-d                disable block descriptors for mode sense\n"
9227"-P pgctl          page control field 0-3\n"
9228"defects arguments:\n"
9229"-f format         specify defect list format (block, bfi or phys)\n"
9230"-G                get the grown defect list\n"
9231"-P                get the permanent defect list\n"
9232"inquiry arguments:\n"
9233"-D                get the standard inquiry data\n"
9234"-S                get the serial number\n"
9235"-R                get the transfer rate, etc.\n"
9236"reportluns arguments:\n"
9237"-c                only report a count of available LUNs\n"
9238"-l                only print out luns, and not a count\n"
9239"-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
9240"readcap arguments\n"
9241"-b                only report the blocksize\n"
9242"-h                human readable device size, base 2\n"
9243"-H                human readable device size, base 10\n"
9244"-N                print the number of blocks instead of last block\n"
9245"-q                quiet, print numbers only\n"
9246"-s                only report the last block/device size\n"
9247"cmd arguments:\n"
9248"-c cdb [args]     specify the SCSI CDB\n"
9249"-i len fmt        specify input data and input data format\n"
9250"-o len fmt [args] specify output data and output data fmt\n"
9251"smpcmd arguments:\n"
9252"-r len fmt [args] specify the SMP command to be sent\n"
9253"-R len fmt [args] specify SMP response format\n"
9254"smprg arguments:\n"
9255"-l                specify the long response format\n"
9256"smppc arguments:\n"
9257"-p phy            specify the PHY to operate on\n"
9258"-l                specify the long request/response format\n"
9259"-o operation      specify the phy control operation\n"
9260"-d name           set the attached device name\n"
9261"-m rate           set the minimum physical link rate\n"
9262"-M rate           set the maximum physical link rate\n"
9263"-T pp_timeout     set the partial pathway timeout value\n"
9264"-a enable|disable enable or disable SATA slumber\n"
9265"-A enable|disable enable or disable SATA partial phy power\n"
9266"-s enable|disable enable or disable SAS slumber\n"
9267"-S enable|disable enable or disable SAS partial phy power\n"
9268"smpphylist arguments:\n"
9269"-l                specify the long response format\n"
9270"-q                only print phys with attached devices\n"
9271"smpmaninfo arguments:\n"
9272"-l                specify the long response format\n"
9273"debug arguments:\n"
9274"-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
9275"-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
9276"-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
9277"-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
9278"tags arguments:\n"
9279"-N tags           specify the number of tags to use for this device\n"
9280"-q                be quiet, don't report the number of tags\n"
9281"-v                report a number of tag-related parameters\n"
9282"negotiate arguments:\n"
9283"-a                send a test unit ready after negotiation\n"
9284"-c                report/set current negotiation settings\n"
9285"-D <arg>          \"enable\" or \"disable\" disconnection\n"
9286"-M mode           set ATA mode\n"
9287"-O offset         set command delay offset\n"
9288"-q                be quiet, don't report anything\n"
9289"-R syncrate       synchronization rate in MHz\n"
9290"-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
9291"-U                report/set user negotiation settings\n"
9292"-W bus_width      set the bus width in bits (8, 16 or 32)\n"
9293"-v                also print a Path Inquiry CCB for the controller\n"
9294"format arguments:\n"
9295"-q                be quiet, don't print status messages\n"
9296"-r                run in report only mode\n"
9297"-w                don't send immediate format command\n"
9298"-y                don't ask any questions\n"
9299"sanitize arguments:\n"
9300"-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
9301"-c passes         overwrite passes to perform (1 to 31)\n"
9302"-I                invert overwrite pattern after each pass\n"
9303"-P pattern        path to overwrite pattern file\n"
9304"-q                be quiet, don't print status messages\n"
9305"-r                run in report only mode\n"
9306"-U                run operation in unrestricted completion exit mode\n"
9307"-w                don't send immediate sanitize command\n"
9308"-y                don't ask any questions\n"
9309"idle/standby arguments:\n"
9310"-t <arg>          number of seconds before respective state.\n"
9311"fwdownload arguments:\n"
9312"-f fw_image       path to firmware image file\n"
9313"-q                don't print informational messages, only errors\n"
9314"-s                run in simulation mode\n"
9315"-v                print info for every firmware segment sent to device\n"
9316"-y                don't ask any questions\n"
9317"security arguments:\n"
9318"-d pwd            disable security using the given password for the selected\n"
9319"                  user\n"
9320"-e pwd            erase the device using the given pwd for the selected user\n"
9321"-f                freeze the security configuration of the specified device\n"
9322"-h pwd            enhanced erase the device using the given pwd for the\n"
9323"                  selected user\n"
9324"-k pwd            unlock the device using the given pwd for the selected\n"
9325"                  user\n"
9326"-l <high|maximum> specifies which security level to set: high or maximum\n"
9327"-q                be quiet, do not print any status messages\n"
9328"-s pwd            password the device (enable security) using the given\n"
9329"                  pwd for the selected user\n"
9330"-T timeout        overrides the timeout (seconds) used for erase operation\n"
9331"-U <user|master>  specifies which user to set: user or master\n"
9332"-y                don't ask any questions\n"
9333"hpa arguments:\n"
9334"-f                freeze the HPA configuration of the device\n"
9335"-l                lock the HPA configuration of the device\n"
9336"-P                make the HPA max sectors persist\n"
9337"-p pwd            Set the HPA configuration password required for unlock\n"
9338"                  calls\n"
9339"-q                be quiet, do not print any status messages\n"
9340"-s sectors        configures the maximum user accessible sectors of the\n"
9341"                  device\n"
9342"-U pwd            unlock the HPA configuration of the device\n"
9343"-y                don't ask any questions\n"
9344"persist arguments:\n"
9345"-i action         specify read_keys, read_reservation, report_cap, or\n"
9346"                  read_full_status\n"
9347"-o action         specify register, register_ignore, reserve, release,\n"
9348"                  clear, preempt, preempt_abort, register_move, replace_lost\n"
9349"-a                set the All Target Ports (ALL_TG_PT) bit\n"
9350"-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
9351"-k key            specify the Reservation Key\n"
9352"-K sa_key         specify the Service Action Reservation Key\n"
9353"-p                set the Activate Persist Through Power Loss bit\n"
9354"-R rtp            specify the Relative Target Port\n"
9355"-s scope          specify the scope: lun, extent, element or a number\n"
9356"-S                specify Transport ID for register, requires -I\n"
9357"-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
9358"                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
9359"-U                unregister the current initiator for register_move\n"
9360"attrib arguments:\n"
9361"-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
9362"                  supp_attr\n"
9363"-w attr           specify an attribute to write, one -w argument per attr\n"
9364"-a attr_num       only display this attribute number\n"
9365"-c                get cached attributes\n"
9366"-e elem_addr      request attributes for the given element in a changer\n"
9367"-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
9368"                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
9369"                  field_none, field_desc, field_num, field_size, field_rw\n"
9370"-p partition      request attributes for the given partition\n"
9371"-s start_attr     request attributes starting at the given number\n"
9372"-T elem_type      specify the element type (used with -e)\n"
9373"-V logical_vol    specify the logical volume ID\n"
9374"opcodes arguments:\n"
9375"-o opcode         specify the individual opcode to list\n"
9376"-s service_action specify the service action for the opcode\n"
9377"-N                do not return SCSI error for unsupported SA\n"
9378"-T                request nominal and recommended timeout values\n"
9379"zone arguments:\n"
9380"-c cmd            required: rz, open, close, finish, or rwp\n"
9381"-a                apply the action to all zones\n"
9382"-l LBA            specify the zone starting LBA\n"
9383"-o rep_opts       report zones options: all, empty, imp_open, exp_open,\n"
9384"                  closed, full, ro, offline, reset, nonseq, nonwp\n"
9385"-P print_opt      report zones printing:  normal, summary, script\n"
9386"epc arguments:\n"
9387"-c cmd            required: restore, goto, timer, state, enable, disable,\n"
9388"                  source, status, list\n"
9389"-d                disable power mode (timer, state)\n"
9390"-D                delayed entry (goto)\n"
9391"-e                enable power mode (timer, state)\n"
9392"-H                hold power mode (goto)\n"
9393"-p power_cond     Idle_a, Idle_b, Idle_c, Standby_y, Standby_z (timer,\n"
9394"                  state, goto)\n"
9395"-P                only display power mode (status)\n"
9396"-r rst_src        restore settings from: default, saved (restore)\n"
9397"-s                save mode (timer, state, restore)\n"
9398"-S power_src      set power source: battery, nonbattery (source)\n"
9399"-T timer          set timer, seconds, .1 sec resolution (timer)\n"
9400"timestamp arguments:\n"
9401"-r                report the timestamp of the device\n"
9402"-f format         report the timestamp of the device with the given\n"
9403"                  strftime(3) format string\n"
9404"-m                report the timestamp of the device as milliseconds since\n"
9405"                  January 1st, 1970\n"
9406"-U                report the time with UTC instead of the local time zone\n"
9407"-s                set the timestamp of the device\n"
9408"-f format         the format of the time string passed into strptime(3)\n"
9409"-T time           the time value passed into strptime(3)\n"
9410"-U                set the timestamp of the device to UTC time\n"
9411);
9412#endif /* MINIMALISTIC */
9413}
9414
9415int
9416main(int argc, char **argv)
9417{
9418	int c;
9419	char *device = NULL;
9420	int unit = 0;
9421	struct cam_device *cam_dev = NULL;
9422	int timeout = 0, retry_count = 1;
9423	camcontrol_optret optreturn;
9424	char *tstr;
9425	const char *mainopt = "C:En:Q:t:u:v";
9426	const char *subopt = NULL;
9427	char combinedopt[256];
9428	int error = 0, optstart = 2;
9429	int task_attr = MSG_SIMPLE_Q_TAG;
9430	int devopen = 1;
9431#ifndef MINIMALISTIC
9432	path_id_t bus;
9433	target_id_t target;
9434	lun_id_t lun;
9435#endif /* MINIMALISTIC */
9436
9437	cmdlist = CAM_CMD_NONE;
9438	arglist = CAM_ARG_NONE;
9439
9440	if (argc < 2) {
9441		usage(0);
9442		exit(1);
9443	}
9444
9445	/*
9446	 * Get the base option.
9447	 */
9448	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
9449
9450	if (optreturn == CC_OR_AMBIGUOUS) {
9451		warnx("ambiguous option %s", argv[1]);
9452		usage(0);
9453		exit(1);
9454	} else if (optreturn == CC_OR_NOT_FOUND) {
9455		warnx("option %s not found", argv[1]);
9456		usage(0);
9457		exit(1);
9458	}
9459
9460	/*
9461	 * Ahh, getopt(3) is a pain.
9462	 *
9463	 * This is a gross hack.  There really aren't many other good
9464	 * options (excuse the pun) for parsing options in a situation like
9465	 * this.  getopt is kinda braindead, so you end up having to run
9466	 * through the options twice, and give each invocation of getopt
9467	 * the option string for the other invocation.
9468	 *
9469	 * You would think that you could just have two groups of options.
9470	 * The first group would get parsed by the first invocation of
9471	 * getopt, and the second group would get parsed by the second
9472	 * invocation of getopt.  It doesn't quite work out that way.  When
9473	 * the first invocation of getopt finishes, it leaves optind pointing
9474	 * to the argument _after_ the first argument in the second group.
9475	 * So when the second invocation of getopt comes around, it doesn't
9476	 * recognize the first argument it gets and then bails out.
9477	 *
9478	 * A nice alternative would be to have a flag for getopt that says
9479	 * "just keep parsing arguments even when you encounter an unknown
9480	 * argument", but there isn't one.  So there's no real clean way to
9481	 * easily parse two sets of arguments without having one invocation
9482	 * of getopt know about the other.
9483	 *
9484	 * Without this hack, the first invocation of getopt would work as
9485	 * long as the generic arguments are first, but the second invocation
9486	 * (in the subfunction) would fail in one of two ways.  In the case
9487	 * where you don't set optreset, it would fail because optind may be
9488	 * pointing to the argument after the one it should be pointing at.
9489	 * In the case where you do set optreset, and reset optind, it would
9490	 * fail because getopt would run into the first set of options, which
9491	 * it doesn't understand.
9492	 *
9493	 * All of this would "sort of" work if you could somehow figure out
9494	 * whether optind had been incremented one option too far.  The
9495	 * mechanics of that, however, are more daunting than just giving
9496	 * both invocations all of the expect options for either invocation.
9497	 *
9498	 * Needless to say, I wouldn't mind if someone invented a better
9499	 * (non-GPL!) command line parsing interface than getopt.  I
9500	 * wouldn't mind if someone added more knobs to getopt to make it
9501	 * work better.  Who knows, I may talk myself into doing it someday,
9502	 * if the standards weenies let me.  As it is, it just leads to
9503	 * hackery like this and causes people to avoid it in some cases.
9504	 *
9505	 * KDM, September 8th, 1998
9506	 */
9507	if (subopt != NULL)
9508		sprintf(combinedopt, "%s%s", mainopt, subopt);
9509	else
9510		sprintf(combinedopt, "%s", mainopt);
9511
9512	/*
9513	 * For these options we do not parse optional device arguments and
9514	 * we do not open a passthrough device.
9515	 */
9516	if ((cmdlist == CAM_CMD_RESCAN)
9517	 || (cmdlist == CAM_CMD_RESET)
9518	 || (cmdlist == CAM_CMD_DEVTREE)
9519	 || (cmdlist == CAM_CMD_USAGE)
9520	 || (cmdlist == CAM_CMD_DEBUG))
9521		devopen = 0;
9522
9523#ifndef MINIMALISTIC
9524	if ((devopen == 1)
9525	 && (argc > 2 && argv[2][0] != '-')) {
9526		char name[30];
9527		int rv;
9528
9529		if (isdigit(argv[2][0])) {
9530			/* device specified as bus:target[:lun] */
9531			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9532			if (rv < 2)
9533				errx(1, "numeric device specification must "
9534				     "be either bus:target, or "
9535				     "bus:target:lun");
9536			/* default to 0 if lun was not specified */
9537			if ((arglist & CAM_ARG_LUN) == 0) {
9538				lun = 0;
9539				arglist |= CAM_ARG_LUN;
9540			}
9541			optstart++;
9542		} else {
9543			if (cam_get_device(argv[2], name, sizeof name, &unit)
9544			    == -1)
9545				errx(1, "%s", cam_errbuf);
9546			device = strdup(name);
9547			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9548			optstart++;
9549		}
9550	}
9551#endif /* MINIMALISTIC */
9552	/*
9553	 * Start getopt processing at argv[2/3], since we've already
9554	 * accepted argv[1..2] as the command name, and as a possible
9555	 * device name.
9556	 */
9557	optind = optstart;
9558
9559	/*
9560	 * Now we run through the argument list looking for generic
9561	 * options, and ignoring options that possibly belong to
9562	 * subfunctions.
9563	 */
9564	while ((c = getopt(argc, argv, combinedopt))!= -1){
9565		switch(c) {
9566			case 'C':
9567				retry_count = strtol(optarg, NULL, 0);
9568				if (retry_count < 0)
9569					errx(1, "retry count %d is < 0",
9570					     retry_count);
9571				arglist |= CAM_ARG_RETRIES;
9572				break;
9573			case 'E':
9574				arglist |= CAM_ARG_ERR_RECOVER;
9575				break;
9576			case 'n':
9577				arglist |= CAM_ARG_DEVICE;
9578				tstr = optarg;
9579				while (isspace(*tstr) && (*tstr != '\0'))
9580					tstr++;
9581				device = (char *)strdup(tstr);
9582				break;
9583			case 'Q': {
9584				char *endptr;
9585				int table_entry = 0;
9586
9587				tstr = optarg;
9588				while (isspace(*tstr) && (*tstr != '\0'))
9589					tstr++;
9590				if (isdigit(*tstr)) {
9591					task_attr = strtol(tstr, &endptr, 0);
9592					if (*endptr != '\0') {
9593						errx(1, "Invalid queue option "
9594						    "%s", tstr);
9595					}
9596				} else {
9597					size_t table_size;
9598					scsi_nv_status status;
9599
9600					table_size = sizeof(task_attrs) /
9601						     sizeof(task_attrs[0]);
9602					status = scsi_get_nv(task_attrs,
9603					    table_size, tstr, &table_entry,
9604					    SCSI_NV_FLAG_IG_CASE);
9605					if (status == SCSI_NV_FOUND)
9606						task_attr = task_attrs[
9607						    table_entry].value;
9608					else {
9609						errx(1, "%s option %s",
9610						  (status == SCSI_NV_AMBIGUOUS)?
9611						    "ambiguous" : "invalid",
9612						    tstr);
9613					}
9614				}
9615				break;
9616			}
9617			case 't':
9618				timeout = strtol(optarg, NULL, 0);
9619				if (timeout < 0)
9620					errx(1, "invalid timeout %d", timeout);
9621				/* Convert the timeout from seconds to ms */
9622				timeout *= 1000;
9623				arglist |= CAM_ARG_TIMEOUT;
9624				break;
9625			case 'u':
9626				arglist |= CAM_ARG_UNIT;
9627				unit = strtol(optarg, NULL, 0);
9628				break;
9629			case 'v':
9630				arglist |= CAM_ARG_VERBOSE;
9631				break;
9632			default:
9633				break;
9634		}
9635	}
9636
9637#ifndef MINIMALISTIC
9638	/*
9639	 * For most commands we'll want to open the passthrough device
9640	 * associated with the specified device.  In the case of the rescan
9641	 * commands, we don't use a passthrough device at all, just the
9642	 * transport layer device.
9643	 */
9644	if (devopen == 1) {
9645		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
9646		 && (((arglist & CAM_ARG_DEVICE) == 0)
9647		  || ((arglist & CAM_ARG_UNIT) == 0))) {
9648			errx(1, "subcommand \"%s\" requires a valid device "
9649			     "identifier", argv[1]);
9650		}
9651
9652		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
9653				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
9654				cam_open_spec_device(device,unit,O_RDWR,NULL)))
9655		     == NULL)
9656			errx(1,"%s", cam_errbuf);
9657	}
9658#endif /* MINIMALISTIC */
9659
9660	/*
9661	 * Reset optind to 2, and reset getopt, so these routines can parse
9662	 * the arguments again.
9663	 */
9664	optind = optstart;
9665	optreset = 1;
9666
9667	switch(cmdlist) {
9668#ifndef MINIMALISTIC
9669	case CAM_CMD_DEVLIST:
9670		error = getdevlist(cam_dev);
9671		break;
9672	case CAM_CMD_HPA:
9673		error = atahpa(cam_dev, retry_count, timeout,
9674			       argc, argv, combinedopt);
9675		break;
9676#endif /* MINIMALISTIC */
9677	case CAM_CMD_DEVTREE:
9678		error = getdevtree(argc, argv, combinedopt);
9679		break;
9680#ifndef MINIMALISTIC
9681	case CAM_CMD_TUR:
9682		error = testunitready(cam_dev, task_attr, retry_count,
9683		    timeout, 0);
9684		break;
9685	case CAM_CMD_INQUIRY:
9686		error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
9687				      task_attr, retry_count, timeout);
9688		break;
9689	case CAM_CMD_IDENTIFY:
9690		error = ataidentify(cam_dev, retry_count, timeout);
9691		break;
9692	case CAM_CMD_STARTSTOP:
9693		error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
9694				  arglist & CAM_ARG_EJECT, task_attr,
9695				  retry_count, timeout);
9696		break;
9697#endif /* MINIMALISTIC */
9698	case CAM_CMD_RESCAN:
9699		error = dorescan_or_reset(argc, argv, 1);
9700		break;
9701	case CAM_CMD_RESET:
9702		error = dorescan_or_reset(argc, argv, 0);
9703		break;
9704#ifndef MINIMALISTIC
9705	case CAM_CMD_READ_DEFECTS:
9706		error = readdefects(cam_dev, argc, argv, combinedopt,
9707				    task_attr, retry_count, timeout);
9708		break;
9709	case CAM_CMD_MODE_PAGE:
9710		modepage(cam_dev, argc, argv, combinedopt,
9711			 task_attr, retry_count, timeout);
9712		break;
9713	case CAM_CMD_SCSI_CMD:
9714		error = scsicmd(cam_dev, argc, argv, combinedopt,
9715				task_attr, retry_count, timeout);
9716		break;
9717	case CAM_CMD_SMP_CMD:
9718		error = smpcmd(cam_dev, argc, argv, combinedopt,
9719			       retry_count, timeout);
9720		break;
9721	case CAM_CMD_SMP_RG:
9722		error = smpreportgeneral(cam_dev, argc, argv,
9723					 combinedopt, retry_count,
9724					 timeout);
9725		break;
9726	case CAM_CMD_SMP_PC:
9727		error = smpphycontrol(cam_dev, argc, argv, combinedopt,
9728				      retry_count, timeout);
9729		break;
9730	case CAM_CMD_SMP_PHYLIST:
9731		error = smpphylist(cam_dev, argc, argv, combinedopt,
9732				   retry_count, timeout);
9733		break;
9734	case CAM_CMD_SMP_MANINFO:
9735		error = smpmaninfo(cam_dev, argc, argv, combinedopt,
9736				   retry_count, timeout);
9737		break;
9738	case CAM_CMD_DEBUG:
9739		error = camdebug(argc, argv, combinedopt);
9740		break;
9741	case CAM_CMD_TAG:
9742		error = tagcontrol(cam_dev, argc, argv, combinedopt);
9743		break;
9744	case CAM_CMD_RATE:
9745		error = ratecontrol(cam_dev, task_attr, retry_count,
9746				    timeout, argc, argv, combinedopt);
9747		break;
9748	case CAM_CMD_FORMAT:
9749		error = scsiformat(cam_dev, argc, argv,
9750				   combinedopt, task_attr, retry_count,
9751				   timeout);
9752		break;
9753	case CAM_CMD_REPORTLUNS:
9754		error = scsireportluns(cam_dev, argc, argv,
9755				       combinedopt, task_attr,
9756				       retry_count, timeout);
9757		break;
9758	case CAM_CMD_READCAP:
9759		error = scsireadcapacity(cam_dev, argc, argv,
9760					 combinedopt, task_attr,
9761					 retry_count, timeout);
9762		break;
9763	case CAM_CMD_IDLE:
9764	case CAM_CMD_STANDBY:
9765	case CAM_CMD_SLEEP:
9766	case CAM_CMD_POWER_MODE:
9767		error = atapm(cam_dev, argc, argv,
9768			      combinedopt, retry_count, timeout);
9769		break;
9770	case CAM_CMD_APM:
9771	case CAM_CMD_AAM:
9772		error = ataaxm(cam_dev, argc, argv,
9773			      combinedopt, retry_count, timeout);
9774		break;
9775	case CAM_CMD_SECURITY:
9776		error = atasecurity(cam_dev, retry_count, timeout,
9777				    argc, argv, combinedopt);
9778		break;
9779	case CAM_CMD_DOWNLOAD_FW:
9780		error = fwdownload(cam_dev, argc, argv, combinedopt,
9781		    arglist & CAM_ARG_VERBOSE, task_attr, retry_count,
9782		    timeout);
9783		break;
9784	case CAM_CMD_SANITIZE:
9785		error = scsisanitize(cam_dev, argc, argv,
9786				     combinedopt, task_attr,
9787				     retry_count, timeout);
9788		break;
9789	case CAM_CMD_PERSIST:
9790		error = scsipersist(cam_dev, argc, argv, combinedopt,
9791		    task_attr, retry_count, timeout,
9792		    arglist & CAM_ARG_VERBOSE,
9793		    arglist & CAM_ARG_ERR_RECOVER);
9794		break;
9795	case CAM_CMD_ATTRIB:
9796		error = scsiattrib(cam_dev, argc, argv, combinedopt,
9797		    task_attr, retry_count, timeout,
9798		    arglist & CAM_ARG_VERBOSE,
9799		    arglist & CAM_ARG_ERR_RECOVER);
9800		break;
9801	case CAM_CMD_OPCODES:
9802		error = scsiopcodes(cam_dev, argc, argv, combinedopt,
9803		    task_attr, retry_count, timeout,
9804		    arglist & CAM_ARG_VERBOSE);
9805		break;
9806	case CAM_CMD_REPROBE:
9807		error = scsireprobe(cam_dev);
9808		break;
9809	case CAM_CMD_ZONE:
9810		error = zone(cam_dev, argc, argv, combinedopt,
9811		    task_attr, retry_count, timeout,
9812		    arglist & CAM_ARG_VERBOSE);
9813		break;
9814	case CAM_CMD_EPC:
9815		error = epc(cam_dev, argc, argv, combinedopt,
9816		    retry_count, timeout, arglist & CAM_ARG_VERBOSE);
9817		break;
9818	case CAM_CMD_TIMESTAMP:
9819		error = timestamp(cam_dev, argc, argv, combinedopt,
9820		    task_attr, retry_count, timeout,
9821		    arglist & CAM_ARG_VERBOSE);
9822		break;
9823#endif /* MINIMALISTIC */
9824	case CAM_CMD_USAGE:
9825		usage(1);
9826		break;
9827	default:
9828		usage(0);
9829		error = 1;
9830		break;
9831	}
9832
9833	if (cam_dev != NULL)
9834		cam_close_device(cam_dev);
9835
9836	exit(error);
9837}
9838