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