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