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