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