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