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