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