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