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