camcontrol.c revision 275630
138451Smsmith/*
238451Smsmith * Copyright (c) 1997-2007 Kenneth D. Merry
338451Smsmith * All rights reserved.
438451Smsmith *
538451Smsmith * Redistribution and use in source and binary forms, with or without
638451Smsmith * modification, are permitted provided that the following conditions
738451Smsmith * are met:
838451Smsmith * 1. Redistributions of source code must retain the above copyright
938451Smsmith *    notice, this list of conditions and the following disclaimer.
1038451Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1138451Smsmith *    notice, this list of conditions and the following disclaimer in the
1238451Smsmith *    documentation and/or other materials provided with the distribution.
1338451Smsmith * 3. The name of the author may not be used to endorse or promote products
1438451Smsmith *    derived from this software without specific prior written permission.
1538451Smsmith *
1638451Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1738451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1838451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1938451Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2038451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2138451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2238451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2338451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2438451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2538451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2638451Smsmith * SUCH DAMAGE.
2738451Smsmith */
2838451Smsmith
2938451Smsmith#include <sys/cdefs.h>
3038451Smsmith__FBSDID("$FreeBSD: stable/10/sbin/camcontrol/camcontrol.c 275630 2014-12-09 07:03:49Z bryanv $");
3138451Smsmith
3238451Smsmith#include <sys/ioctl.h>
3384221Sdillon#include <sys/stdint.h>
3484221Sdillon#include <sys/types.h>
3584221Sdillon#include <sys/stat.h>
3638451Smsmith#include <sys/endian.h>
3738451Smsmith#include <sys/sbuf.h>
3838451Smsmith
3938451Smsmith#include <stdio.h>
4038451Smsmith#include <stdlib.h>
41221358Srodrigc#include <string.h>
4238451Smsmith#include <unistd.h>
4338451Smsmith#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:GP";
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
3372static int
3373readdefects(struct cam_device *device, int argc, char **argv,
3374	    char *combinedopt, int retry_count, int timeout)
3375{
3376	union ccb *ccb = NULL;
3377	struct scsi_read_defect_data_10 *rdd_cdb;
3378	u_int8_t *defect_list = NULL;
3379	u_int32_t max_dlist_length = SRDD10_MAX_LENGTH, dlist_length = 0;
3380	u_int32_t returned_length = 0;
3381	u_int32_t num_returned = 0;
3382	u_int8_t returned_format;
3383	unsigned int i;
3384	int c, error = 0;
3385	int lists_specified;
3386	int get_length = 1;
3387
3388	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3389		switch(c){
3390		case 'f':
3391		{
3392			char *tstr;
3393			tstr = optarg;
3394			while (isspace(*tstr) && (*tstr != '\0'))
3395				tstr++;
3396			if (strcmp(tstr, "block") == 0)
3397				arglist |= CAM_ARG_FORMAT_BLOCK;
3398			else if (strcmp(tstr, "bfi") == 0)
3399				arglist |= CAM_ARG_FORMAT_BFI;
3400			else if (strcmp(tstr, "phys") == 0)
3401				arglist |= CAM_ARG_FORMAT_PHYS;
3402			else {
3403				error = 1;
3404				warnx("invalid defect format %s", tstr);
3405				goto defect_bailout;
3406			}
3407			break;
3408		}
3409		case 'G':
3410			arglist |= CAM_ARG_GLIST;
3411			break;
3412		case 'P':
3413			arglist |= CAM_ARG_PLIST;
3414			break;
3415		default:
3416			break;
3417		}
3418	}
3419
3420	ccb = cam_getccb(device);
3421
3422	/*
3423	 * Eventually we should probably support the 12 byte READ DEFECT
3424	 * DATA command.  It supports a longer parameter list, which may be
3425	 * necessary on newer drives with lots of defects.  According to
3426	 * the SBC-3 spec, drives are supposed to return an illegal request
3427	 * if they have more defect data than will fit in 64K.
3428	 */
3429	defect_list = malloc(max_dlist_length);
3430	if (defect_list == NULL) {
3431		warnx("can't malloc memory for defect list");
3432		error = 1;
3433		goto defect_bailout;
3434	}
3435
3436	/*
3437	 * We start off asking for just the header to determine how much
3438	 * defect data is available.  Some Hitachi drives return an error
3439	 * if you ask for more data than the drive has.  Once we know the
3440	 * length, we retry the command with the returned length.
3441	 */
3442	dlist_length = sizeof(struct scsi_read_defect_data_hdr_10);
3443
3444	rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
3445
3446retry:
3447
3448	lists_specified = 0;
3449
3450	/*
3451	 * cam_getccb() zeros the CCB header only.  So we need to zero the
3452	 * payload portion of the ccb.
3453	 */
3454	bzero(&(&ccb->ccb_h)[1],
3455	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3456
3457	cam_fill_csio(&ccb->csio,
3458		      /*retries*/ retry_count,
3459		      /*cbfcnp*/ NULL,
3460		      /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
3461					      CAM_PASS_ERR_RECOVER : 0),
3462		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
3463		      /*data_ptr*/ defect_list,
3464		      /*dxfer_len*/ dlist_length,
3465		      /*sense_len*/ SSD_FULL_SIZE,
3466		      /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
3467		      /*timeout*/ timeout ? timeout : 5000);
3468
3469	rdd_cdb->opcode = READ_DEFECT_DATA_10;
3470	if (arglist & CAM_ARG_FORMAT_BLOCK)
3471		rdd_cdb->format = SRDD10_BLOCK_FORMAT;
3472	else if (arglist & CAM_ARG_FORMAT_BFI)
3473		rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
3474	else if (arglist & CAM_ARG_FORMAT_PHYS)
3475		rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
3476	else {
3477		error = 1;
3478		warnx("no defect list format specified");
3479		goto defect_bailout;
3480	}
3481	if (arglist & CAM_ARG_PLIST) {
3482		rdd_cdb->format |= SRDD10_PLIST;
3483		lists_specified++;
3484	}
3485
3486	if (arglist & CAM_ARG_GLIST) {
3487		rdd_cdb->format |= SRDD10_GLIST;
3488		lists_specified++;
3489	}
3490
3491	scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
3492
3493	/* Disable freezing the device queue */
3494	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3495
3496	if (cam_send_ccb(device, ccb) < 0) {
3497		perror("error reading defect list");
3498
3499		if (arglist & CAM_ARG_VERBOSE) {
3500			cam_error_print(device, ccb, CAM_ESF_ALL,
3501					CAM_EPF_ALL, stderr);
3502		}
3503
3504		error = 1;
3505		goto defect_bailout;
3506	}
3507
3508	returned_length = scsi_2btoul(((struct
3509		scsi_read_defect_data_hdr_10 *)defect_list)->length);
3510
3511	if (get_length != 0) {
3512		get_length = 0;
3513
3514		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3515		     CAM_SCSI_STATUS_ERROR) {
3516			struct scsi_sense_data *sense;
3517			int error_code, sense_key, asc, ascq;
3518
3519			sense = &ccb->csio.sense_data;
3520			scsi_extract_sense_len(sense, ccb->csio.sense_len -
3521			    ccb->csio.sense_resid, &error_code, &sense_key,
3522			    &asc, &ascq, /*show_errors*/ 1);
3523
3524			/*
3525			 * If the drive is reporting that it just doesn't
3526			 * support the defect list format, go ahead and use
3527			 * the length it reported.  Otherwise, the length
3528			 * may not be valid, so use the maximum.
3529			 */
3530			if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3531			 && (asc == 0x1c) && (ascq == 0x00)
3532			 && (returned_length > 0)) {
3533				dlist_length = returned_length +
3534				    sizeof(struct scsi_read_defect_data_hdr_10);
3535				dlist_length = min(dlist_length,
3536						   SRDD10_MAX_LENGTH);
3537			} else
3538				dlist_length = max_dlist_length;
3539		} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3540			    CAM_REQ_CMP){
3541			error = 1;
3542			warnx("Error reading defect header");
3543			if (arglist & CAM_ARG_VERBOSE)
3544				cam_error_print(device, ccb, CAM_ESF_ALL,
3545						CAM_EPF_ALL, stderr);
3546			goto defect_bailout;
3547		} else {
3548			dlist_length = returned_length +
3549			    sizeof(struct scsi_read_defect_data_hdr_10);
3550			dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3551		}
3552
3553		goto retry;
3554	}
3555
3556	returned_format = ((struct scsi_read_defect_data_hdr_10 *)
3557			defect_list)->format;
3558
3559	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3560	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3561	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3562		struct scsi_sense_data *sense;
3563		int error_code, sense_key, asc, ascq;
3564
3565		sense = &ccb->csio.sense_data;
3566		scsi_extract_sense_len(sense, ccb->csio.sense_len -
3567		    ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3568		    &ascq, /*show_errors*/ 1);
3569
3570		/*
3571		 * According to the SCSI spec, if the disk doesn't support
3572		 * the requested format, it will generally return a sense
3573		 * key of RECOVERED ERROR, and an additional sense code
3574		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
3575		 * also check to make sure that the returned length is
3576		 * greater than 0, and then print out whatever format the
3577		 * disk gave us.
3578		 */
3579		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3580		 && (asc == 0x1c) && (ascq == 0x00)
3581		 && (returned_length > 0)) {
3582			warnx("requested defect format not available");
3583			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
3584			case SRDD10_BLOCK_FORMAT:
3585				warnx("Device returned block format");
3586				break;
3587			case SRDD10_BYTES_FROM_INDEX_FORMAT:
3588				warnx("Device returned bytes from index"
3589				      " format");
3590				break;
3591			case SRDD10_PHYSICAL_SECTOR_FORMAT:
3592				warnx("Device returned physical sector format");
3593				break;
3594			default:
3595				error = 1;
3596				warnx("Device returned unknown defect"
3597				     " data format %#x", returned_format);
3598				goto defect_bailout;
3599				break; /* NOTREACHED */
3600			}
3601		} else {
3602			error = 1;
3603			warnx("Error returned from read defect data command");
3604			if (arglist & CAM_ARG_VERBOSE)
3605				cam_error_print(device, ccb, CAM_ESF_ALL,
3606						CAM_EPF_ALL, stderr);
3607			goto defect_bailout;
3608		}
3609	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3610		error = 1;
3611		warnx("Error returned from read defect data command");
3612		if (arglist & CAM_ARG_VERBOSE)
3613			cam_error_print(device, ccb, CAM_ESF_ALL,
3614					CAM_EPF_ALL, stderr);
3615		goto defect_bailout;
3616	}
3617
3618	/*
3619	 * XXX KDM  I should probably clean up the printout format for the
3620	 * disk defects.
3621	 */
3622	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
3623		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
3624		{
3625			struct scsi_defect_desc_phys_sector *dlist;
3626
3627			dlist = (struct scsi_defect_desc_phys_sector *)
3628				(defect_list +
3629				sizeof(struct scsi_read_defect_data_hdr_10));
3630
3631			num_returned = returned_length /
3632				sizeof(struct scsi_defect_desc_phys_sector);
3633
3634			fprintf(stderr, "Got %d defect", num_returned);
3635
3636			if ((lists_specified == 0) || (num_returned == 0)) {
3637				fprintf(stderr, "s.\n");
3638				break;
3639			} else if (num_returned == 1)
3640				fprintf(stderr, ":\n");
3641			else
3642				fprintf(stderr, "s:\n");
3643
3644			for (i = 0; i < num_returned; i++) {
3645				fprintf(stdout, "%d:%d:%d\n",
3646					scsi_3btoul(dlist[i].cylinder),
3647					dlist[i].head,
3648					scsi_4btoul(dlist[i].sector));
3649			}
3650			break;
3651		}
3652		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
3653		{
3654			struct scsi_defect_desc_bytes_from_index *dlist;
3655
3656			dlist = (struct scsi_defect_desc_bytes_from_index *)
3657				(defect_list +
3658				sizeof(struct scsi_read_defect_data_hdr_10));
3659
3660			num_returned = returned_length /
3661			      sizeof(struct scsi_defect_desc_bytes_from_index);
3662
3663			fprintf(stderr, "Got %d defect", num_returned);
3664
3665			if ((lists_specified == 0) || (num_returned == 0)) {
3666				fprintf(stderr, "s.\n");
3667				break;
3668			} else if (num_returned == 1)
3669				fprintf(stderr, ":\n");
3670			else
3671				fprintf(stderr, "s:\n");
3672
3673			for (i = 0; i < num_returned; i++) {
3674				fprintf(stdout, "%d:%d:%d\n",
3675					scsi_3btoul(dlist[i].cylinder),
3676					dlist[i].head,
3677					scsi_4btoul(dlist[i].bytes_from_index));
3678			}
3679			break;
3680		}
3681		case SRDDH10_BLOCK_FORMAT:
3682		{
3683			struct scsi_defect_desc_block *dlist;
3684
3685			dlist = (struct scsi_defect_desc_block *)(defect_list +
3686				sizeof(struct scsi_read_defect_data_hdr_10));
3687
3688			num_returned = returned_length /
3689			      sizeof(struct scsi_defect_desc_block);
3690
3691			fprintf(stderr, "Got %d defect", num_returned);
3692
3693			if ((lists_specified == 0) || (num_returned == 0)) {
3694				fprintf(stderr, "s.\n");
3695				break;
3696			} else if (num_returned == 1)
3697				fprintf(stderr, ":\n");
3698			else
3699				fprintf(stderr, "s:\n");
3700
3701			for (i = 0; i < num_returned; i++)
3702				fprintf(stdout, "%u\n",
3703					scsi_4btoul(dlist[i].address));
3704			break;
3705		}
3706		default:
3707			fprintf(stderr, "Unknown defect format %d\n",
3708				returned_format & SRDDH10_DLIST_FORMAT_MASK);
3709			error = 1;
3710			break;
3711	}
3712defect_bailout:
3713
3714	if (defect_list != NULL)
3715		free(defect_list);
3716
3717	if (ccb != NULL)
3718		cam_freeccb(ccb);
3719
3720	return(error);
3721}
3722#endif /* MINIMALISTIC */
3723
3724#if 0
3725void
3726reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3727{
3728	union ccb *ccb;
3729
3730	ccb = cam_getccb(device);
3731
3732	cam_freeccb(ccb);
3733}
3734#endif
3735
3736#ifndef MINIMALISTIC
3737void
3738mode_sense(struct cam_device *device, int mode_page, int page_control,
3739	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3740{
3741	union ccb *ccb;
3742	int retval;
3743
3744	ccb = cam_getccb(device);
3745
3746	if (ccb == NULL)
3747		errx(1, "mode_sense: couldn't allocate CCB");
3748
3749	bzero(&(&ccb->ccb_h)[1],
3750	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3751
3752	scsi_mode_sense(&ccb->csio,
3753			/* retries */ retry_count,
3754			/* cbfcnp */ NULL,
3755			/* tag_action */ MSG_SIMPLE_Q_TAG,
3756			/* dbd */ dbd,
3757			/* page_code */ page_control << 6,
3758			/* page */ mode_page,
3759			/* param_buf */ data,
3760			/* param_len */ datalen,
3761			/* sense_len */ SSD_FULL_SIZE,
3762			/* timeout */ timeout ? timeout : 5000);
3763
3764	if (arglist & CAM_ARG_ERR_RECOVER)
3765		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3766
3767	/* Disable freezing the device queue */
3768	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3769
3770	if (((retval = cam_send_ccb(device, ccb)) < 0)
3771	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3772		if (arglist & CAM_ARG_VERBOSE) {
3773			cam_error_print(device, ccb, CAM_ESF_ALL,
3774					CAM_EPF_ALL, stderr);
3775		}
3776		cam_freeccb(ccb);
3777		cam_close_device(device);
3778		if (retval < 0)
3779			err(1, "error sending mode sense command");
3780		else
3781			errx(1, "error sending mode sense command");
3782	}
3783
3784	cam_freeccb(ccb);
3785}
3786
3787void
3788mode_select(struct cam_device *device, int save_pages, int retry_count,
3789	   int timeout, u_int8_t *data, int datalen)
3790{
3791	union ccb *ccb;
3792	int retval;
3793
3794	ccb = cam_getccb(device);
3795
3796	if (ccb == NULL)
3797		errx(1, "mode_select: couldn't allocate CCB");
3798
3799	bzero(&(&ccb->ccb_h)[1],
3800	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3801
3802	scsi_mode_select(&ccb->csio,
3803			 /* retries */ retry_count,
3804			 /* cbfcnp */ NULL,
3805			 /* tag_action */ MSG_SIMPLE_Q_TAG,
3806			 /* scsi_page_fmt */ 1,
3807			 /* save_pages */ save_pages,
3808			 /* param_buf */ data,
3809			 /* param_len */ datalen,
3810			 /* sense_len */ SSD_FULL_SIZE,
3811			 /* timeout */ timeout ? timeout : 5000);
3812
3813	if (arglist & CAM_ARG_ERR_RECOVER)
3814		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3815
3816	/* Disable freezing the device queue */
3817	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3818
3819	if (((retval = cam_send_ccb(device, ccb)) < 0)
3820	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3821		if (arglist & CAM_ARG_VERBOSE) {
3822			cam_error_print(device, ccb, CAM_ESF_ALL,
3823					CAM_EPF_ALL, stderr);
3824		}
3825		cam_freeccb(ccb);
3826		cam_close_device(device);
3827
3828		if (retval < 0)
3829			err(1, "error sending mode select command");
3830		else
3831			errx(1, "error sending mode select command");
3832
3833	}
3834
3835	cam_freeccb(ccb);
3836}
3837
3838void
3839modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
3840	 int retry_count, int timeout)
3841{
3842	int c, mode_page = -1, page_control = 0;
3843	int binary = 0, list = 0;
3844
3845	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3846		switch(c) {
3847		case 'b':
3848			binary = 1;
3849			break;
3850		case 'd':
3851			arglist |= CAM_ARG_DBD;
3852			break;
3853		case 'e':
3854			arglist |= CAM_ARG_MODE_EDIT;
3855			break;
3856		case 'l':
3857			list = 1;
3858			break;
3859		case 'm':
3860			mode_page = strtol(optarg, NULL, 0);
3861			if (mode_page < 0)
3862				errx(1, "invalid mode page %d", mode_page);
3863			break;
3864		case 'P':
3865			page_control = strtol(optarg, NULL, 0);
3866			if ((page_control < 0) || (page_control > 3))
3867				errx(1, "invalid page control field %d",
3868				     page_control);
3869			arglist |= CAM_ARG_PAGE_CNTL;
3870			break;
3871		default:
3872			break;
3873		}
3874	}
3875
3876	if (mode_page == -1 && list == 0)
3877		errx(1, "you must specify a mode page!");
3878
3879	if (list) {
3880		mode_list(device, page_control, arglist & CAM_ARG_DBD,
3881		    retry_count, timeout);
3882	} else {
3883		mode_edit(device, mode_page, page_control,
3884		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
3885		    retry_count, timeout);
3886	}
3887}
3888
3889static int
3890scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
3891	int retry_count, int timeout)
3892{
3893	union ccb *ccb;
3894	u_int32_t flags = CAM_DIR_NONE;
3895	u_int8_t *data_ptr = NULL;
3896	u_int8_t cdb[20];
3897	u_int8_t atacmd[12];
3898	struct get_hook hook;
3899	int c, data_bytes = 0;
3900	int cdb_len = 0;
3901	int atacmd_len = 0;
3902	int dmacmd = 0;
3903	int fpdmacmd = 0;
3904	int need_res = 0;
3905	char *datastr = NULL, *tstr, *resstr = NULL;
3906	int error = 0;
3907	int fd_data = 0, fd_res = 0;
3908	int retval;
3909
3910	ccb = cam_getccb(device);
3911
3912	if (ccb == NULL) {
3913		warnx("scsicmd: error allocating ccb");
3914		return(1);
3915	}
3916
3917	bzero(&(&ccb->ccb_h)[1],
3918	      sizeof(union ccb) - sizeof(struct ccb_hdr));
3919
3920	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3921		switch(c) {
3922		case 'a':
3923			tstr = optarg;
3924			while (isspace(*tstr) && (*tstr != '\0'))
3925				tstr++;
3926			hook.argc = argc - optind;
3927			hook.argv = argv + optind;
3928			hook.got = 0;
3929			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
3930						    iget, &hook);
3931			/*
3932			 * Increment optind by the number of arguments the
3933			 * encoding routine processed.  After each call to
3934			 * getopt(3), optind points to the argument that
3935			 * getopt should process _next_.  In this case,
3936			 * that means it points to the first command string
3937			 * argument, if there is one.  Once we increment
3938			 * this, it should point to either the next command
3939			 * line argument, or it should be past the end of
3940			 * the list.
3941			 */
3942			optind += hook.got;
3943			break;
3944		case 'c':
3945			tstr = optarg;
3946			while (isspace(*tstr) && (*tstr != '\0'))
3947				tstr++;
3948			hook.argc = argc - optind;
3949			hook.argv = argv + optind;
3950			hook.got = 0;
3951			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
3952						    iget, &hook);
3953			/*
3954			 * Increment optind by the number of arguments the
3955			 * encoding routine processed.  After each call to
3956			 * getopt(3), optind points to the argument that
3957			 * getopt should process _next_.  In this case,
3958			 * that means it points to the first command string
3959			 * argument, if there is one.  Once we increment
3960			 * this, it should point to either the next command
3961			 * line argument, or it should be past the end of
3962			 * the list.
3963			 */
3964			optind += hook.got;
3965			break;
3966		case 'd':
3967			dmacmd = 1;
3968			break;
3969		case 'f':
3970			fpdmacmd = 1;
3971			break;
3972		case 'i':
3973			if (arglist & CAM_ARG_CMD_OUT) {
3974				warnx("command must either be "
3975				      "read or write, not both");
3976				error = 1;
3977				goto scsicmd_bailout;
3978			}
3979			arglist |= CAM_ARG_CMD_IN;
3980			flags = CAM_DIR_IN;
3981			data_bytes = strtol(optarg, NULL, 0);
3982			if (data_bytes <= 0) {
3983				warnx("invalid number of input bytes %d",
3984				      data_bytes);
3985				error = 1;
3986				goto scsicmd_bailout;
3987			}
3988			hook.argc = argc - optind;
3989			hook.argv = argv + optind;
3990			hook.got = 0;
3991			optind++;
3992			datastr = cget(&hook, NULL);
3993			/*
3994			 * If the user supplied "-" instead of a format, he
3995			 * wants the data to be written to stdout.
3996			 */
3997			if ((datastr != NULL)
3998			 && (datastr[0] == '-'))
3999				fd_data = 1;
4000
4001			data_ptr = (u_int8_t *)malloc(data_bytes);
4002			if (data_ptr == NULL) {
4003				warnx("can't malloc memory for data_ptr");
4004				error = 1;
4005				goto scsicmd_bailout;
4006			}
4007			break;
4008		case 'o':
4009			if (arglist & CAM_ARG_CMD_IN) {
4010				warnx("command must either be "
4011				      "read or write, not both");
4012				error = 1;
4013				goto scsicmd_bailout;
4014			}
4015			arglist |= CAM_ARG_CMD_OUT;
4016			flags = CAM_DIR_OUT;
4017			data_bytes = strtol(optarg, NULL, 0);
4018			if (data_bytes <= 0) {
4019				warnx("invalid number of output bytes %d",
4020				      data_bytes);
4021				error = 1;
4022				goto scsicmd_bailout;
4023			}
4024			hook.argc = argc - optind;
4025			hook.argv = argv + optind;
4026			hook.got = 0;
4027			datastr = cget(&hook, NULL);
4028			data_ptr = (u_int8_t *)malloc(data_bytes);
4029			if (data_ptr == NULL) {
4030				warnx("can't malloc memory for data_ptr");
4031				error = 1;
4032				goto scsicmd_bailout;
4033			}
4034			bzero(data_ptr, data_bytes);
4035			/*
4036			 * If the user supplied "-" instead of a format, he
4037			 * wants the data to be read from stdin.
4038			 */
4039			if ((datastr != NULL)
4040			 && (datastr[0] == '-'))
4041				fd_data = 1;
4042			else
4043				buff_encode_visit(data_ptr, data_bytes, datastr,
4044						  iget, &hook);
4045			optind += hook.got;
4046			break;
4047		case 'r':
4048			need_res = 1;
4049			hook.argc = argc - optind;
4050			hook.argv = argv + optind;
4051			hook.got = 0;
4052			resstr = cget(&hook, NULL);
4053			if ((resstr != NULL) && (resstr[0] == '-'))
4054				fd_res = 1;
4055			optind += hook.got;
4056			break;
4057		default:
4058			break;
4059		}
4060	}
4061
4062	/*
4063	 * If fd_data is set, and we're writing to the device, we need to
4064	 * read the data the user wants written from stdin.
4065	 */
4066	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4067		ssize_t amt_read;
4068		int amt_to_read = data_bytes;
4069		u_int8_t *buf_ptr = data_ptr;
4070
4071		for (amt_read = 0; amt_to_read > 0;
4072		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4073			if (amt_read == -1) {
4074				warn("error reading data from stdin");
4075				error = 1;
4076				goto scsicmd_bailout;
4077			}
4078			amt_to_read -= amt_read;
4079			buf_ptr += amt_read;
4080		}
4081	}
4082
4083	if (arglist & CAM_ARG_ERR_RECOVER)
4084		flags |= CAM_PASS_ERR_RECOVER;
4085
4086	/* Disable freezing the device queue */
4087	flags |= CAM_DEV_QFRZDIS;
4088
4089	if (cdb_len) {
4090		/*
4091		 * This is taken from the SCSI-3 draft spec.
4092		 * (T10/1157D revision 0.3)
4093		 * The top 3 bits of an opcode are the group code.
4094		 * The next 5 bits are the command code.
4095		 * Group 0:  six byte commands
4096		 * Group 1:  ten byte commands
4097		 * Group 2:  ten byte commands
4098		 * Group 3:  reserved
4099		 * Group 4:  sixteen byte commands
4100		 * Group 5:  twelve byte commands
4101		 * Group 6:  vendor specific
4102		 * Group 7:  vendor specific
4103		 */
4104		switch((cdb[0] >> 5) & 0x7) {
4105			case 0:
4106				cdb_len = 6;
4107				break;
4108			case 1:
4109			case 2:
4110				cdb_len = 10;
4111				break;
4112			case 3:
4113			case 6:
4114			case 7:
4115			        /* computed by buff_encode_visit */
4116				break;
4117			case 4:
4118				cdb_len = 16;
4119				break;
4120			case 5:
4121				cdb_len = 12;
4122				break;
4123		}
4124
4125		/*
4126		 * We should probably use csio_build_visit or something like that
4127		 * here, but it's easier to encode arguments as you go.  The
4128		 * alternative would be skipping the CDB argument and then encoding
4129		 * it here, since we've got the data buffer argument by now.
4130		 */
4131		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4132
4133		cam_fill_csio(&ccb->csio,
4134		      /*retries*/ retry_count,
4135		      /*cbfcnp*/ NULL,
4136		      /*flags*/ flags,
4137		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
4138		      /*data_ptr*/ data_ptr,
4139		      /*dxfer_len*/ data_bytes,
4140		      /*sense_len*/ SSD_FULL_SIZE,
4141		      /*cdb_len*/ cdb_len,
4142		      /*timeout*/ timeout ? timeout : 5000);
4143	} else {
4144		atacmd_len = 12;
4145		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4146		if (need_res)
4147			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4148		if (dmacmd)
4149			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4150		if (fpdmacmd)
4151			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4152
4153		cam_fill_ataio(&ccb->ataio,
4154		      /*retries*/ retry_count,
4155		      /*cbfcnp*/ NULL,
4156		      /*flags*/ flags,
4157		      /*tag_action*/ 0,
4158		      /*data_ptr*/ data_ptr,
4159		      /*dxfer_len*/ data_bytes,
4160		      /*timeout*/ timeout ? timeout : 5000);
4161	}
4162
4163	if (((retval = cam_send_ccb(device, ccb)) < 0)
4164	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4165		const char warnstr[] = "error sending command";
4166
4167		if (retval < 0)
4168			warn(warnstr);
4169		else
4170			warnx(warnstr);
4171
4172		if (arglist & CAM_ARG_VERBOSE) {
4173			cam_error_print(device, ccb, CAM_ESF_ALL,
4174					CAM_EPF_ALL, stderr);
4175		}
4176
4177		error = 1;
4178		goto scsicmd_bailout;
4179	}
4180
4181	if (atacmd_len && need_res) {
4182		if (fd_res == 0) {
4183			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4184					  arg_put, NULL);
4185			fprintf(stdout, "\n");
4186		} else {
4187			fprintf(stdout,
4188			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4189			    ccb->ataio.res.status,
4190			    ccb->ataio.res.error,
4191			    ccb->ataio.res.lba_low,
4192			    ccb->ataio.res.lba_mid,
4193			    ccb->ataio.res.lba_high,
4194			    ccb->ataio.res.device,
4195			    ccb->ataio.res.lba_low_exp,
4196			    ccb->ataio.res.lba_mid_exp,
4197			    ccb->ataio.res.lba_high_exp,
4198			    ccb->ataio.res.sector_count,
4199			    ccb->ataio.res.sector_count_exp);
4200			fflush(stdout);
4201		}
4202	}
4203
4204	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4205	 && (arglist & CAM_ARG_CMD_IN)
4206	 && (data_bytes > 0)) {
4207		if (fd_data == 0) {
4208			buff_decode_visit(data_ptr, data_bytes, datastr,
4209					  arg_put, NULL);
4210			fprintf(stdout, "\n");
4211		} else {
4212			ssize_t amt_written;
4213			int amt_to_write = data_bytes;
4214			u_int8_t *buf_ptr = data_ptr;
4215
4216			for (amt_written = 0; (amt_to_write > 0) &&
4217			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4218				amt_to_write -= amt_written;
4219				buf_ptr += amt_written;
4220			}
4221			if (amt_written == -1) {
4222				warn("error writing data to stdout");
4223				error = 1;
4224				goto scsicmd_bailout;
4225			} else if ((amt_written == 0)
4226				&& (amt_to_write > 0)) {
4227				warnx("only wrote %u bytes out of %u",
4228				      data_bytes - amt_to_write, data_bytes);
4229			}
4230		}
4231	}
4232
4233scsicmd_bailout:
4234
4235	if ((data_bytes > 0) && (data_ptr != NULL))
4236		free(data_ptr);
4237
4238	cam_freeccb(ccb);
4239
4240	return(error);
4241}
4242
4243static int
4244camdebug(int argc, char **argv, char *combinedopt)
4245{
4246	int c, fd;
4247	path_id_t bus = CAM_BUS_WILDCARD;
4248	target_id_t target = CAM_TARGET_WILDCARD;
4249	lun_id_t lun = CAM_LUN_WILDCARD;
4250	char *tstr, *tmpstr = NULL;
4251	union ccb ccb;
4252	int error = 0;
4253
4254	bzero(&ccb, sizeof(union ccb));
4255
4256	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4257		switch(c) {
4258		case 'I':
4259			arglist |= CAM_ARG_DEBUG_INFO;
4260			ccb.cdbg.flags |= CAM_DEBUG_INFO;
4261			break;
4262		case 'P':
4263			arglist |= CAM_ARG_DEBUG_PERIPH;
4264			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4265			break;
4266		case 'S':
4267			arglist |= CAM_ARG_DEBUG_SUBTRACE;
4268			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4269			break;
4270		case 'T':
4271			arglist |= CAM_ARG_DEBUG_TRACE;
4272			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4273			break;
4274		case 'X':
4275			arglist |= CAM_ARG_DEBUG_XPT;
4276			ccb.cdbg.flags |= CAM_DEBUG_XPT;
4277			break;
4278		case 'c':
4279			arglist |= CAM_ARG_DEBUG_CDB;
4280			ccb.cdbg.flags |= CAM_DEBUG_CDB;
4281			break;
4282		case 'p':
4283			arglist |= CAM_ARG_DEBUG_PROBE;
4284			ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4285			break;
4286		default:
4287			break;
4288		}
4289	}
4290
4291	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4292		warnx("error opening transport layer device %s", XPT_DEVICE);
4293		warn("%s", XPT_DEVICE);
4294		return(1);
4295	}
4296	argc -= optind;
4297	argv += optind;
4298
4299	if (argc <= 0) {
4300		warnx("you must specify \"off\", \"all\" or a bus,");
4301		warnx("bus:target, or bus:target:lun");
4302		close(fd);
4303		return(1);
4304	}
4305
4306	tstr = *argv;
4307
4308	while (isspace(*tstr) && (*tstr != '\0'))
4309		tstr++;
4310
4311	if (strncmp(tstr, "off", 3) == 0) {
4312		ccb.cdbg.flags = CAM_DEBUG_NONE;
4313		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4314			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4315			     CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4316	} else if (strncmp(tstr, "all", 3) != 0) {
4317		tmpstr = (char *)strtok(tstr, ":");
4318		if ((tmpstr != NULL) && (*tmpstr != '\0')){
4319			bus = strtol(tmpstr, NULL, 0);
4320			arglist |= CAM_ARG_BUS;
4321			tmpstr = (char *)strtok(NULL, ":");
4322			if ((tmpstr != NULL) && (*tmpstr != '\0')){
4323				target = strtol(tmpstr, NULL, 0);
4324				arglist |= CAM_ARG_TARGET;
4325				tmpstr = (char *)strtok(NULL, ":");
4326				if ((tmpstr != NULL) && (*tmpstr != '\0')){
4327					lun = strtol(tmpstr, NULL, 0);
4328					arglist |= CAM_ARG_LUN;
4329				}
4330			}
4331		} else {
4332			error = 1;
4333			warnx("you must specify \"all\", \"off\", or a bus,");
4334			warnx("bus:target, or bus:target:lun to debug");
4335		}
4336	}
4337
4338	if (error == 0) {
4339
4340		ccb.ccb_h.func_code = XPT_DEBUG;
4341		ccb.ccb_h.path_id = bus;
4342		ccb.ccb_h.target_id = target;
4343		ccb.ccb_h.target_lun = lun;
4344
4345		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4346			warn("CAMIOCOMMAND ioctl failed");
4347			error = 1;
4348		}
4349
4350		if (error == 0) {
4351			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4352			     CAM_FUNC_NOTAVAIL) {
4353				warnx("CAM debugging not available");
4354				warnx("you need to put options CAMDEBUG in"
4355				      " your kernel config file!");
4356				error = 1;
4357			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4358				    CAM_REQ_CMP) {
4359				warnx("XPT_DEBUG CCB failed with status %#x",
4360				      ccb.ccb_h.status);
4361				error = 1;
4362			} else {
4363				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4364					fprintf(stderr,
4365						"Debugging turned off\n");
4366				} else {
4367					fprintf(stderr,
4368						"Debugging enabled for "
4369						"%d:%d:%jx\n",
4370						bus, target, (uintmax_t)lun);
4371				}
4372			}
4373		}
4374		close(fd);
4375	}
4376
4377	return(error);
4378}
4379
4380static int
4381tagcontrol(struct cam_device *device, int argc, char **argv,
4382	   char *combinedopt)
4383{
4384	int c;
4385	union ccb *ccb;
4386	int numtags = -1;
4387	int retval = 0;
4388	int quiet = 0;
4389	char pathstr[1024];
4390
4391	ccb = cam_getccb(device);
4392
4393	if (ccb == NULL) {
4394		warnx("tagcontrol: error allocating ccb");
4395		return(1);
4396	}
4397
4398	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4399		switch(c) {
4400		case 'N':
4401			numtags = strtol(optarg, NULL, 0);
4402			if (numtags < 0) {
4403				warnx("tag count %d is < 0", numtags);
4404				retval = 1;
4405				goto tagcontrol_bailout;
4406			}
4407			break;
4408		case 'q':
4409			quiet++;
4410			break;
4411		default:
4412			break;
4413		}
4414	}
4415
4416	cam_path_string(device, pathstr, sizeof(pathstr));
4417
4418	if (numtags >= 0) {
4419		bzero(&(&ccb->ccb_h)[1],
4420		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4421		ccb->ccb_h.func_code = XPT_REL_SIMQ;
4422		ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4423		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4424		ccb->crs.openings = numtags;
4425
4426
4427		if (cam_send_ccb(device, ccb) < 0) {
4428			perror("error sending XPT_REL_SIMQ CCB");
4429			retval = 1;
4430			goto tagcontrol_bailout;
4431		}
4432
4433		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4434			warnx("XPT_REL_SIMQ CCB failed");
4435			cam_error_print(device, ccb, CAM_ESF_ALL,
4436					CAM_EPF_ALL, stderr);
4437			retval = 1;
4438			goto tagcontrol_bailout;
4439		}
4440
4441
4442		if (quiet == 0)
4443			fprintf(stdout, "%stagged openings now %d\n",
4444				pathstr, ccb->crs.openings);
4445	}
4446
4447	bzero(&(&ccb->ccb_h)[1],
4448	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4449
4450	ccb->ccb_h.func_code = XPT_GDEV_STATS;
4451
4452	if (cam_send_ccb(device, ccb) < 0) {
4453		perror("error sending XPT_GDEV_STATS CCB");
4454		retval = 1;
4455		goto tagcontrol_bailout;
4456	}
4457
4458	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4459		warnx("XPT_GDEV_STATS CCB failed");
4460		cam_error_print(device, ccb, CAM_ESF_ALL,
4461				CAM_EPF_ALL, stderr);
4462		retval = 1;
4463		goto tagcontrol_bailout;
4464	}
4465
4466	if (arglist & CAM_ARG_VERBOSE) {
4467		fprintf(stdout, "%s", pathstr);
4468		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4469		fprintf(stdout, "%s", pathstr);
4470		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4471		fprintf(stdout, "%s", pathstr);
4472		fprintf(stdout, "allocated     %d\n", ccb->cgds.allocated);
4473		fprintf(stdout, "%s", pathstr);
4474		fprintf(stdout, "queued        %d\n", ccb->cgds.queued);
4475		fprintf(stdout, "%s", pathstr);
4476		fprintf(stdout, "held          %d\n", ccb->cgds.held);
4477		fprintf(stdout, "%s", pathstr);
4478		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4479		fprintf(stdout, "%s", pathstr);
4480		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4481	} else {
4482		if (quiet == 0) {
4483			fprintf(stdout, "%s", pathstr);
4484			fprintf(stdout, "device openings: ");
4485		}
4486		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4487			ccb->cgds.dev_active);
4488	}
4489
4490tagcontrol_bailout:
4491
4492	cam_freeccb(ccb);
4493	return(retval);
4494}
4495
4496static void
4497cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4498{
4499	char pathstr[1024];
4500
4501	cam_path_string(device, pathstr, sizeof(pathstr));
4502
4503	if (cts->transport == XPORT_SPI) {
4504		struct ccb_trans_settings_spi *spi =
4505		    &cts->xport_specific.spi;
4506
4507		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4508
4509			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4510				spi->sync_period);
4511
4512			if (spi->sync_offset != 0) {
4513				u_int freq;
4514
4515				freq = scsi_calc_syncsrate(spi->sync_period);
4516				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4517					pathstr, freq / 1000, freq % 1000);
4518			}
4519		}
4520
4521		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4522			fprintf(stdout, "%soffset: %d\n", pathstr,
4523			    spi->sync_offset);
4524		}
4525
4526		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4527			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4528				(0x01 << spi->bus_width) * 8);
4529		}
4530
4531		if (spi->valid & CTS_SPI_VALID_DISC) {
4532			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4533				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4534				"enabled" : "disabled");
4535		}
4536	}
4537	if (cts->transport == XPORT_FC) {
4538		struct ccb_trans_settings_fc *fc =
4539		    &cts->xport_specific.fc;
4540
4541		if (fc->valid & CTS_FC_VALID_WWNN)
4542			fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4543			    (long long) fc->wwnn);
4544		if (fc->valid & CTS_FC_VALID_WWPN)
4545			fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4546			    (long long) fc->wwpn);
4547		if (fc->valid & CTS_FC_VALID_PORT)
4548			fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4549		if (fc->valid & CTS_FC_VALID_SPEED)
4550			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4551			    pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4552	}
4553	if (cts->transport == XPORT_SAS) {
4554		struct ccb_trans_settings_sas *sas =
4555		    &cts->xport_specific.sas;
4556
4557		if (sas->valid & CTS_SAS_VALID_SPEED)
4558			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4559			    pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4560	}
4561	if (cts->transport == XPORT_ATA) {
4562		struct ccb_trans_settings_pata *pata =
4563		    &cts->xport_specific.ata;
4564
4565		if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4566			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4567				ata_mode2string(pata->mode));
4568		}
4569		if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4570			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4571				pata->atapi);
4572		}
4573		if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4574			fprintf(stdout, "%sPIO transaction length: %d\n",
4575				pathstr, pata->bytecount);
4576		}
4577	}
4578	if (cts->transport == XPORT_SATA) {
4579		struct ccb_trans_settings_sata *sata =
4580		    &cts->xport_specific.sata;
4581
4582		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4583			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4584				sata->revision);
4585		}
4586		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4587			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4588				ata_mode2string(sata->mode));
4589		}
4590		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4591			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4592				sata->atapi);
4593		}
4594		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4595			fprintf(stdout, "%sPIO transaction length: %d\n",
4596				pathstr, sata->bytecount);
4597		}
4598		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4599			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4600				sata->pm_present);
4601		}
4602		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4603			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4604				sata->tags);
4605		}
4606		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4607			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4608				sata->caps);
4609		}
4610	}
4611	if (cts->protocol == PROTO_ATA) {
4612		struct ccb_trans_settings_ata *ata=
4613		    &cts->proto_specific.ata;
4614
4615		if (ata->valid & CTS_ATA_VALID_TQ) {
4616			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4617				(ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4618				"enabled" : "disabled");
4619		}
4620	}
4621	if (cts->protocol == PROTO_SCSI) {
4622		struct ccb_trans_settings_scsi *scsi=
4623		    &cts->proto_specific.scsi;
4624
4625		if (scsi->valid & CTS_SCSI_VALID_TQ) {
4626			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4627				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4628				"enabled" : "disabled");
4629		}
4630	}
4631
4632}
4633
4634/*
4635 * Get a path inquiry CCB for the specified device.
4636 */
4637static int
4638get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4639{
4640	union ccb *ccb;
4641	int retval = 0;
4642
4643	ccb = cam_getccb(device);
4644	if (ccb == NULL) {
4645		warnx("get_cpi: couldn't allocate CCB");
4646		return(1);
4647	}
4648	bzero(&(&ccb->ccb_h)[1],
4649	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4650	ccb->ccb_h.func_code = XPT_PATH_INQ;
4651	if (cam_send_ccb(device, ccb) < 0) {
4652		warn("get_cpi: error sending Path Inquiry CCB");
4653		if (arglist & CAM_ARG_VERBOSE)
4654			cam_error_print(device, ccb, CAM_ESF_ALL,
4655					CAM_EPF_ALL, stderr);
4656		retval = 1;
4657		goto get_cpi_bailout;
4658	}
4659	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4660		if (arglist & CAM_ARG_VERBOSE)
4661			cam_error_print(device, ccb, CAM_ESF_ALL,
4662					CAM_EPF_ALL, stderr);
4663		retval = 1;
4664		goto get_cpi_bailout;
4665	}
4666	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4667
4668get_cpi_bailout:
4669	cam_freeccb(ccb);
4670	return(retval);
4671}
4672
4673/*
4674 * Get a get device CCB for the specified device.
4675 */
4676static int
4677get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4678{
4679	union ccb *ccb;
4680	int retval = 0;
4681
4682	ccb = cam_getccb(device);
4683	if (ccb == NULL) {
4684		warnx("get_cgd: couldn't allocate CCB");
4685		return(1);
4686	}
4687	bzero(&(&ccb->ccb_h)[1],
4688	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4689	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4690	if (cam_send_ccb(device, ccb) < 0) {
4691		warn("get_cgd: error sending Path Inquiry CCB");
4692		if (arglist & CAM_ARG_VERBOSE)
4693			cam_error_print(device, ccb, CAM_ESF_ALL,
4694					CAM_EPF_ALL, stderr);
4695		retval = 1;
4696		goto get_cgd_bailout;
4697	}
4698	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4699		if (arglist & CAM_ARG_VERBOSE)
4700			cam_error_print(device, ccb, CAM_ESF_ALL,
4701					CAM_EPF_ALL, stderr);
4702		retval = 1;
4703		goto get_cgd_bailout;
4704	}
4705	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4706
4707get_cgd_bailout:
4708	cam_freeccb(ccb);
4709	return(retval);
4710}
4711
4712/* return the type of disk (really the command type) */
4713static const char *
4714get_disk_type(struct cam_device *device)
4715{
4716	struct ccb_getdev	cgd;
4717
4718	(void) memset(&cgd, 0x0, sizeof(cgd));
4719	get_cgd(device, &cgd);
4720	switch(cgd.protocol) {
4721	case PROTO_SCSI:
4722		return "scsi";
4723	case PROTO_ATA:
4724	case PROTO_ATAPI:
4725	case PROTO_SATAPM:
4726		return "ata";
4727	default:
4728		return "unknown";
4729	}
4730}
4731
4732static void
4733cpi_print(struct ccb_pathinq *cpi)
4734{
4735	char adapter_str[1024];
4736	int i;
4737
4738	snprintf(adapter_str, sizeof(adapter_str),
4739		 "%s%d:", cpi->dev_name, cpi->unit_number);
4740
4741	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
4742		cpi->version_num);
4743
4744	for (i = 1; i < 0xff; i = i << 1) {
4745		const char *str;
4746
4747		if ((i & cpi->hba_inquiry) == 0)
4748			continue;
4749
4750		fprintf(stdout, "%s supports ", adapter_str);
4751
4752		switch(i) {
4753		case PI_MDP_ABLE:
4754			str = "MDP message";
4755			break;
4756		case PI_WIDE_32:
4757			str = "32 bit wide SCSI";
4758			break;
4759		case PI_WIDE_16:
4760			str = "16 bit wide SCSI";
4761			break;
4762		case PI_SDTR_ABLE:
4763			str = "SDTR message";
4764			break;
4765		case PI_LINKED_CDB:
4766			str = "linked CDBs";
4767			break;
4768		case PI_TAG_ABLE:
4769			str = "tag queue messages";
4770			break;
4771		case PI_SOFT_RST:
4772			str = "soft reset alternative";
4773			break;
4774		case PI_SATAPM:
4775			str = "SATA Port Multiplier";
4776			break;
4777		default:
4778			str = "unknown PI bit set";
4779			break;
4780		}
4781		fprintf(stdout, "%s\n", str);
4782	}
4783
4784	for (i = 1; i < 0xff; i = i << 1) {
4785		const char *str;
4786
4787		if ((i & cpi->hba_misc) == 0)
4788			continue;
4789
4790		fprintf(stdout, "%s ", adapter_str);
4791
4792		switch(i) {
4793		case PIM_SCANHILO:
4794			str = "bus scans from high ID to low ID";
4795			break;
4796		case PIM_NOREMOVE:
4797			str = "removable devices not included in scan";
4798			break;
4799		case PIM_NOINITIATOR:
4800			str = "initiator role not supported";
4801			break;
4802		case PIM_NOBUSRESET:
4803			str = "user has disabled initial BUS RESET or"
4804			      " controller is in target/mixed mode";
4805			break;
4806		case PIM_NO_6_BYTE:
4807			str = "do not send 6-byte commands";
4808			break;
4809		case PIM_SEQSCAN:
4810			str = "scan bus sequentially";
4811			break;
4812		default:
4813			str = "unknown PIM bit set";
4814			break;
4815		}
4816		fprintf(stdout, "%s\n", str);
4817	}
4818
4819	for (i = 1; i < 0xff; i = i << 1) {
4820		const char *str;
4821
4822		if ((i & cpi->target_sprt) == 0)
4823			continue;
4824
4825		fprintf(stdout, "%s supports ", adapter_str);
4826		switch(i) {
4827		case PIT_PROCESSOR:
4828			str = "target mode processor mode";
4829			break;
4830		case PIT_PHASE:
4831			str = "target mode phase cog. mode";
4832			break;
4833		case PIT_DISCONNECT:
4834			str = "disconnects in target mode";
4835			break;
4836		case PIT_TERM_IO:
4837			str = "terminate I/O message in target mode";
4838			break;
4839		case PIT_GRP_6:
4840			str = "group 6 commands in target mode";
4841			break;
4842		case PIT_GRP_7:
4843			str = "group 7 commands in target mode";
4844			break;
4845		default:
4846			str = "unknown PIT bit set";
4847			break;
4848		}
4849
4850		fprintf(stdout, "%s\n", str);
4851	}
4852	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
4853		cpi->hba_eng_cnt);
4854	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
4855		cpi->max_target);
4856	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
4857		cpi->max_lun);
4858	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
4859		adapter_str, cpi->hpath_id);
4860	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
4861		cpi->initiator_id);
4862	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
4863	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
4864	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
4865	    adapter_str, cpi->hba_vendor);
4866	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
4867	    adapter_str, cpi->hba_device);
4868	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
4869	    adapter_str, cpi->hba_subvendor);
4870	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
4871	    adapter_str, cpi->hba_subdevice);
4872	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
4873	fprintf(stdout, "%s base transfer speed: ", adapter_str);
4874	if (cpi->base_transfer_speed > 1000)
4875		fprintf(stdout, "%d.%03dMB/sec\n",
4876			cpi->base_transfer_speed / 1000,
4877			cpi->base_transfer_speed % 1000);
4878	else
4879		fprintf(stdout, "%dKB/sec\n",
4880			(cpi->base_transfer_speed % 1000) * 1000);
4881	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
4882	    adapter_str, cpi->maxio);
4883}
4884
4885static int
4886get_print_cts(struct cam_device *device, int user_settings, int quiet,
4887	      struct ccb_trans_settings *cts)
4888{
4889	int retval;
4890	union ccb *ccb;
4891
4892	retval = 0;
4893	ccb = cam_getccb(device);
4894
4895	if (ccb == NULL) {
4896		warnx("get_print_cts: error allocating ccb");
4897		return(1);
4898	}
4899
4900	bzero(&(&ccb->ccb_h)[1],
4901	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
4902
4903	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
4904
4905	if (user_settings == 0)
4906		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
4907	else
4908		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
4909
4910	if (cam_send_ccb(device, ccb) < 0) {
4911		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
4912		if (arglist & CAM_ARG_VERBOSE)
4913			cam_error_print(device, ccb, CAM_ESF_ALL,
4914					CAM_EPF_ALL, stderr);
4915		retval = 1;
4916		goto get_print_cts_bailout;
4917	}
4918
4919	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4920		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
4921		if (arglist & CAM_ARG_VERBOSE)
4922			cam_error_print(device, ccb, CAM_ESF_ALL,
4923					CAM_EPF_ALL, stderr);
4924		retval = 1;
4925		goto get_print_cts_bailout;
4926	}
4927
4928	if (quiet == 0)
4929		cts_print(device, &ccb->cts);
4930
4931	if (cts != NULL)
4932		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
4933
4934get_print_cts_bailout:
4935
4936	cam_freeccb(ccb);
4937
4938	return(retval);
4939}
4940
4941static int
4942ratecontrol(struct cam_device *device, int retry_count, int timeout,
4943	    int argc, char **argv, char *combinedopt)
4944{
4945	int c;
4946	union ccb *ccb;
4947	int user_settings = 0;
4948	int retval = 0;
4949	int disc_enable = -1, tag_enable = -1;
4950	int mode = -1;
4951	int offset = -1;
4952	double syncrate = -1;
4953	int bus_width = -1;
4954	int quiet = 0;
4955	int change_settings = 0, send_tur = 0;
4956	struct ccb_pathinq cpi;
4957
4958	ccb = cam_getccb(device);
4959	if (ccb == NULL) {
4960		warnx("ratecontrol: error allocating ccb");
4961		return(1);
4962	}
4963	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4964		switch(c){
4965		case 'a':
4966			send_tur = 1;
4967			break;
4968		case 'c':
4969			user_settings = 0;
4970			break;
4971		case 'D':
4972			if (strncasecmp(optarg, "enable", 6) == 0)
4973				disc_enable = 1;
4974			else if (strncasecmp(optarg, "disable", 7) == 0)
4975				disc_enable = 0;
4976			else {
4977				warnx("-D argument \"%s\" is unknown", optarg);
4978				retval = 1;
4979				goto ratecontrol_bailout;
4980			}
4981			change_settings = 1;
4982			break;
4983		case 'M':
4984			mode = ata_string2mode(optarg);
4985			if (mode < 0) {
4986				warnx("unknown mode '%s'", optarg);
4987				retval = 1;
4988				goto ratecontrol_bailout;
4989			}
4990			change_settings = 1;
4991			break;
4992		case 'O':
4993			offset = strtol(optarg, NULL, 0);
4994			if (offset < 0) {
4995				warnx("offset value %d is < 0", offset);
4996				retval = 1;
4997				goto ratecontrol_bailout;
4998			}
4999			change_settings = 1;
5000			break;
5001		case 'q':
5002			quiet++;
5003			break;
5004		case 'R':
5005			syncrate = atof(optarg);
5006			if (syncrate < 0) {
5007				warnx("sync rate %f is < 0", syncrate);
5008				retval = 1;
5009				goto ratecontrol_bailout;
5010			}
5011			change_settings = 1;
5012			break;
5013		case 'T':
5014			if (strncasecmp(optarg, "enable", 6) == 0)
5015				tag_enable = 1;
5016			else if (strncasecmp(optarg, "disable", 7) == 0)
5017				tag_enable = 0;
5018			else {
5019				warnx("-T argument \"%s\" is unknown", optarg);
5020				retval = 1;
5021				goto ratecontrol_bailout;
5022			}
5023			change_settings = 1;
5024			break;
5025		case 'U':
5026			user_settings = 1;
5027			break;
5028		case 'W':
5029			bus_width = strtol(optarg, NULL, 0);
5030			if (bus_width < 0) {
5031				warnx("bus width %d is < 0", bus_width);
5032				retval = 1;
5033				goto ratecontrol_bailout;
5034			}
5035			change_settings = 1;
5036			break;
5037		default:
5038			break;
5039		}
5040	}
5041	bzero(&(&ccb->ccb_h)[1],
5042	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5043	/*
5044	 * Grab path inquiry information, so we can determine whether
5045	 * or not the initiator is capable of the things that the user
5046	 * requests.
5047	 */
5048	ccb->ccb_h.func_code = XPT_PATH_INQ;
5049	if (cam_send_ccb(device, ccb) < 0) {
5050		perror("error sending XPT_PATH_INQ CCB");
5051		if (arglist & CAM_ARG_VERBOSE) {
5052			cam_error_print(device, ccb, CAM_ESF_ALL,
5053					CAM_EPF_ALL, stderr);
5054		}
5055		retval = 1;
5056		goto ratecontrol_bailout;
5057	}
5058	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5059		warnx("XPT_PATH_INQ CCB failed");
5060		if (arglist & CAM_ARG_VERBOSE) {
5061			cam_error_print(device, ccb, CAM_ESF_ALL,
5062					CAM_EPF_ALL, stderr);
5063		}
5064		retval = 1;
5065		goto ratecontrol_bailout;
5066	}
5067	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5068	bzero(&(&ccb->ccb_h)[1],
5069	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5070	if (quiet == 0) {
5071		fprintf(stdout, "%s parameters:\n",
5072		    user_settings ? "User" : "Current");
5073	}
5074	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5075	if (retval != 0)
5076		goto ratecontrol_bailout;
5077
5078	if (arglist & CAM_ARG_VERBOSE)
5079		cpi_print(&cpi);
5080
5081	if (change_settings) {
5082		int didsettings = 0;
5083		struct ccb_trans_settings_spi *spi = NULL;
5084		struct ccb_trans_settings_pata *pata = NULL;
5085		struct ccb_trans_settings_sata *sata = NULL;
5086		struct ccb_trans_settings_ata *ata = NULL;
5087		struct ccb_trans_settings_scsi *scsi = NULL;
5088
5089		if (ccb->cts.transport == XPORT_SPI)
5090			spi = &ccb->cts.xport_specific.spi;
5091		if (ccb->cts.transport == XPORT_ATA)
5092			pata = &ccb->cts.xport_specific.ata;
5093		if (ccb->cts.transport == XPORT_SATA)
5094			sata = &ccb->cts.xport_specific.sata;
5095		if (ccb->cts.protocol == PROTO_ATA)
5096			ata = &ccb->cts.proto_specific.ata;
5097		if (ccb->cts.protocol == PROTO_SCSI)
5098			scsi = &ccb->cts.proto_specific.scsi;
5099		ccb->cts.xport_specific.valid = 0;
5100		ccb->cts.proto_specific.valid = 0;
5101		if (spi && disc_enable != -1) {
5102			spi->valid |= CTS_SPI_VALID_DISC;
5103			if (disc_enable == 0)
5104				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5105			else
5106				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5107			didsettings++;
5108		}
5109		if (tag_enable != -1) {
5110			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5111				warnx("HBA does not support tagged queueing, "
5112				      "so you cannot modify tag settings");
5113				retval = 1;
5114				goto ratecontrol_bailout;
5115			}
5116			if (ata) {
5117				ata->valid |= CTS_SCSI_VALID_TQ;
5118				if (tag_enable == 0)
5119					ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5120				else
5121					ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5122				didsettings++;
5123			} else if (scsi) {
5124				scsi->valid |= CTS_SCSI_VALID_TQ;
5125				if (tag_enable == 0)
5126					scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5127				else
5128					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5129				didsettings++;
5130			}
5131		}
5132		if (spi && offset != -1) {
5133			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5134				warnx("HBA is not capable of changing offset");
5135				retval = 1;
5136				goto ratecontrol_bailout;
5137			}
5138			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5139			spi->sync_offset = offset;
5140			didsettings++;
5141		}
5142		if (spi && syncrate != -1) {
5143			int prelim_sync_period;
5144
5145			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5146				warnx("HBA is not capable of changing "
5147				      "transfer rates");
5148				retval = 1;
5149				goto ratecontrol_bailout;
5150			}
5151			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5152			/*
5153			 * The sync rate the user gives us is in MHz.
5154			 * We need to translate it into KHz for this
5155			 * calculation.
5156			 */
5157			syncrate *= 1000;
5158			/*
5159			 * Next, we calculate a "preliminary" sync period
5160			 * in tenths of a nanosecond.
5161			 */
5162			if (syncrate == 0)
5163				prelim_sync_period = 0;
5164			else
5165				prelim_sync_period = 10000000 / syncrate;
5166			spi->sync_period =
5167				scsi_calc_syncparam(prelim_sync_period);
5168			didsettings++;
5169		}
5170		if (sata && syncrate != -1) {
5171			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5172				warnx("HBA is not capable of changing "
5173				      "transfer rates");
5174				retval = 1;
5175				goto ratecontrol_bailout;
5176			}
5177			if  (!user_settings) {
5178				warnx("You can modify only user rate "
5179				    "settings for SATA");
5180				retval = 1;
5181				goto ratecontrol_bailout;
5182			}
5183			sata->revision = ata_speed2revision(syncrate * 100);
5184			if (sata->revision < 0) {
5185				warnx("Invalid rate %f", syncrate);
5186				retval = 1;
5187				goto ratecontrol_bailout;
5188			}
5189			sata->valid |= CTS_SATA_VALID_REVISION;
5190			didsettings++;
5191		}
5192		if ((pata || sata) && mode != -1) {
5193			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5194				warnx("HBA is not capable of changing "
5195				      "transfer rates");
5196				retval = 1;
5197				goto ratecontrol_bailout;
5198			}
5199			if  (!user_settings) {
5200				warnx("You can modify only user mode "
5201				    "settings for ATA/SATA");
5202				retval = 1;
5203				goto ratecontrol_bailout;
5204			}
5205			if (pata) {
5206				pata->mode = mode;
5207				pata->valid |= CTS_ATA_VALID_MODE;
5208			} else {
5209				sata->mode = mode;
5210				sata->valid |= CTS_SATA_VALID_MODE;
5211			}
5212			didsettings++;
5213		}
5214		/*
5215		 * The bus_width argument goes like this:
5216		 * 0 == 8 bit
5217		 * 1 == 16 bit
5218		 * 2 == 32 bit
5219		 * Therefore, if you shift the number of bits given on the
5220		 * command line right by 4, you should get the correct
5221		 * number.
5222		 */
5223		if (spi && bus_width != -1) {
5224			/*
5225			 * We might as well validate things here with a
5226			 * decipherable error message, rather than what
5227			 * will probably be an indecipherable error message
5228			 * by the time it gets back to us.
5229			 */
5230			if ((bus_width == 16)
5231			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5232				warnx("HBA does not support 16 bit bus width");
5233				retval = 1;
5234				goto ratecontrol_bailout;
5235			} else if ((bus_width == 32)
5236				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5237				warnx("HBA does not support 32 bit bus width");
5238				retval = 1;
5239				goto ratecontrol_bailout;
5240			} else if ((bus_width != 8)
5241				&& (bus_width != 16)
5242				&& (bus_width != 32)) {
5243				warnx("Invalid bus width %d", bus_width);
5244				retval = 1;
5245				goto ratecontrol_bailout;
5246			}
5247			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5248			spi->bus_width = bus_width >> 4;
5249			didsettings++;
5250		}
5251		if  (didsettings == 0) {
5252			goto ratecontrol_bailout;
5253		}
5254		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5255		if (cam_send_ccb(device, ccb) < 0) {
5256			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5257			if (arglist & CAM_ARG_VERBOSE) {
5258				cam_error_print(device, ccb, CAM_ESF_ALL,
5259						CAM_EPF_ALL, stderr);
5260			}
5261			retval = 1;
5262			goto ratecontrol_bailout;
5263		}
5264		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5265			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5266			if (arglist & CAM_ARG_VERBOSE) {
5267				cam_error_print(device, ccb, CAM_ESF_ALL,
5268						CAM_EPF_ALL, stderr);
5269			}
5270			retval = 1;
5271			goto ratecontrol_bailout;
5272		}
5273	}
5274	if (send_tur) {
5275		retval = testunitready(device, retry_count, timeout,
5276				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5277		/*
5278		 * If the TUR didn't succeed, just bail.
5279		 */
5280		if (retval != 0) {
5281			if (quiet == 0)
5282				fprintf(stderr, "Test Unit Ready failed\n");
5283			goto ratecontrol_bailout;
5284		}
5285	}
5286	if ((change_settings || send_tur) && !quiet &&
5287	    (ccb->cts.transport == XPORT_ATA ||
5288	     ccb->cts.transport == XPORT_SATA || send_tur)) {
5289		fprintf(stdout, "New parameters:\n");
5290		retval = get_print_cts(device, user_settings, 0, NULL);
5291	}
5292
5293ratecontrol_bailout:
5294	cam_freeccb(ccb);
5295	return(retval);
5296}
5297
5298static int
5299scsiformat(struct cam_device *device, int argc, char **argv,
5300	   char *combinedopt, int retry_count, int timeout)
5301{
5302	union ccb *ccb;
5303	int c;
5304	int ycount = 0, quiet = 0;
5305	int error = 0, retval = 0;
5306	int use_timeout = 10800 * 1000;
5307	int immediate = 1;
5308	struct format_defect_list_header fh;
5309	u_int8_t *data_ptr = NULL;
5310	u_int32_t dxfer_len = 0;
5311	u_int8_t byte2 = 0;
5312	int num_warnings = 0;
5313	int reportonly = 0;
5314
5315	ccb = cam_getccb(device);
5316
5317	if (ccb == NULL) {
5318		warnx("scsiformat: error allocating ccb");
5319		return(1);
5320	}
5321
5322	bzero(&(&ccb->ccb_h)[1],
5323	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5324
5325	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5326		switch(c) {
5327		case 'q':
5328			quiet++;
5329			break;
5330		case 'r':
5331			reportonly = 1;
5332			break;
5333		case 'w':
5334			immediate = 0;
5335			break;
5336		case 'y':
5337			ycount++;
5338			break;
5339		}
5340	}
5341
5342	if (reportonly)
5343		goto doreport;
5344
5345	if (quiet == 0) {
5346		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5347			"following device:\n");
5348
5349		error = scsidoinquiry(device, argc, argv, combinedopt,
5350				      retry_count, timeout);
5351
5352		if (error != 0) {
5353			warnx("scsiformat: error sending inquiry");
5354			goto scsiformat_bailout;
5355		}
5356	}
5357
5358	if (ycount == 0) {
5359		if (!get_confirmation()) {
5360			error = 1;
5361			goto scsiformat_bailout;
5362		}
5363	}
5364
5365	if (timeout != 0)
5366		use_timeout = timeout;
5367
5368	if (quiet == 0) {
5369		fprintf(stdout, "Current format timeout is %d seconds\n",
5370			use_timeout / 1000);
5371	}
5372
5373	/*
5374	 * If the user hasn't disabled questions and didn't specify a
5375	 * timeout on the command line, ask them if they want the current
5376	 * timeout.
5377	 */
5378	if ((ycount == 0)
5379	 && (timeout == 0)) {
5380		char str[1024];
5381		int new_timeout = 0;
5382
5383		fprintf(stdout, "Enter new timeout in seconds or press\n"
5384			"return to keep the current timeout [%d] ",
5385			use_timeout / 1000);
5386
5387		if (fgets(str, sizeof(str), stdin) != NULL) {
5388			if (str[0] != '\0')
5389				new_timeout = atoi(str);
5390		}
5391
5392		if (new_timeout != 0) {
5393			use_timeout = new_timeout * 1000;
5394			fprintf(stdout, "Using new timeout value %d\n",
5395				use_timeout / 1000);
5396		}
5397	}
5398
5399	/*
5400	 * Keep this outside the if block below to silence any unused
5401	 * variable warnings.
5402	 */
5403	bzero(&fh, sizeof(fh));
5404
5405	/*
5406	 * If we're in immediate mode, we've got to include the format
5407	 * header
5408	 */
5409	if (immediate != 0) {
5410		fh.byte2 = FU_DLH_IMMED;
5411		data_ptr = (u_int8_t *)&fh;
5412		dxfer_len = sizeof(fh);
5413		byte2 = FU_FMT_DATA;
5414	} else if (quiet == 0) {
5415		fprintf(stdout, "Formatting...");
5416		fflush(stdout);
5417	}
5418
5419	scsi_format_unit(&ccb->csio,
5420			 /* retries */ retry_count,
5421			 /* cbfcnp */ NULL,
5422			 /* tag_action */ MSG_SIMPLE_Q_TAG,
5423			 /* byte2 */ byte2,
5424			 /* ileave */ 0,
5425			 /* data_ptr */ data_ptr,
5426			 /* dxfer_len */ dxfer_len,
5427			 /* sense_len */ SSD_FULL_SIZE,
5428			 /* timeout */ use_timeout);
5429
5430	/* Disable freezing the device queue */
5431	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5432
5433	if (arglist & CAM_ARG_ERR_RECOVER)
5434		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5435
5436	if (((retval = cam_send_ccb(device, ccb)) < 0)
5437	 || ((immediate == 0)
5438	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5439		const char errstr[] = "error sending format command";
5440
5441		if (retval < 0)
5442			warn(errstr);
5443		else
5444			warnx(errstr);
5445
5446		if (arglist & CAM_ARG_VERBOSE) {
5447			cam_error_print(device, ccb, CAM_ESF_ALL,
5448					CAM_EPF_ALL, stderr);
5449		}
5450		error = 1;
5451		goto scsiformat_bailout;
5452	}
5453
5454	/*
5455	 * If we ran in non-immediate mode, we already checked for errors
5456	 * above and printed out any necessary information.  If we're in
5457	 * immediate mode, we need to loop through and get status
5458	 * information periodically.
5459	 */
5460	if (immediate == 0) {
5461		if (quiet == 0) {
5462			fprintf(stdout, "Format Complete\n");
5463		}
5464		goto scsiformat_bailout;
5465	}
5466
5467doreport:
5468	do {
5469		cam_status status;
5470
5471		bzero(&(&ccb->ccb_h)[1],
5472		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5473
5474		/*
5475		 * There's really no need to do error recovery or
5476		 * retries here, since we're just going to sit in a
5477		 * loop and wait for the device to finish formatting.
5478		 */
5479		scsi_test_unit_ready(&ccb->csio,
5480				     /* retries */ 0,
5481				     /* cbfcnp */ NULL,
5482				     /* tag_action */ MSG_SIMPLE_Q_TAG,
5483				     /* sense_len */ SSD_FULL_SIZE,
5484				     /* timeout */ 5000);
5485
5486		/* Disable freezing the device queue */
5487		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5488
5489		retval = cam_send_ccb(device, ccb);
5490
5491		/*
5492		 * If we get an error from the ioctl, bail out.  SCSI
5493		 * errors are expected.
5494		 */
5495		if (retval < 0) {
5496			warn("error sending CAMIOCOMMAND ioctl");
5497			if (arglist & CAM_ARG_VERBOSE) {
5498				cam_error_print(device, ccb, CAM_ESF_ALL,
5499						CAM_EPF_ALL, stderr);
5500			}
5501			error = 1;
5502			goto scsiformat_bailout;
5503		}
5504
5505		status = ccb->ccb_h.status & CAM_STATUS_MASK;
5506
5507		if ((status != CAM_REQ_CMP)
5508		 && (status == CAM_SCSI_STATUS_ERROR)
5509		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5510			struct scsi_sense_data *sense;
5511			int error_code, sense_key, asc, ascq;
5512
5513			sense = &ccb->csio.sense_data;
5514			scsi_extract_sense_len(sense, ccb->csio.sense_len -
5515			    ccb->csio.sense_resid, &error_code, &sense_key,
5516			    &asc, &ascq, /*show_errors*/ 1);
5517
5518			/*
5519			 * According to the SCSI-2 and SCSI-3 specs, a
5520			 * drive that is in the middle of a format should
5521			 * return NOT READY with an ASC of "logical unit
5522			 * not ready, format in progress".  The sense key
5523			 * specific bytes will then be a progress indicator.
5524			 */
5525			if ((sense_key == SSD_KEY_NOT_READY)
5526			 && (asc == 0x04) && (ascq == 0x04)) {
5527				uint8_t sks[3];
5528
5529				if ((scsi_get_sks(sense, ccb->csio.sense_len -
5530				     ccb->csio.sense_resid, sks) == 0)
5531				 && (quiet == 0)) {
5532					int val;
5533					u_int64_t percentage;
5534
5535					val = scsi_2btoul(&sks[1]);
5536					percentage = 10000 * val;
5537
5538					fprintf(stdout,
5539						"\rFormatting:  %ju.%02u %% "
5540						"(%d/%d) done",
5541						(uintmax_t)(percentage /
5542						(0x10000 * 100)),
5543						(unsigned)((percentage /
5544						0x10000) % 100),
5545						val, 0x10000);
5546					fflush(stdout);
5547				} else if ((quiet == 0)
5548					&& (++num_warnings <= 1)) {
5549					warnx("Unexpected SCSI Sense Key "
5550					      "Specific value returned "
5551					      "during format:");
5552					scsi_sense_print(device, &ccb->csio,
5553							 stderr);
5554					warnx("Unable to print status "
5555					      "information, but format will "
5556					      "proceed.");
5557					warnx("will exit when format is "
5558					      "complete");
5559				}
5560				sleep(1);
5561			} else {
5562				warnx("Unexpected SCSI error during format");
5563				cam_error_print(device, ccb, CAM_ESF_ALL,
5564						CAM_EPF_ALL, stderr);
5565				error = 1;
5566				goto scsiformat_bailout;
5567			}
5568
5569		} else if (status != CAM_REQ_CMP) {
5570			warnx("Unexpected CAM status %#x", status);
5571			if (arglist & CAM_ARG_VERBOSE)
5572				cam_error_print(device, ccb, CAM_ESF_ALL,
5573						CAM_EPF_ALL, stderr);
5574			error = 1;
5575			goto scsiformat_bailout;
5576		}
5577
5578	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5579
5580	if (quiet == 0)
5581		fprintf(stdout, "\nFormat Complete\n");
5582
5583scsiformat_bailout:
5584
5585	cam_freeccb(ccb);
5586
5587	return(error);
5588}
5589
5590static int
5591scsisanitize(struct cam_device *device, int argc, char **argv,
5592	     char *combinedopt, int retry_count, int timeout)
5593{
5594	union ccb *ccb;
5595	u_int8_t action = 0;
5596	int c;
5597	int ycount = 0, quiet = 0;
5598	int error = 0, retval = 0;
5599	int use_timeout = 10800 * 1000;
5600	int immediate = 1;
5601	int invert = 0;
5602	int passes = 0;
5603	int ause = 0;
5604	int fd = -1;
5605	const char *pattern = NULL;
5606	u_int8_t *data_ptr = NULL;
5607	u_int32_t dxfer_len = 0;
5608	u_int8_t byte2 = 0;
5609	int num_warnings = 0;
5610	int reportonly = 0;
5611
5612	ccb = cam_getccb(device);
5613
5614	if (ccb == NULL) {
5615		warnx("scsisanitize: error allocating ccb");
5616		return(1);
5617	}
5618
5619	bzero(&(&ccb->ccb_h)[1],
5620	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5621
5622	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5623		switch(c) {
5624		case 'a':
5625			if (strcasecmp(optarg, "overwrite") == 0)
5626				action = SSZ_SERVICE_ACTION_OVERWRITE;
5627			else if (strcasecmp(optarg, "block") == 0)
5628				action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
5629			else if (strcasecmp(optarg, "crypto") == 0)
5630				action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
5631			else if (strcasecmp(optarg, "exitfailure") == 0)
5632				action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
5633			else {
5634				warnx("invalid service operation \"%s\"",
5635				      optarg);
5636				error = 1;
5637				goto scsisanitize_bailout;
5638			}
5639			break;
5640		case 'c':
5641			passes = strtol(optarg, NULL, 0);
5642			if (passes < 1 || passes > 31) {
5643				warnx("invalid passes value %d", passes);
5644				error = 1;
5645				goto scsisanitize_bailout;
5646			}
5647			break;
5648		case 'I':
5649			invert = 1;
5650			break;
5651		case 'P':
5652			pattern = optarg;
5653			break;
5654		case 'q':
5655			quiet++;
5656			break;
5657		case 'U':
5658			ause = 1;
5659			break;
5660		case 'r':
5661			reportonly = 1;
5662			break;
5663		case 'w':
5664			immediate = 0;
5665			break;
5666		case 'y':
5667			ycount++;
5668			break;
5669		}
5670	}
5671
5672	if (reportonly)
5673		goto doreport;
5674
5675	if (action == 0) {
5676		warnx("an action is required");
5677		error = 1;
5678		goto scsisanitize_bailout;
5679	} else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
5680		struct scsi_sanitize_parameter_list *pl;
5681		struct stat sb;
5682		ssize_t sz, amt;
5683
5684		if (pattern == NULL) {
5685			warnx("overwrite action requires -P argument");
5686			error = 1;
5687			goto scsisanitize_bailout;
5688		}
5689		fd = open(pattern, O_RDONLY);
5690		if (fd < 0) {
5691			warn("cannot open pattern file %s", pattern);
5692			error = 1;
5693			goto scsisanitize_bailout;
5694		}
5695		if (fstat(fd, &sb) < 0) {
5696			warn("cannot stat pattern file %s", pattern);
5697			error = 1;
5698			goto scsisanitize_bailout;
5699		}
5700		sz = sb.st_size;
5701		if (sz > SSZPL_MAX_PATTERN_LENGTH) {
5702			warnx("pattern file size exceeds maximum value %d",
5703			      SSZPL_MAX_PATTERN_LENGTH);
5704			error = 1;
5705			goto scsisanitize_bailout;
5706		}
5707		dxfer_len = sizeof(*pl) + sz;
5708		data_ptr = calloc(1, dxfer_len);
5709		if (data_ptr == NULL) {
5710			warnx("cannot allocate parameter list buffer");
5711			error = 1;
5712			goto scsisanitize_bailout;
5713		}
5714
5715		amt = read(fd, data_ptr + sizeof(*pl), sz);
5716		if (amt < 0) {
5717			warn("cannot read pattern file");
5718			error = 1;
5719			goto scsisanitize_bailout;
5720		} else if (amt != sz) {
5721			warnx("short pattern file read");
5722			error = 1;
5723			goto scsisanitize_bailout;
5724		}
5725
5726		pl = (struct scsi_sanitize_parameter_list *)data_ptr;
5727		if (passes == 0)
5728			pl->byte1 = 1;
5729		else
5730			pl->byte1 = passes;
5731		if (invert != 0)
5732			pl->byte1 |= SSZPL_INVERT;
5733		scsi_ulto2b(sz, pl->length);
5734	} else {
5735		const char *arg;
5736
5737		if (passes != 0)
5738			arg = "-c";
5739		else if (invert != 0)
5740			arg = "-I";
5741		else if (pattern != NULL)
5742			arg = "-P";
5743		else
5744			arg = NULL;
5745		if (arg != NULL) {
5746			warnx("%s argument only valid with overwrite "
5747			      "operation", arg);
5748			error = 1;
5749			goto scsisanitize_bailout;
5750		}
5751	}
5752
5753	if (quiet == 0) {
5754		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5755			"following device:\n");
5756
5757		error = scsidoinquiry(device, argc, argv, combinedopt,
5758				      retry_count, timeout);
5759
5760		if (error != 0) {
5761			warnx("scsisanitize: error sending inquiry");
5762			goto scsisanitize_bailout;
5763		}
5764	}
5765
5766	if (ycount == 0) {
5767		if (!get_confirmation()) {
5768			error = 1;
5769			goto scsisanitize_bailout;
5770		}
5771	}
5772
5773	if (timeout != 0)
5774		use_timeout = timeout;
5775
5776	if (quiet == 0) {
5777		fprintf(stdout, "Current sanitize timeout is %d seconds\n",
5778			use_timeout / 1000);
5779	}
5780
5781	/*
5782	 * If the user hasn't disabled questions and didn't specify a
5783	 * timeout on the command line, ask them if they want the current
5784	 * timeout.
5785	 */
5786	if ((ycount == 0)
5787	 && (timeout == 0)) {
5788		char str[1024];
5789		int new_timeout = 0;
5790
5791		fprintf(stdout, "Enter new timeout in seconds or press\n"
5792			"return to keep the current timeout [%d] ",
5793			use_timeout / 1000);
5794
5795		if (fgets(str, sizeof(str), stdin) != NULL) {
5796			if (str[0] != '\0')
5797				new_timeout = atoi(str);
5798		}
5799
5800		if (new_timeout != 0) {
5801			use_timeout = new_timeout * 1000;
5802			fprintf(stdout, "Using new timeout value %d\n",
5803				use_timeout / 1000);
5804		}
5805	}
5806
5807	byte2 = action;
5808	if (ause != 0)
5809		byte2 |= SSZ_UNRESTRICTED_EXIT;
5810	if (immediate != 0)
5811		byte2 |= SSZ_IMMED;
5812
5813	scsi_sanitize(&ccb->csio,
5814		      /* retries */ retry_count,
5815		      /* cbfcnp */ NULL,
5816		      /* tag_action */ MSG_SIMPLE_Q_TAG,
5817		      /* byte2 */ byte2,
5818		      /* control */ 0,
5819		      /* data_ptr */ data_ptr,
5820		      /* dxfer_len */ dxfer_len,
5821		      /* sense_len */ SSD_FULL_SIZE,
5822		      /* timeout */ use_timeout);
5823
5824	/* Disable freezing the device queue */
5825	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5826
5827	if (arglist & CAM_ARG_ERR_RECOVER)
5828		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5829
5830	if (cam_send_ccb(device, ccb) < 0) {
5831		warn("error sending sanitize command");
5832		error = 1;
5833		goto scsisanitize_bailout;
5834	}
5835
5836	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5837		struct scsi_sense_data *sense;
5838		int error_code, sense_key, asc, ascq;
5839
5840		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
5841		    CAM_SCSI_STATUS_ERROR) {
5842			sense = &ccb->csio.sense_data;
5843			scsi_extract_sense_len(sense, ccb->csio.sense_len -
5844			    ccb->csio.sense_resid, &error_code, &sense_key,
5845			    &asc, &ascq, /*show_errors*/ 1);
5846
5847			if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
5848			    asc == 0x20 && ascq == 0x00)
5849				warnx("sanitize is not supported by "
5850				      "this device");
5851			else
5852				warnx("error sanitizing this device");
5853		} else
5854			warnx("error sanitizing this device");
5855
5856		if (arglist & CAM_ARG_VERBOSE) {
5857			cam_error_print(device, ccb, CAM_ESF_ALL,
5858					CAM_EPF_ALL, stderr);
5859		}
5860		error = 1;
5861		goto scsisanitize_bailout;
5862	}
5863
5864	/*
5865	 * If we ran in non-immediate mode, we already checked for errors
5866	 * above and printed out any necessary information.  If we're in
5867	 * immediate mode, we need to loop through and get status
5868	 * information periodically.
5869	 */
5870	if (immediate == 0) {
5871		if (quiet == 0) {
5872			fprintf(stdout, "Sanitize Complete\n");
5873		}
5874		goto scsisanitize_bailout;
5875	}
5876
5877doreport:
5878	do {
5879		cam_status status;
5880
5881		bzero(&(&ccb->ccb_h)[1],
5882		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5883
5884		/*
5885		 * There's really no need to do error recovery or
5886		 * retries here, since we're just going to sit in a
5887		 * loop and wait for the device to finish sanitizing.
5888		 */
5889		scsi_test_unit_ready(&ccb->csio,
5890				     /* retries */ 0,
5891				     /* cbfcnp */ NULL,
5892				     /* tag_action */ MSG_SIMPLE_Q_TAG,
5893				     /* sense_len */ SSD_FULL_SIZE,
5894				     /* timeout */ 5000);
5895
5896		/* Disable freezing the device queue */
5897		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5898
5899		retval = cam_send_ccb(device, ccb);
5900
5901		/*
5902		 * If we get an error from the ioctl, bail out.  SCSI
5903		 * errors are expected.
5904		 */
5905		if (retval < 0) {
5906			warn("error sending CAMIOCOMMAND ioctl");
5907			if (arglist & CAM_ARG_VERBOSE) {
5908				cam_error_print(device, ccb, CAM_ESF_ALL,
5909						CAM_EPF_ALL, stderr);
5910			}
5911			error = 1;
5912			goto scsisanitize_bailout;
5913		}
5914
5915		status = ccb->ccb_h.status & CAM_STATUS_MASK;
5916
5917		if ((status != CAM_REQ_CMP)
5918		 && (status == CAM_SCSI_STATUS_ERROR)
5919		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5920			struct scsi_sense_data *sense;
5921			int error_code, sense_key, asc, ascq;
5922
5923			sense = &ccb->csio.sense_data;
5924			scsi_extract_sense_len(sense, ccb->csio.sense_len -
5925			    ccb->csio.sense_resid, &error_code, &sense_key,
5926			    &asc, &ascq, /*show_errors*/ 1);
5927
5928			/*
5929			 * According to the SCSI-3 spec, a drive that is in the
5930			 * middle of a sanitize should return NOT READY with an
5931			 * ASC of "logical unit not ready, sanitize in
5932			 * progress". The sense key specific bytes will then
5933			 * be a progress indicator.
5934			 */
5935			if ((sense_key == SSD_KEY_NOT_READY)
5936			 && (asc == 0x04) && (ascq == 0x1b)) {
5937				uint8_t sks[3];
5938
5939				if ((scsi_get_sks(sense, ccb->csio.sense_len -
5940				     ccb->csio.sense_resid, sks) == 0)
5941				 && (quiet == 0)) {
5942					int val;
5943					u_int64_t percentage;
5944
5945					val = scsi_2btoul(&sks[1]);
5946					percentage = 10000 * val;
5947
5948					fprintf(stdout,
5949						"\rSanitizing:  %ju.%02u %% "
5950						"(%d/%d) done",
5951						(uintmax_t)(percentage /
5952						(0x10000 * 100)),
5953						(unsigned)((percentage /
5954						0x10000) % 100),
5955						val, 0x10000);
5956					fflush(stdout);
5957				} else if ((quiet == 0)
5958					&& (++num_warnings <= 1)) {
5959					warnx("Unexpected SCSI Sense Key "
5960					      "Specific value returned "
5961					      "during sanitize:");
5962					scsi_sense_print(device, &ccb->csio,
5963							 stderr);
5964					warnx("Unable to print status "
5965					      "information, but sanitze will "
5966					      "proceed.");
5967					warnx("will exit when sanitize is "
5968					      "complete");
5969				}
5970				sleep(1);
5971			} else {
5972				warnx("Unexpected SCSI error during sanitize");
5973				cam_error_print(device, ccb, CAM_ESF_ALL,
5974						CAM_EPF_ALL, stderr);
5975				error = 1;
5976				goto scsisanitize_bailout;
5977			}
5978
5979		} else if (status != CAM_REQ_CMP) {
5980			warnx("Unexpected CAM status %#x", status);
5981			if (arglist & CAM_ARG_VERBOSE)
5982				cam_error_print(device, ccb, CAM_ESF_ALL,
5983						CAM_EPF_ALL, stderr);
5984			error = 1;
5985			goto scsisanitize_bailout;
5986		}
5987	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5988
5989	if (quiet == 0)
5990		fprintf(stdout, "\nSanitize Complete\n");
5991
5992scsisanitize_bailout:
5993	if (fd >= 0)
5994		close(fd);
5995	if (data_ptr != NULL)
5996		free(data_ptr);
5997	cam_freeccb(ccb);
5998
5999	return(error);
6000}
6001
6002static int
6003scsireportluns(struct cam_device *device, int argc, char **argv,
6004	       char *combinedopt, int retry_count, int timeout)
6005{
6006	union ccb *ccb;
6007	int c, countonly, lunsonly;
6008	struct scsi_report_luns_data *lundata;
6009	int alloc_len;
6010	uint8_t report_type;
6011	uint32_t list_len, i, j;
6012	int retval;
6013
6014	retval = 0;
6015	lundata = NULL;
6016	report_type = RPL_REPORT_DEFAULT;
6017	ccb = cam_getccb(device);
6018
6019	if (ccb == NULL) {
6020		warnx("%s: error allocating ccb", __func__);
6021		return (1);
6022	}
6023
6024	bzero(&(&ccb->ccb_h)[1],
6025	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6026
6027	countonly = 0;
6028	lunsonly = 0;
6029
6030	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6031		switch (c) {
6032		case 'c':
6033			countonly++;
6034			break;
6035		case 'l':
6036			lunsonly++;
6037			break;
6038		case 'r':
6039			if (strcasecmp(optarg, "default") == 0)
6040				report_type = RPL_REPORT_DEFAULT;
6041			else if (strcasecmp(optarg, "wellknown") == 0)
6042				report_type = RPL_REPORT_WELLKNOWN;
6043			else if (strcasecmp(optarg, "all") == 0)
6044				report_type = RPL_REPORT_ALL;
6045			else {
6046				warnx("%s: invalid report type \"%s\"",
6047				      __func__, optarg);
6048				retval = 1;
6049				goto bailout;
6050			}
6051			break;
6052		default:
6053			break;
6054		}
6055	}
6056
6057	if ((countonly != 0)
6058	 && (lunsonly != 0)) {
6059		warnx("%s: you can only specify one of -c or -l", __func__);
6060		retval = 1;
6061		goto bailout;
6062	}
6063	/*
6064	 * According to SPC-4, the allocation length must be at least 16
6065	 * bytes -- enough for the header and one LUN.
6066	 */
6067	alloc_len = sizeof(*lundata) + 8;
6068
6069retry:
6070
6071	lundata = malloc(alloc_len);
6072
6073	if (lundata == NULL) {
6074		warn("%s: error mallocing %d bytes", __func__, alloc_len);
6075		retval = 1;
6076		goto bailout;
6077	}
6078
6079	scsi_report_luns(&ccb->csio,
6080			 /*retries*/ retry_count,
6081			 /*cbfcnp*/ NULL,
6082			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6083			 /*select_report*/ report_type,
6084			 /*rpl_buf*/ lundata,
6085			 /*alloc_len*/ alloc_len,
6086			 /*sense_len*/ SSD_FULL_SIZE,
6087			 /*timeout*/ timeout ? timeout : 5000);
6088
6089	/* Disable freezing the device queue */
6090	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6091
6092	if (arglist & CAM_ARG_ERR_RECOVER)
6093		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6094
6095	if (cam_send_ccb(device, ccb) < 0) {
6096		warn("error sending REPORT LUNS command");
6097
6098		if (arglist & CAM_ARG_VERBOSE)
6099			cam_error_print(device, ccb, CAM_ESF_ALL,
6100					CAM_EPF_ALL, stderr);
6101
6102		retval = 1;
6103		goto bailout;
6104	}
6105
6106	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6107		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6108		retval = 1;
6109		goto bailout;
6110	}
6111
6112
6113	list_len = scsi_4btoul(lundata->length);
6114
6115	/*
6116	 * If we need to list the LUNs, and our allocation
6117	 * length was too short, reallocate and retry.
6118	 */
6119	if ((countonly == 0)
6120	 && (list_len > (alloc_len - sizeof(*lundata)))) {
6121		alloc_len = list_len + sizeof(*lundata);
6122		free(lundata);
6123		goto retry;
6124	}
6125
6126	if (lunsonly == 0)
6127		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6128			((list_len / 8) > 1) ? "s" : "");
6129
6130	if (countonly != 0)
6131		goto bailout;
6132
6133	for (i = 0; i < (list_len / 8); i++) {
6134		int no_more;
6135
6136		no_more = 0;
6137		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6138			if (j != 0)
6139				fprintf(stdout, ",");
6140			switch (lundata->luns[i].lundata[j] &
6141				RPL_LUNDATA_ATYP_MASK) {
6142			case RPL_LUNDATA_ATYP_PERIPH:
6143				if ((lundata->luns[i].lundata[j] &
6144				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6145					fprintf(stdout, "%d:",
6146						lundata->luns[i].lundata[j] &
6147						RPL_LUNDATA_PERIPH_BUS_MASK);
6148				else if ((j == 0)
6149				      && ((lundata->luns[i].lundata[j+2] &
6150					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6151					no_more = 1;
6152
6153				fprintf(stdout, "%d",
6154					lundata->luns[i].lundata[j+1]);
6155				break;
6156			case RPL_LUNDATA_ATYP_FLAT: {
6157				uint8_t tmplun[2];
6158				tmplun[0] = lundata->luns[i].lundata[j] &
6159					RPL_LUNDATA_FLAT_LUN_MASK;
6160				tmplun[1] = lundata->luns[i].lundata[j+1];
6161
6162				fprintf(stdout, "%d", scsi_2btoul(tmplun));
6163				no_more = 1;
6164				break;
6165			}
6166			case RPL_LUNDATA_ATYP_LUN:
6167				fprintf(stdout, "%d:%d:%d",
6168					(lundata->luns[i].lundata[j+1] &
6169					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6170					lundata->luns[i].lundata[j] &
6171					RPL_LUNDATA_LUN_TARG_MASK,
6172					lundata->luns[i].lundata[j+1] &
6173					RPL_LUNDATA_LUN_LUN_MASK);
6174				break;
6175			case RPL_LUNDATA_ATYP_EXTLUN: {
6176				int field_len_code, eam_code;
6177
6178				eam_code = lundata->luns[i].lundata[j] &
6179					RPL_LUNDATA_EXT_EAM_MASK;
6180				field_len_code = (lundata->luns[i].lundata[j] &
6181					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6182
6183				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6184				 && (field_len_code == 0x00)) {
6185					fprintf(stdout, "%d",
6186						lundata->luns[i].lundata[j+1]);
6187				} else if ((eam_code ==
6188					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6189					&& (field_len_code == 0x03)) {
6190					uint8_t tmp_lun[8];
6191
6192					/*
6193					 * This format takes up all 8 bytes.
6194					 * If we aren't starting at offset 0,
6195					 * that's a bug.
6196					 */
6197					if (j != 0) {
6198						fprintf(stdout, "Invalid "
6199							"offset %d for "
6200							"Extended LUN not "
6201							"specified format", j);
6202						no_more = 1;
6203						break;
6204					}
6205					bzero(tmp_lun, sizeof(tmp_lun));
6206					bcopy(&lundata->luns[i].lundata[j+1],
6207					      &tmp_lun[1], sizeof(tmp_lun) - 1);
6208					fprintf(stdout, "%#jx",
6209					       (intmax_t)scsi_8btou64(tmp_lun));
6210					no_more = 1;
6211				} else {
6212					fprintf(stderr, "Unknown Extended LUN"
6213						"Address method %#x, length "
6214						"code %#x", eam_code,
6215						field_len_code);
6216					no_more = 1;
6217				}
6218				break;
6219			}
6220			default:
6221				fprintf(stderr, "Unknown LUN address method "
6222					"%#x\n", lundata->luns[i].lundata[0] &
6223					RPL_LUNDATA_ATYP_MASK);
6224				break;
6225			}
6226			/*
6227			 * For the flat addressing method, there are no
6228			 * other levels after it.
6229			 */
6230			if (no_more != 0)
6231				break;
6232		}
6233		fprintf(stdout, "\n");
6234	}
6235
6236bailout:
6237
6238	cam_freeccb(ccb);
6239
6240	free(lundata);
6241
6242	return (retval);
6243}
6244
6245static int
6246scsireadcapacity(struct cam_device *device, int argc, char **argv,
6247		 char *combinedopt, int retry_count, int timeout)
6248{
6249	union ccb *ccb;
6250	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6251	struct scsi_read_capacity_data rcap;
6252	struct scsi_read_capacity_data_long rcaplong;
6253	uint64_t maxsector;
6254	uint32_t block_len;
6255	int retval;
6256	int c;
6257
6258	blocksizeonly = 0;
6259	humanize = 0;
6260	numblocks = 0;
6261	quiet = 0;
6262	sizeonly = 0;
6263	baseten = 0;
6264	retval = 0;
6265
6266	ccb = cam_getccb(device);
6267
6268	if (ccb == NULL) {
6269		warnx("%s: error allocating ccb", __func__);
6270		return (1);
6271	}
6272
6273	bzero(&(&ccb->ccb_h)[1],
6274	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6275
6276	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6277		switch (c) {
6278		case 'b':
6279			blocksizeonly++;
6280			break;
6281		case 'h':
6282			humanize++;
6283			baseten = 0;
6284			break;
6285		case 'H':
6286			humanize++;
6287			baseten++;
6288			break;
6289		case 'N':
6290			numblocks++;
6291			break;
6292		case 'q':
6293			quiet++;
6294			break;
6295		case 's':
6296			sizeonly++;
6297			break;
6298		default:
6299			break;
6300		}
6301	}
6302
6303	if ((blocksizeonly != 0)
6304	 && (numblocks != 0)) {
6305		warnx("%s: you can only specify one of -b or -N", __func__);
6306		retval = 1;
6307		goto bailout;
6308	}
6309
6310	if ((blocksizeonly != 0)
6311	 && (sizeonly != 0)) {
6312		warnx("%s: you can only specify one of -b or -s", __func__);
6313		retval = 1;
6314		goto bailout;
6315	}
6316
6317	if ((humanize != 0)
6318	 && (quiet != 0)) {
6319		warnx("%s: you can only specify one of -h/-H or -q", __func__);
6320		retval = 1;
6321		goto bailout;
6322	}
6323
6324	if ((humanize != 0)
6325	 && (blocksizeonly != 0)) {
6326		warnx("%s: you can only specify one of -h/-H or -b", __func__);
6327		retval = 1;
6328		goto bailout;
6329	}
6330
6331	scsi_read_capacity(&ccb->csio,
6332			   /*retries*/ retry_count,
6333			   /*cbfcnp*/ NULL,
6334			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
6335			   &rcap,
6336			   SSD_FULL_SIZE,
6337			   /*timeout*/ timeout ? timeout : 5000);
6338
6339	/* Disable freezing the device queue */
6340	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6341
6342	if (arglist & CAM_ARG_ERR_RECOVER)
6343		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6344
6345	if (cam_send_ccb(device, ccb) < 0) {
6346		warn("error sending READ CAPACITY command");
6347
6348		if (arglist & CAM_ARG_VERBOSE)
6349			cam_error_print(device, ccb, CAM_ESF_ALL,
6350					CAM_EPF_ALL, stderr);
6351
6352		retval = 1;
6353		goto bailout;
6354	}
6355
6356	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6357		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6358		retval = 1;
6359		goto bailout;
6360	}
6361
6362	maxsector = scsi_4btoul(rcap.addr);
6363	block_len = scsi_4btoul(rcap.length);
6364
6365	/*
6366	 * A last block of 2^32-1 means that the true capacity is over 2TB,
6367	 * and we need to issue the long READ CAPACITY to get the real
6368	 * capacity.  Otherwise, we're all set.
6369	 */
6370	if (maxsector != 0xffffffff)
6371		goto do_print;
6372
6373	scsi_read_capacity_16(&ccb->csio,
6374			      /*retries*/ retry_count,
6375			      /*cbfcnp*/ NULL,
6376			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
6377			      /*lba*/ 0,
6378			      /*reladdr*/ 0,
6379			      /*pmi*/ 0,
6380			      /*rcap_buf*/ (uint8_t *)&rcaplong,
6381			      /*rcap_buf_len*/ sizeof(rcaplong),
6382			      /*sense_len*/ SSD_FULL_SIZE,
6383			      /*timeout*/ timeout ? timeout : 5000);
6384
6385	/* Disable freezing the device queue */
6386	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6387
6388	if (arglist & CAM_ARG_ERR_RECOVER)
6389		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6390
6391	if (cam_send_ccb(device, ccb) < 0) {
6392		warn("error sending READ CAPACITY (16) command");
6393
6394		if (arglist & CAM_ARG_VERBOSE)
6395			cam_error_print(device, ccb, CAM_ESF_ALL,
6396					CAM_EPF_ALL, stderr);
6397
6398		retval = 1;
6399		goto bailout;
6400	}
6401
6402	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6403		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6404		retval = 1;
6405		goto bailout;
6406	}
6407
6408	maxsector = scsi_8btou64(rcaplong.addr);
6409	block_len = scsi_4btoul(rcaplong.length);
6410
6411do_print:
6412	if (blocksizeonly == 0) {
6413		/*
6414		 * Humanize implies !quiet, and also implies numblocks.
6415		 */
6416		if (humanize != 0) {
6417			char tmpstr[6];
6418			int64_t tmpbytes;
6419			int ret;
6420
6421			tmpbytes = (maxsector + 1) * block_len;
6422			ret = humanize_number(tmpstr, sizeof(tmpstr),
6423					      tmpbytes, "", HN_AUTOSCALE,
6424					      HN_B | HN_DECIMAL |
6425					      ((baseten != 0) ?
6426					      HN_DIVISOR_1000 : 0));
6427			if (ret == -1) {
6428				warnx("%s: humanize_number failed!", __func__);
6429				retval = 1;
6430				goto bailout;
6431			}
6432			fprintf(stdout, "Device Size: %s%s", tmpstr,
6433				(sizeonly == 0) ?  ", " : "\n");
6434		} else if (numblocks != 0) {
6435			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6436				"Blocks: " : "", (uintmax_t)maxsector + 1,
6437				(sizeonly == 0) ? ", " : "\n");
6438		} else {
6439			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6440				"Last Block: " : "", (uintmax_t)maxsector,
6441				(sizeonly == 0) ? ", " : "\n");
6442		}
6443	}
6444	if (sizeonly == 0)
6445		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6446			"Block Length: " : "", block_len, (quiet == 0) ?
6447			" bytes" : "");
6448bailout:
6449	cam_freeccb(ccb);
6450
6451	return (retval);
6452}
6453
6454static int
6455smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6456       int retry_count, int timeout)
6457{
6458	int c, error = 0;
6459	union ccb *ccb;
6460	uint8_t *smp_request = NULL, *smp_response = NULL;
6461	int request_size = 0, response_size = 0;
6462	int fd_request = 0, fd_response = 0;
6463	char *datastr = NULL;
6464	struct get_hook hook;
6465	int retval;
6466	int flags = 0;
6467
6468	/*
6469	 * Note that at the moment we don't support sending SMP CCBs to
6470	 * devices that aren't probed by CAM.
6471	 */
6472	ccb = cam_getccb(device);
6473	if (ccb == NULL) {
6474		warnx("%s: error allocating CCB", __func__);
6475		return (1);
6476	}
6477
6478	bzero(&(&ccb->ccb_h)[1],
6479	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6480
6481	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6482		switch (c) {
6483		case 'R':
6484			arglist |= CAM_ARG_CMD_IN;
6485			response_size = strtol(optarg, NULL, 0);
6486			if (response_size <= 0) {
6487				warnx("invalid number of response bytes %d",
6488				      response_size);
6489				error = 1;
6490				goto smpcmd_bailout;
6491			}
6492			hook.argc = argc - optind;
6493			hook.argv = argv + optind;
6494			hook.got = 0;
6495			optind++;
6496			datastr = cget(&hook, NULL);
6497			/*
6498			 * If the user supplied "-" instead of a format, he
6499			 * wants the data to be written to stdout.
6500			 */
6501			if ((datastr != NULL)
6502			 && (datastr[0] == '-'))
6503				fd_response = 1;
6504
6505			smp_response = (u_int8_t *)malloc(response_size);
6506			if (smp_response == NULL) {
6507				warn("can't malloc memory for SMP response");
6508				error = 1;
6509				goto smpcmd_bailout;
6510			}
6511			break;
6512		case 'r':
6513			arglist |= CAM_ARG_CMD_OUT;
6514			request_size = strtol(optarg, NULL, 0);
6515			if (request_size <= 0) {
6516				warnx("invalid number of request bytes %d",
6517				      request_size);
6518				error = 1;
6519				goto smpcmd_bailout;
6520			}
6521			hook.argc = argc - optind;
6522			hook.argv = argv + optind;
6523			hook.got = 0;
6524			datastr = cget(&hook, NULL);
6525			smp_request = (u_int8_t *)malloc(request_size);
6526			if (smp_request == NULL) {
6527				warn("can't malloc memory for SMP request");
6528				error = 1;
6529				goto smpcmd_bailout;
6530			}
6531			bzero(smp_request, request_size);
6532			/*
6533			 * If the user supplied "-" instead of a format, he
6534			 * wants the data to be read from stdin.
6535			 */
6536			if ((datastr != NULL)
6537			 && (datastr[0] == '-'))
6538				fd_request = 1;
6539			else
6540				buff_encode_visit(smp_request, request_size,
6541						  datastr,
6542						  iget, &hook);
6543			optind += hook.got;
6544			break;
6545		default:
6546			break;
6547		}
6548	}
6549
6550	/*
6551	 * If fd_data is set, and we're writing to the device, we need to
6552	 * read the data the user wants written from stdin.
6553	 */
6554	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6555		ssize_t amt_read;
6556		int amt_to_read = request_size;
6557		u_int8_t *buf_ptr = smp_request;
6558
6559		for (amt_read = 0; amt_to_read > 0;
6560		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6561			if (amt_read == -1) {
6562				warn("error reading data from stdin");
6563				error = 1;
6564				goto smpcmd_bailout;
6565			}
6566			amt_to_read -= amt_read;
6567			buf_ptr += amt_read;
6568		}
6569	}
6570
6571	if (((arglist & CAM_ARG_CMD_IN) == 0)
6572	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6573		warnx("%s: need both the request (-r) and response (-R) "
6574		      "arguments", __func__);
6575		error = 1;
6576		goto smpcmd_bailout;
6577	}
6578
6579	flags |= CAM_DEV_QFRZDIS;
6580
6581	cam_fill_smpio(&ccb->smpio,
6582		       /*retries*/ retry_count,
6583		       /*cbfcnp*/ NULL,
6584		       /*flags*/ flags,
6585		       /*smp_request*/ smp_request,
6586		       /*smp_request_len*/ request_size,
6587		       /*smp_response*/ smp_response,
6588		       /*smp_response_len*/ response_size,
6589		       /*timeout*/ timeout ? timeout : 5000);
6590
6591	ccb->smpio.flags = SMP_FLAG_NONE;
6592
6593	if (((retval = cam_send_ccb(device, ccb)) < 0)
6594	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6595		const char warnstr[] = "error sending command";
6596
6597		if (retval < 0)
6598			warn(warnstr);
6599		else
6600			warnx(warnstr);
6601
6602		if (arglist & CAM_ARG_VERBOSE) {
6603			cam_error_print(device, ccb, CAM_ESF_ALL,
6604					CAM_EPF_ALL, stderr);
6605		}
6606	}
6607
6608	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6609	 && (response_size > 0)) {
6610		if (fd_response == 0) {
6611			buff_decode_visit(smp_response, response_size,
6612					  datastr, arg_put, NULL);
6613			fprintf(stdout, "\n");
6614		} else {
6615			ssize_t amt_written;
6616			int amt_to_write = response_size;
6617			u_int8_t *buf_ptr = smp_response;
6618
6619			for (amt_written = 0; (amt_to_write > 0) &&
6620			     (amt_written = write(STDOUT_FILENO, buf_ptr,
6621						  amt_to_write)) > 0;){
6622				amt_to_write -= amt_written;
6623				buf_ptr += amt_written;
6624			}
6625			if (amt_written == -1) {
6626				warn("error writing data to stdout");
6627				error = 1;
6628				goto smpcmd_bailout;
6629			} else if ((amt_written == 0)
6630				&& (amt_to_write > 0)) {
6631				warnx("only wrote %u bytes out of %u",
6632				      response_size - amt_to_write,
6633				      response_size);
6634			}
6635		}
6636	}
6637smpcmd_bailout:
6638	if (ccb != NULL)
6639		cam_freeccb(ccb);
6640
6641	if (smp_request != NULL)
6642		free(smp_request);
6643
6644	if (smp_response != NULL)
6645		free(smp_response);
6646
6647	return (error);
6648}
6649
6650static int
6651smpreportgeneral(struct cam_device *device, int argc, char **argv,
6652		 char *combinedopt, int retry_count, int timeout)
6653{
6654	union ccb *ccb;
6655	struct smp_report_general_request *request = NULL;
6656	struct smp_report_general_response *response = NULL;
6657	struct sbuf *sb = NULL;
6658	int error = 0;
6659	int c, long_response = 0;
6660	int retval;
6661
6662	/*
6663	 * Note that at the moment we don't support sending SMP CCBs to
6664	 * devices that aren't probed by CAM.
6665	 */
6666	ccb = cam_getccb(device);
6667	if (ccb == NULL) {
6668		warnx("%s: error allocating CCB", __func__);
6669		return (1);
6670	}
6671
6672	bzero(&(&ccb->ccb_h)[1],
6673	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6674
6675	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6676		switch (c) {
6677		case 'l':
6678			long_response = 1;
6679			break;
6680		default:
6681			break;
6682		}
6683	}
6684	request = malloc(sizeof(*request));
6685	if (request == NULL) {
6686		warn("%s: unable to allocate %zd bytes", __func__,
6687		     sizeof(*request));
6688		error = 1;
6689		goto bailout;
6690	}
6691
6692	response = malloc(sizeof(*response));
6693	if (response == NULL) {
6694		warn("%s: unable to allocate %zd bytes", __func__,
6695		     sizeof(*response));
6696		error = 1;
6697		goto bailout;
6698	}
6699
6700try_long:
6701	smp_report_general(&ccb->smpio,
6702			   retry_count,
6703			   /*cbfcnp*/ NULL,
6704			   request,
6705			   /*request_len*/ sizeof(*request),
6706			   (uint8_t *)response,
6707			   /*response_len*/ sizeof(*response),
6708			   /*long_response*/ long_response,
6709			   timeout);
6710
6711	if (((retval = cam_send_ccb(device, ccb)) < 0)
6712	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6713		const char warnstr[] = "error sending command";
6714
6715		if (retval < 0)
6716			warn(warnstr);
6717		else
6718			warnx(warnstr);
6719
6720		if (arglist & CAM_ARG_VERBOSE) {
6721			cam_error_print(device, ccb, CAM_ESF_ALL,
6722					CAM_EPF_ALL, stderr);
6723		}
6724		error = 1;
6725		goto bailout;
6726	}
6727
6728	/*
6729	 * If the device supports the long response bit, try again and see
6730	 * if we can get all of the data.
6731	 */
6732	if ((response->long_response & SMP_RG_LONG_RESPONSE)
6733	 && (long_response == 0)) {
6734		ccb->ccb_h.status = CAM_REQ_INPROG;
6735		bzero(&(&ccb->ccb_h)[1],
6736		      sizeof(union ccb) - sizeof(struct ccb_hdr));
6737		long_response = 1;
6738		goto try_long;
6739	}
6740
6741	/*
6742	 * XXX KDM detect and decode SMP errors here.
6743	 */
6744	sb = sbuf_new_auto();
6745	if (sb == NULL) {
6746		warnx("%s: error allocating sbuf", __func__);
6747		goto bailout;
6748	}
6749
6750	smp_report_general_sbuf(response, sizeof(*response), sb);
6751
6752	if (sbuf_finish(sb) != 0) {
6753		warnx("%s: sbuf_finish", __func__);
6754		goto bailout;
6755	}
6756
6757	printf("%s", sbuf_data(sb));
6758
6759bailout:
6760	if (ccb != NULL)
6761		cam_freeccb(ccb);
6762
6763	if (request != NULL)
6764		free(request);
6765
6766	if (response != NULL)
6767		free(response);
6768
6769	if (sb != NULL)
6770		sbuf_delete(sb);
6771
6772	return (error);
6773}
6774
6775static struct camcontrol_opts phy_ops[] = {
6776	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
6777	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
6778	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
6779	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
6780	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
6781	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
6782	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
6783	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
6784	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
6785	{NULL, 0, 0, NULL}
6786};
6787
6788static int
6789smpphycontrol(struct cam_device *device, int argc, char **argv,
6790	      char *combinedopt, int retry_count, int timeout)
6791{
6792	union ccb *ccb;
6793	struct smp_phy_control_request *request = NULL;
6794	struct smp_phy_control_response *response = NULL;
6795	int long_response = 0;
6796	int retval = 0;
6797	int phy = -1;
6798	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
6799	int phy_op_set = 0;
6800	uint64_t attached_dev_name = 0;
6801	int dev_name_set = 0;
6802	uint32_t min_plr = 0, max_plr = 0;
6803	uint32_t pp_timeout_val = 0;
6804	int slumber_partial = 0;
6805	int set_pp_timeout_val = 0;
6806	int c;
6807
6808	/*
6809	 * Note that at the moment we don't support sending SMP CCBs to
6810	 * devices that aren't probed by CAM.
6811	 */
6812	ccb = cam_getccb(device);
6813	if (ccb == NULL) {
6814		warnx("%s: error allocating CCB", __func__);
6815		return (1);
6816	}
6817
6818	bzero(&(&ccb->ccb_h)[1],
6819	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6820
6821	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6822		switch (c) {
6823		case 'a':
6824		case 'A':
6825		case 's':
6826		case 'S': {
6827			int enable = -1;
6828
6829			if (strcasecmp(optarg, "enable") == 0)
6830				enable = 1;
6831			else if (strcasecmp(optarg, "disable") == 0)
6832				enable = 2;
6833			else {
6834				warnx("%s: Invalid argument %s", __func__,
6835				      optarg);
6836				retval = 1;
6837				goto bailout;
6838			}
6839			switch (c) {
6840			case 's':
6841				slumber_partial |= enable <<
6842						   SMP_PC_SAS_SLUMBER_SHIFT;
6843				break;
6844			case 'S':
6845				slumber_partial |= enable <<
6846						   SMP_PC_SAS_PARTIAL_SHIFT;
6847				break;
6848			case 'a':
6849				slumber_partial |= enable <<
6850						   SMP_PC_SATA_SLUMBER_SHIFT;
6851				break;
6852			case 'A':
6853				slumber_partial |= enable <<
6854						   SMP_PC_SATA_PARTIAL_SHIFT;
6855				break;
6856			default:
6857				warnx("%s: programmer error", __func__);
6858				retval = 1;
6859				goto bailout;
6860				break; /*NOTREACHED*/
6861			}
6862			break;
6863		}
6864		case 'd':
6865			attached_dev_name = (uintmax_t)strtoumax(optarg,
6866								 NULL,0);
6867			dev_name_set = 1;
6868			break;
6869		case 'l':
6870			long_response = 1;
6871			break;
6872		case 'm':
6873			/*
6874			 * We don't do extensive checking here, so this
6875			 * will continue to work when new speeds come out.
6876			 */
6877			min_plr = strtoul(optarg, NULL, 0);
6878			if ((min_plr == 0)
6879			 || (min_plr > 0xf)) {
6880				warnx("%s: invalid link rate %x",
6881				      __func__, min_plr);
6882				retval = 1;
6883				goto bailout;
6884			}
6885			break;
6886		case 'M':
6887			/*
6888			 * We don't do extensive checking here, so this
6889			 * will continue to work when new speeds come out.
6890			 */
6891			max_plr = strtoul(optarg, NULL, 0);
6892			if ((max_plr == 0)
6893			 || (max_plr > 0xf)) {
6894				warnx("%s: invalid link rate %x",
6895				      __func__, max_plr);
6896				retval = 1;
6897				goto bailout;
6898			}
6899			break;
6900		case 'o': {
6901			camcontrol_optret optreturn;
6902			cam_argmask argnums;
6903			const char *subopt;
6904
6905			if (phy_op_set != 0) {
6906				warnx("%s: only one phy operation argument "
6907				      "(-o) allowed", __func__);
6908				retval = 1;
6909				goto bailout;
6910			}
6911
6912			phy_op_set = 1;
6913
6914			/*
6915			 * Allow the user to specify the phy operation
6916			 * numerically, as well as with a name.  This will
6917			 * future-proof it a bit, so options that are added
6918			 * in future specs can be used.
6919			 */
6920			if (isdigit(optarg[0])) {
6921				phy_operation = strtoul(optarg, NULL, 0);
6922				if ((phy_operation == 0)
6923				 || (phy_operation > 0xff)) {
6924					warnx("%s: invalid phy operation %#x",
6925					      __func__, phy_operation);
6926					retval = 1;
6927					goto bailout;
6928				}
6929				break;
6930			}
6931			optreturn = getoption(phy_ops, optarg, &phy_operation,
6932					      &argnums, &subopt);
6933
6934			if (optreturn == CC_OR_AMBIGUOUS) {
6935				warnx("%s: ambiguous option %s", __func__,
6936				      optarg);
6937				usage(0);
6938				retval = 1;
6939				goto bailout;
6940			} else if (optreturn == CC_OR_NOT_FOUND) {
6941				warnx("%s: option %s not found", __func__,
6942				      optarg);
6943				usage(0);
6944				retval = 1;
6945				goto bailout;
6946			}
6947			break;
6948		}
6949		case 'p':
6950			phy = atoi(optarg);
6951			break;
6952		case 'T':
6953			pp_timeout_val = strtoul(optarg, NULL, 0);
6954			if (pp_timeout_val > 15) {
6955				warnx("%s: invalid partial pathway timeout "
6956				      "value %u, need a value less than 16",
6957				      __func__, pp_timeout_val);
6958				retval = 1;
6959				goto bailout;
6960			}
6961			set_pp_timeout_val = 1;
6962			break;
6963		default:
6964			break;
6965		}
6966	}
6967
6968	if (phy == -1) {
6969		warnx("%s: a PHY (-p phy) argument is required",__func__);
6970		retval = 1;
6971		goto bailout;
6972	}
6973
6974	if (((dev_name_set != 0)
6975	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
6976	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
6977	  && (dev_name_set == 0))) {
6978		warnx("%s: -d name and -o setdevname arguments both "
6979		      "required to set device name", __func__);
6980		retval = 1;
6981		goto bailout;
6982	}
6983
6984	request = malloc(sizeof(*request));
6985	if (request == NULL) {
6986		warn("%s: unable to allocate %zd bytes", __func__,
6987		     sizeof(*request));
6988		retval = 1;
6989		goto bailout;
6990	}
6991
6992	response = malloc(sizeof(*response));
6993	if (response == NULL) {
6994		warn("%s: unable to allocate %zd bytes", __func__,
6995		     sizeof(*request));
6996		retval = 1;
6997		goto bailout;
6998	}
6999
7000	smp_phy_control(&ccb->smpio,
7001			retry_count,
7002			/*cbfcnp*/ NULL,
7003			request,
7004			sizeof(*request),
7005			(uint8_t *)response,
7006			sizeof(*response),
7007			long_response,
7008			/*expected_exp_change_count*/ 0,
7009			phy,
7010			phy_operation,
7011			(set_pp_timeout_val != 0) ? 1 : 0,
7012			attached_dev_name,
7013			min_plr,
7014			max_plr,
7015			slumber_partial,
7016			pp_timeout_val,
7017			timeout);
7018
7019	if (((retval = cam_send_ccb(device, ccb)) < 0)
7020	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7021		const char warnstr[] = "error sending command";
7022
7023		if (retval < 0)
7024			warn(warnstr);
7025		else
7026			warnx(warnstr);
7027
7028		if (arglist & CAM_ARG_VERBOSE) {
7029			/*
7030			 * Use CAM_EPF_NORMAL so we only get one line of
7031			 * SMP command decoding.
7032			 */
7033			cam_error_print(device, ccb, CAM_ESF_ALL,
7034					CAM_EPF_NORMAL, stderr);
7035		}
7036		retval = 1;
7037		goto bailout;
7038	}
7039
7040	/* XXX KDM print out something here for success? */
7041bailout:
7042	if (ccb != NULL)
7043		cam_freeccb(ccb);
7044
7045	if (request != NULL)
7046		free(request);
7047
7048	if (response != NULL)
7049		free(response);
7050
7051	return (retval);
7052}
7053
7054static int
7055smpmaninfo(struct cam_device *device, int argc, char **argv,
7056	   char *combinedopt, int retry_count, int timeout)
7057{
7058	union ccb *ccb;
7059	struct smp_report_manuf_info_request request;
7060	struct smp_report_manuf_info_response response;
7061	struct sbuf *sb = NULL;
7062	int long_response = 0;
7063	int retval = 0;
7064	int c;
7065
7066	/*
7067	 * Note that at the moment we don't support sending SMP CCBs to
7068	 * devices that aren't probed by CAM.
7069	 */
7070	ccb = cam_getccb(device);
7071	if (ccb == NULL) {
7072		warnx("%s: error allocating CCB", __func__);
7073		return (1);
7074	}
7075
7076	bzero(&(&ccb->ccb_h)[1],
7077	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7078
7079	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7080		switch (c) {
7081		case 'l':
7082			long_response = 1;
7083			break;
7084		default:
7085			break;
7086		}
7087	}
7088	bzero(&request, sizeof(request));
7089	bzero(&response, sizeof(response));
7090
7091	smp_report_manuf_info(&ccb->smpio,
7092			      retry_count,
7093			      /*cbfcnp*/ NULL,
7094			      &request,
7095			      sizeof(request),
7096			      (uint8_t *)&response,
7097			      sizeof(response),
7098			      long_response,
7099			      timeout);
7100
7101	if (((retval = cam_send_ccb(device, ccb)) < 0)
7102	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7103		const char warnstr[] = "error sending command";
7104
7105		if (retval < 0)
7106			warn(warnstr);
7107		else
7108			warnx(warnstr);
7109
7110		if (arglist & CAM_ARG_VERBOSE) {
7111			cam_error_print(device, ccb, CAM_ESF_ALL,
7112					CAM_EPF_ALL, stderr);
7113		}
7114		retval = 1;
7115		goto bailout;
7116	}
7117
7118	sb = sbuf_new_auto();
7119	if (sb == NULL) {
7120		warnx("%s: error allocating sbuf", __func__);
7121		goto bailout;
7122	}
7123
7124	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7125
7126	if (sbuf_finish(sb) != 0) {
7127		warnx("%s: sbuf_finish", __func__);
7128		goto bailout;
7129	}
7130
7131	printf("%s", sbuf_data(sb));
7132
7133bailout:
7134
7135	if (ccb != NULL)
7136		cam_freeccb(ccb);
7137
7138	if (sb != NULL)
7139		sbuf_delete(sb);
7140
7141	return (retval);
7142}
7143
7144static int
7145getdevid(struct cam_devitem *item)
7146{
7147	int retval = 0;
7148	union ccb *ccb = NULL;
7149
7150	struct cam_device *dev;
7151
7152	dev = cam_open_btl(item->dev_match.path_id,
7153			   item->dev_match.target_id,
7154			   item->dev_match.target_lun, O_RDWR, NULL);
7155
7156	if (dev == NULL) {
7157		warnx("%s", cam_errbuf);
7158		retval = 1;
7159		goto bailout;
7160	}
7161
7162	item->device_id_len = 0;
7163
7164	ccb = cam_getccb(dev);
7165	if (ccb == NULL) {
7166		warnx("%s: error allocating CCB", __func__);
7167		retval = 1;
7168		goto bailout;
7169	}
7170
7171	bzero(&(&ccb->ccb_h)[1],
7172	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7173
7174	/*
7175	 * On the first try, we just probe for the size of the data, and
7176	 * then allocate that much memory and try again.
7177	 */
7178retry:
7179	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7180	ccb->ccb_h.flags = CAM_DIR_IN;
7181	ccb->cdai.flags = 0;
7182	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7183	ccb->cdai.bufsiz = item->device_id_len;
7184	if (item->device_id_len != 0)
7185		ccb->cdai.buf = (uint8_t *)item->device_id;
7186
7187	if (cam_send_ccb(dev, ccb) < 0) {
7188		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7189		retval = 1;
7190		goto bailout;
7191	}
7192
7193	if (ccb->ccb_h.status != CAM_REQ_CMP) {
7194		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7195		retval = 1;
7196		goto bailout;
7197	}
7198
7199	if (item->device_id_len == 0) {
7200		/*
7201		 * This is our first time through.  Allocate the buffer,
7202		 * and then go back to get the data.
7203		 */
7204		if (ccb->cdai.provsiz == 0) {
7205			warnx("%s: invalid .provsiz field returned with "
7206			     "XPT_GDEV_ADVINFO CCB", __func__);
7207			retval = 1;
7208			goto bailout;
7209		}
7210		item->device_id_len = ccb->cdai.provsiz;
7211		item->device_id = malloc(item->device_id_len);
7212		if (item->device_id == NULL) {
7213			warn("%s: unable to allocate %d bytes", __func__,
7214			     item->device_id_len);
7215			retval = 1;
7216			goto bailout;
7217		}
7218		ccb->ccb_h.status = CAM_REQ_INPROG;
7219		goto retry;
7220	}
7221
7222bailout:
7223	if (dev != NULL)
7224		cam_close_device(dev);
7225
7226	if (ccb != NULL)
7227		cam_freeccb(ccb);
7228
7229	return (retval);
7230}
7231
7232/*
7233 * XXX KDM merge this code with getdevtree()?
7234 */
7235static int
7236buildbusdevlist(struct cam_devlist *devlist)
7237{
7238	union ccb ccb;
7239	int bufsize, fd = -1;
7240	struct dev_match_pattern *patterns;
7241	struct cam_devitem *item = NULL;
7242	int skip_device = 0;
7243	int retval = 0;
7244
7245	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7246		warn("couldn't open %s", XPT_DEVICE);
7247		return(1);
7248	}
7249
7250	bzero(&ccb, sizeof(union ccb));
7251
7252	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7253	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7254	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7255
7256	ccb.ccb_h.func_code = XPT_DEV_MATCH;
7257	bufsize = sizeof(struct dev_match_result) * 100;
7258	ccb.cdm.match_buf_len = bufsize;
7259	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7260	if (ccb.cdm.matches == NULL) {
7261		warnx("can't malloc memory for matches");
7262		close(fd);
7263		return(1);
7264	}
7265	ccb.cdm.num_matches = 0;
7266	ccb.cdm.num_patterns = 2;
7267	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7268		ccb.cdm.num_patterns;
7269
7270	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7271	if (patterns == NULL) {
7272		warnx("can't malloc memory for patterns");
7273		retval = 1;
7274		goto bailout;
7275	}
7276
7277	ccb.cdm.patterns = patterns;
7278	bzero(patterns, ccb.cdm.pattern_buf_len);
7279
7280	patterns[0].type = DEV_MATCH_DEVICE;
7281	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7282	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7283	patterns[1].type = DEV_MATCH_PERIPH;
7284	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7285	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7286
7287	/*
7288	 * We do the ioctl multiple times if necessary, in case there are
7289	 * more than 100 nodes in the EDT.
7290	 */
7291	do {
7292		unsigned int i;
7293
7294		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7295			warn("error sending CAMIOCOMMAND ioctl");
7296			retval = 1;
7297			goto bailout;
7298		}
7299
7300		if ((ccb.ccb_h.status != CAM_REQ_CMP)
7301		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7302		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7303			warnx("got CAM error %#x, CDM error %d\n",
7304			      ccb.ccb_h.status, ccb.cdm.status);
7305			retval = 1;
7306			goto bailout;
7307		}
7308
7309		for (i = 0; i < ccb.cdm.num_matches; i++) {
7310			switch (ccb.cdm.matches[i].type) {
7311			case DEV_MATCH_DEVICE: {
7312				struct device_match_result *dev_result;
7313
7314				dev_result =
7315				     &ccb.cdm.matches[i].result.device_result;
7316
7317				if (dev_result->flags &
7318				    DEV_RESULT_UNCONFIGURED) {
7319					skip_device = 1;
7320					break;
7321				} else
7322					skip_device = 0;
7323
7324				item = malloc(sizeof(*item));
7325				if (item == NULL) {
7326					warn("%s: unable to allocate %zd bytes",
7327					     __func__, sizeof(*item));
7328					retval = 1;
7329					goto bailout;
7330				}
7331				bzero(item, sizeof(*item));
7332				bcopy(dev_result, &item->dev_match,
7333				      sizeof(*dev_result));
7334				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7335						   links);
7336
7337				if (getdevid(item) != 0) {
7338					retval = 1;
7339					goto bailout;
7340				}
7341				break;
7342			}
7343			case DEV_MATCH_PERIPH: {
7344				struct periph_match_result *periph_result;
7345
7346				periph_result =
7347				      &ccb.cdm.matches[i].result.periph_result;
7348
7349				if (skip_device != 0)
7350					break;
7351				item->num_periphs++;
7352				item->periph_matches = realloc(
7353					item->periph_matches,
7354					item->num_periphs *
7355					sizeof(struct periph_match_result));
7356				if (item->periph_matches == NULL) {
7357					warn("%s: error allocating periph "
7358					     "list", __func__);
7359					retval = 1;
7360					goto bailout;
7361				}
7362				bcopy(periph_result, &item->periph_matches[
7363				      item->num_periphs - 1],
7364				      sizeof(*periph_result));
7365				break;
7366			}
7367			default:
7368				fprintf(stderr, "%s: unexpected match "
7369					"type %d\n", __func__,
7370					ccb.cdm.matches[i].type);
7371				retval = 1;
7372				goto bailout;
7373				break; /*NOTREACHED*/
7374			}
7375		}
7376	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
7377		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7378bailout:
7379
7380	if (fd != -1)
7381		close(fd);
7382
7383	free(patterns);
7384
7385	free(ccb.cdm.matches);
7386
7387	if (retval != 0)
7388		freebusdevlist(devlist);
7389
7390	return (retval);
7391}
7392
7393static void
7394freebusdevlist(struct cam_devlist *devlist)
7395{
7396	struct cam_devitem *item, *item2;
7397
7398	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7399		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7400			      links);
7401		free(item->device_id);
7402		free(item->periph_matches);
7403		free(item);
7404	}
7405}
7406
7407static struct cam_devitem *
7408findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7409{
7410	struct cam_devitem *item;
7411
7412	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7413		struct scsi_vpd_id_descriptor *idd;
7414
7415		/*
7416		 * XXX KDM look for LUN IDs as well?
7417		 */
7418		idd = scsi_get_devid(item->device_id,
7419					   item->device_id_len,
7420					   scsi_devid_is_sas_target);
7421		if (idd == NULL)
7422			continue;
7423
7424		if (scsi_8btou64(idd->identifier) == sasaddr)
7425			return (item);
7426	}
7427
7428	return (NULL);
7429}
7430
7431static int
7432smpphylist(struct cam_device *device, int argc, char **argv,
7433	   char *combinedopt, int retry_count, int timeout)
7434{
7435	struct smp_report_general_request *rgrequest = NULL;
7436	struct smp_report_general_response *rgresponse = NULL;
7437	struct smp_discover_request *disrequest = NULL;
7438	struct smp_discover_response *disresponse = NULL;
7439	struct cam_devlist devlist;
7440	union ccb *ccb;
7441	int long_response = 0;
7442	int num_phys = 0;
7443	int quiet = 0;
7444	int retval;
7445	int i, c;
7446
7447	/*
7448	 * Note that at the moment we don't support sending SMP CCBs to
7449	 * devices that aren't probed by CAM.
7450	 */
7451	ccb = cam_getccb(device);
7452	if (ccb == NULL) {
7453		warnx("%s: error allocating CCB", __func__);
7454		return (1);
7455	}
7456
7457	bzero(&(&ccb->ccb_h)[1],
7458	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7459	STAILQ_INIT(&devlist.dev_queue);
7460
7461	rgrequest = malloc(sizeof(*rgrequest));
7462	if (rgrequest == NULL) {
7463		warn("%s: unable to allocate %zd bytes", __func__,
7464		     sizeof(*rgrequest));
7465		retval = 1;
7466		goto bailout;
7467	}
7468
7469	rgresponse = malloc(sizeof(*rgresponse));
7470	if (rgresponse == NULL) {
7471		warn("%s: unable to allocate %zd bytes", __func__,
7472		     sizeof(*rgresponse));
7473		retval = 1;
7474		goto bailout;
7475	}
7476
7477	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7478		switch (c) {
7479		case 'l':
7480			long_response = 1;
7481			break;
7482		case 'q':
7483			quiet = 1;
7484			break;
7485		default:
7486			break;
7487		}
7488	}
7489
7490	smp_report_general(&ccb->smpio,
7491			   retry_count,
7492			   /*cbfcnp*/ NULL,
7493			   rgrequest,
7494			   /*request_len*/ sizeof(*rgrequest),
7495			   (uint8_t *)rgresponse,
7496			   /*response_len*/ sizeof(*rgresponse),
7497			   /*long_response*/ long_response,
7498			   timeout);
7499
7500	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7501
7502	if (((retval = cam_send_ccb(device, ccb)) < 0)
7503	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7504		const char warnstr[] = "error sending command";
7505
7506		if (retval < 0)
7507			warn(warnstr);
7508		else
7509			warnx(warnstr);
7510
7511		if (arglist & CAM_ARG_VERBOSE) {
7512			cam_error_print(device, ccb, CAM_ESF_ALL,
7513					CAM_EPF_ALL, stderr);
7514		}
7515		retval = 1;
7516		goto bailout;
7517	}
7518
7519	num_phys = rgresponse->num_phys;
7520
7521	if (num_phys == 0) {
7522		if (quiet == 0)
7523			fprintf(stdout, "%s: No Phys reported\n", __func__);
7524		retval = 1;
7525		goto bailout;
7526	}
7527
7528	devlist.path_id = device->path_id;
7529
7530	retval = buildbusdevlist(&devlist);
7531	if (retval != 0)
7532		goto bailout;
7533
7534	if (quiet == 0) {
7535		fprintf(stdout, "%d PHYs:\n", num_phys);
7536		fprintf(stdout, "PHY  Attached SAS Address\n");
7537	}
7538
7539	disrequest = malloc(sizeof(*disrequest));
7540	if (disrequest == NULL) {
7541		warn("%s: unable to allocate %zd bytes", __func__,
7542		     sizeof(*disrequest));
7543		retval = 1;
7544		goto bailout;
7545	}
7546
7547	disresponse = malloc(sizeof(*disresponse));
7548	if (disresponse == NULL) {
7549		warn("%s: unable to allocate %zd bytes", __func__,
7550		     sizeof(*disresponse));
7551		retval = 1;
7552		goto bailout;
7553	}
7554
7555	for (i = 0; i < num_phys; i++) {
7556		struct cam_devitem *item;
7557		struct device_match_result *dev_match;
7558		char vendor[16], product[48], revision[16];
7559		char tmpstr[256];
7560		int j;
7561
7562		bzero(&(&ccb->ccb_h)[1],
7563		      sizeof(union ccb) - sizeof(struct ccb_hdr));
7564
7565		ccb->ccb_h.status = CAM_REQ_INPROG;
7566		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7567
7568		smp_discover(&ccb->smpio,
7569			     retry_count,
7570			     /*cbfcnp*/ NULL,
7571			     disrequest,
7572			     sizeof(*disrequest),
7573			     (uint8_t *)disresponse,
7574			     sizeof(*disresponse),
7575			     long_response,
7576			     /*ignore_zone_group*/ 0,
7577			     /*phy*/ i,
7578			     timeout);
7579
7580		if (((retval = cam_send_ccb(device, ccb)) < 0)
7581		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7582		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7583			const char warnstr[] = "error sending command";
7584
7585			if (retval < 0)
7586				warn(warnstr);
7587			else
7588				warnx(warnstr);
7589
7590			if (arglist & CAM_ARG_VERBOSE) {
7591				cam_error_print(device, ccb, CAM_ESF_ALL,
7592						CAM_EPF_ALL, stderr);
7593			}
7594			retval = 1;
7595			goto bailout;
7596		}
7597
7598		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7599			if (quiet == 0)
7600				fprintf(stdout, "%3d  <vacant>\n", i);
7601			continue;
7602		}
7603
7604		if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7605			item = NULL;
7606		} else {
7607			item = findsasdevice(&devlist,
7608			    scsi_8btou64(disresponse->attached_sas_address));
7609		}
7610
7611		if ((quiet == 0)
7612		 || (item != NULL)) {
7613			fprintf(stdout, "%3d  0x%016jx", i,
7614				(uintmax_t)scsi_8btou64(
7615				disresponse->attached_sas_address));
7616			if (item == NULL) {
7617				fprintf(stdout, "\n");
7618				continue;
7619			}
7620		} else if (quiet != 0)
7621			continue;
7622
7623		dev_match = &item->dev_match;
7624
7625		if (dev_match->protocol == PROTO_SCSI) {
7626			cam_strvis(vendor, dev_match->inq_data.vendor,
7627				   sizeof(dev_match->inq_data.vendor),
7628				   sizeof(vendor));
7629			cam_strvis(product, dev_match->inq_data.product,
7630				   sizeof(dev_match->inq_data.product),
7631				   sizeof(product));
7632			cam_strvis(revision, dev_match->inq_data.revision,
7633				   sizeof(dev_match->inq_data.revision),
7634				   sizeof(revision));
7635			sprintf(tmpstr, "<%s %s %s>", vendor, product,
7636				revision);
7637		} else if ((dev_match->protocol == PROTO_ATA)
7638			|| (dev_match->protocol == PROTO_SATAPM)) {
7639			cam_strvis(product, dev_match->ident_data.model,
7640				   sizeof(dev_match->ident_data.model),
7641				   sizeof(product));
7642			cam_strvis(revision, dev_match->ident_data.revision,
7643				   sizeof(dev_match->ident_data.revision),
7644				   sizeof(revision));
7645			sprintf(tmpstr, "<%s %s>", product, revision);
7646		} else {
7647			sprintf(tmpstr, "<>");
7648		}
7649		fprintf(stdout, "   %-33s ", tmpstr);
7650
7651		/*
7652		 * If we have 0 periphs, that's a bug...
7653		 */
7654		if (item->num_periphs == 0) {
7655			fprintf(stdout, "\n");
7656			continue;
7657		}
7658
7659		fprintf(stdout, "(");
7660		for (j = 0; j < item->num_periphs; j++) {
7661			if (j > 0)
7662				fprintf(stdout, ",");
7663
7664			fprintf(stdout, "%s%d",
7665				item->periph_matches[j].periph_name,
7666				item->periph_matches[j].unit_number);
7667
7668		}
7669		fprintf(stdout, ")\n");
7670	}
7671bailout:
7672	if (ccb != NULL)
7673		cam_freeccb(ccb);
7674
7675	free(rgrequest);
7676
7677	free(rgresponse);
7678
7679	free(disrequest);
7680
7681	free(disresponse);
7682
7683	freebusdevlist(&devlist);
7684
7685	return (retval);
7686}
7687
7688static int
7689atapm(struct cam_device *device, int argc, char **argv,
7690		 char *combinedopt, int retry_count, int timeout)
7691{
7692	union ccb *ccb;
7693	int retval = 0;
7694	int t = -1;
7695	int c;
7696	u_char cmd, sc;
7697
7698	ccb = cam_getccb(device);
7699
7700	if (ccb == NULL) {
7701		warnx("%s: error allocating ccb", __func__);
7702		return (1);
7703	}
7704
7705	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7706		switch (c) {
7707		case 't':
7708			t = atoi(optarg);
7709			break;
7710		default:
7711			break;
7712		}
7713	}
7714	if (strcmp(argv[1], "idle") == 0) {
7715		if (t == -1)
7716			cmd = ATA_IDLE_IMMEDIATE;
7717		else
7718			cmd = ATA_IDLE_CMD;
7719	} else if (strcmp(argv[1], "standby") == 0) {
7720		if (t == -1)
7721			cmd = ATA_STANDBY_IMMEDIATE;
7722		else
7723			cmd = ATA_STANDBY_CMD;
7724	} else {
7725		cmd = ATA_SLEEP;
7726		t = -1;
7727	}
7728
7729	if (t < 0)
7730		sc = 0;
7731	else if (t <= (240 * 5))
7732		sc = (t + 4) / 5;
7733	else if (t <= (252 * 5))
7734		/* special encoding for 21 minutes */
7735		sc = 252;
7736	else if (t <= (11 * 30 * 60))
7737		sc = (t - 1) / (30 * 60) + 241;
7738	else
7739		sc = 253;
7740
7741	cam_fill_ataio(&ccb->ataio,
7742		      retry_count,
7743		      NULL,
7744		      /*flags*/CAM_DIR_NONE,
7745		      MSG_SIMPLE_Q_TAG,
7746		      /*data_ptr*/NULL,
7747		      /*dxfer_len*/0,
7748		      timeout ? timeout : 30 * 1000);
7749	ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
7750
7751	/* Disable freezing the device queue */
7752	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7753
7754	if (arglist & CAM_ARG_ERR_RECOVER)
7755		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7756
7757	if (cam_send_ccb(device, ccb) < 0) {
7758		warn("error sending command");
7759
7760		if (arglist & CAM_ARG_VERBOSE)
7761			cam_error_print(device, ccb, CAM_ESF_ALL,
7762					CAM_EPF_ALL, stderr);
7763
7764		retval = 1;
7765		goto bailout;
7766	}
7767
7768	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7769		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7770		retval = 1;
7771		goto bailout;
7772	}
7773bailout:
7774	cam_freeccb(ccb);
7775	return (retval);
7776}
7777
7778#endif /* MINIMALISTIC */
7779
7780void
7781usage(int printlong)
7782{
7783
7784	fprintf(printlong ? stdout : stderr,
7785"usage:  camcontrol <command>  [device id][generic args][command args]\n"
7786"        camcontrol devlist    [-v]\n"
7787#ifndef MINIMALISTIC
7788"        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
7789"        camcontrol tur        [dev_id][generic args]\n"
7790"        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
7791"        camcontrol identify   [dev_id][generic args] [-v]\n"
7792"        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
7793"        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
7794"                              [-q] [-s]\n"
7795"        camcontrol start      [dev_id][generic args]\n"
7796"        camcontrol stop       [dev_id][generic args]\n"
7797"        camcontrol load       [dev_id][generic args]\n"
7798"        camcontrol eject      [dev_id][generic args]\n"
7799#endif /* MINIMALISTIC */
7800"        camcontrol rescan     <all | bus[:target:lun]>\n"
7801"        camcontrol reset      <all | bus[:target:lun]>\n"
7802#ifndef MINIMALISTIC
7803"        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
7804"        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
7805"                              [-P pagectl][-e | -b][-d]\n"
7806"        camcontrol cmd        [dev_id][generic args]\n"
7807"                              <-a cmd [args] | -c cmd [args]>\n"
7808"                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
7809"        camcontrol smpcmd     [dev_id][generic args]\n"
7810"                              <-r len fmt [args]> <-R len fmt [args]>\n"
7811"        camcontrol smprg      [dev_id][generic args][-l]\n"
7812"        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
7813"                              [-o operation][-d name][-m rate][-M rate]\n"
7814"                              [-T pp_timeout][-a enable|disable]\n"
7815"                              [-A enable|disable][-s enable|disable]\n"
7816"                              [-S enable|disable]\n"
7817"        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
7818"        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
7819"        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
7820"                              <all|bus[:target[:lun]]|off>\n"
7821"        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
7822"        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
7823"                              [-D <enable|disable>][-M mode][-O offset]\n"
7824"                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
7825"                              [-U][-W bus_width]\n"
7826"        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
7827"        camcontrol sanitize   [dev_id][generic args]\n"
7828"                              [-a overwrite|block|crypto|exitfailure]\n"
7829"                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
7830"                              [-y]\n"
7831"        camcontrol idle       [dev_id][generic args][-t time]\n"
7832"        camcontrol standby    [dev_id][generic args][-t time]\n"
7833"        camcontrol sleep      [dev_id][generic args]\n"
7834"        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
7835"        camcontrol security   [dev_id][generic args]\n"
7836"                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
7837"                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
7838"                              [-U <user|master>] [-y]\n"
7839"        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
7840"                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
7841"        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
7842"                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
7843"                              [-s scope][-S][-T type][-U]\n"
7844#endif /* MINIMALISTIC */
7845"        camcontrol help\n");
7846	if (!printlong)
7847		return;
7848#ifndef MINIMALISTIC
7849	fprintf(stdout,
7850"Specify one of the following options:\n"
7851"devlist     list all CAM devices\n"
7852"periphlist  list all CAM peripheral drivers attached to a device\n"
7853"tur         send a test unit ready to the named device\n"
7854"inquiry     send a SCSI inquiry command to the named device\n"
7855"identify    send a ATA identify command to the named device\n"
7856"reportluns  send a SCSI report luns command to the device\n"
7857"readcap     send a SCSI read capacity command to the device\n"
7858"start       send a Start Unit command to the device\n"
7859"stop        send a Stop Unit command to the device\n"
7860"load        send a Start Unit command to the device with the load bit set\n"
7861"eject       send a Stop Unit command to the device with the eject bit set\n"
7862"rescan      rescan all busses, the given bus, or bus:target:lun\n"
7863"reset       reset all busses, the given bus, or bus:target:lun\n"
7864"defects     read the defect list of the specified device\n"
7865"modepage    display or edit (-e) the given mode page\n"
7866"cmd         send the given SCSI command, may need -i or -o as well\n"
7867"smpcmd      send the given SMP command, requires -o and -i\n"
7868"smprg       send the SMP Report General command\n"
7869"smppc       send the SMP PHY Control command, requires -p\n"
7870"smpphylist  display phys attached to a SAS expander\n"
7871"smpmaninfo  send the SMP Report Manufacturer Info command\n"
7872"debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
7873"tags        report or set the number of transaction slots for a device\n"
7874"negotiate   report or set device negotiation parameters\n"
7875"format      send the SCSI FORMAT UNIT command to the named device\n"
7876"sanitize    send the SCSI SANITIZE command to the named device\n"
7877"idle        send the ATA IDLE command to the named device\n"
7878"standby     send the ATA STANDBY command to the named device\n"
7879"sleep       send the ATA SLEEP command to the named device\n"
7880"fwdownload  program firmware of the named device with the given image\n"
7881"security    report or send ATA security commands to the named device\n"
7882"persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
7883"help        this message\n"
7884"Device Identifiers:\n"
7885"bus:target        specify the bus and target, lun defaults to 0\n"
7886"bus:target:lun    specify the bus, target and lun\n"
7887"deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
7888"Generic arguments:\n"
7889"-v                be verbose, print out sense information\n"
7890"-t timeout        command timeout in seconds, overrides default timeout\n"
7891"-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
7892"-u unit           specify unit number, e.g. \"0\", \"5\"\n"
7893"-E                have the kernel attempt to perform SCSI error recovery\n"
7894"-C count          specify the SCSI command retry count (needs -E to work)\n"
7895"modepage arguments:\n"
7896"-l                list all available mode pages\n"
7897"-m page           specify the mode page to view or edit\n"
7898"-e                edit the specified mode page\n"
7899"-b                force view to binary mode\n"
7900"-d                disable block descriptors for mode sense\n"
7901"-P pgctl          page control field 0-3\n"
7902"defects arguments:\n"
7903"-f format         specify defect list format (block, bfi or phys)\n"
7904"-G                get the grown defect list\n"
7905"-P                get the permanent defect list\n"
7906"inquiry arguments:\n"
7907"-D                get the standard inquiry data\n"
7908"-S                get the serial number\n"
7909"-R                get the transfer rate, etc.\n"
7910"reportluns arguments:\n"
7911"-c                only report a count of available LUNs\n"
7912"-l                only print out luns, and not a count\n"
7913"-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
7914"readcap arguments\n"
7915"-b                only report the blocksize\n"
7916"-h                human readable device size, base 2\n"
7917"-H                human readable device size, base 10\n"
7918"-N                print the number of blocks instead of last block\n"
7919"-q                quiet, print numbers only\n"
7920"-s                only report the last block/device size\n"
7921"cmd arguments:\n"
7922"-c cdb [args]     specify the SCSI CDB\n"
7923"-i len fmt        specify input data and input data format\n"
7924"-o len fmt [args] specify output data and output data fmt\n"
7925"smpcmd arguments:\n"
7926"-r len fmt [args] specify the SMP command to be sent\n"
7927"-R len fmt [args] specify SMP response format\n"
7928"smprg arguments:\n"
7929"-l                specify the long response format\n"
7930"smppc arguments:\n"
7931"-p phy            specify the PHY to operate on\n"
7932"-l                specify the long request/response format\n"
7933"-o operation      specify the phy control operation\n"
7934"-d name           set the attached device name\n"
7935"-m rate           set the minimum physical link rate\n"
7936"-M rate           set the maximum physical link rate\n"
7937"-T pp_timeout     set the partial pathway timeout value\n"
7938"-a enable|disable enable or disable SATA slumber\n"
7939"-A enable|disable enable or disable SATA partial phy power\n"
7940"-s enable|disable enable or disable SAS slumber\n"
7941"-S enable|disable enable or disable SAS partial phy power\n"
7942"smpphylist arguments:\n"
7943"-l                specify the long response format\n"
7944"-q                only print phys with attached devices\n"
7945"smpmaninfo arguments:\n"
7946"-l                specify the long response format\n"
7947"debug arguments:\n"
7948"-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
7949"-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
7950"-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
7951"-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
7952"tags arguments:\n"
7953"-N tags           specify the number of tags to use for this device\n"
7954"-q                be quiet, don't report the number of tags\n"
7955"-v                report a number of tag-related parameters\n"
7956"negotiate arguments:\n"
7957"-a                send a test unit ready after negotiation\n"
7958"-c                report/set current negotiation settings\n"
7959"-D <arg>          \"enable\" or \"disable\" disconnection\n"
7960"-M mode           set ATA mode\n"
7961"-O offset         set command delay offset\n"
7962"-q                be quiet, don't report anything\n"
7963"-R syncrate       synchronization rate in MHz\n"
7964"-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
7965"-U                report/set user negotiation settings\n"
7966"-W bus_width      set the bus width in bits (8, 16 or 32)\n"
7967"-v                also print a Path Inquiry CCB for the controller\n"
7968"format arguments:\n"
7969"-q                be quiet, don't print status messages\n"
7970"-r                run in report only mode\n"
7971"-w                don't send immediate format command\n"
7972"-y                don't ask any questions\n"
7973"sanitize arguments:\n"
7974"-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
7975"-c passes         overwrite passes to perform (1 to 31)\n"
7976"-I                invert overwrite pattern after each pass\n"
7977"-P pattern        path to overwrite pattern file\n"
7978"-q                be quiet, don't print status messages\n"
7979"-r                run in report only mode\n"
7980"-U                run operation in unrestricted completion exit mode\n"
7981"-w                don't send immediate sanitize command\n"
7982"-y                don't ask any questions\n"
7983"idle/standby arguments:\n"
7984"-t <arg>          number of seconds before respective state.\n"
7985"fwdownload arguments:\n"
7986"-f fw_image       path to firmware image file\n"
7987"-y                don't ask any questions\n"
7988"-s                run in simulation mode\n"
7989"-v                print info for every firmware segment sent to device\n"
7990"security arguments:\n"
7991"-d pwd            disable security using the given password for the selected\n"
7992"                  user\n"
7993"-e pwd            erase the device using the given pwd for the selected user\n"
7994"-f                freeze the security configuration of the specified device\n"
7995"-h pwd            enhanced erase the device using the given pwd for the\n"
7996"                  selected user\n"
7997"-k pwd            unlock the device using the given pwd for the selected\n"
7998"                  user\n"
7999"-l <high|maximum> specifies which security level to set: high or maximum\n"
8000"-q                be quiet, do not print any status messages\n"
8001"-s pwd            password the device (enable security) using the given\n"
8002"                  pwd for the selected user\n"
8003"-T timeout        overrides the timeout (seconds) used for erase operation\n"
8004"-U <user|master>  specifies which user to set: user or master\n"
8005"-y                don't ask any questions\n"
8006"hpa arguments:\n"
8007"-f                freeze the HPA configuration of the device\n"
8008"-l                lock the HPA configuration of the device\n"
8009"-P                make the HPA max sectors persist\n"
8010"-p pwd            Set the HPA configuration password required for unlock\n"
8011"                  calls\n"
8012"-q                be quiet, do not print any status messages\n"
8013"-s sectors        configures the maximum user accessible sectors of the\n"
8014"                  device\n"
8015"-U pwd            unlock the HPA configuration of the device\n"
8016"-y                don't ask any questions\n"
8017"persist arguments:\n"
8018"-i action         specify read_keys, read_reservation, report_cap, or\n"
8019"                  read_full_status\n"
8020"-o action         specify register, register_ignore, reserve, release,\n"
8021"                  clear, preempt, preempt_abort, register_move, replace_lost\n"
8022"-a                set the All Target Ports (ALL_TG_PT) bit\n"
8023"-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8024"-k key            specify the Reservation Key\n"
8025"-K sa_key         specify the Service Action Reservation Key\n"
8026"-p                set the Activate Persist Through Power Loss bit\n"
8027"-R rtp            specify the Relative Target Port\n"
8028"-s scope          specify the scope: lun, extent, element or a number\n"
8029"-S                specify Transport ID for register, requires -I\n"
8030"-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8031"                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8032"-U                unregister the current initiator for register_move\n"
8033);
8034#endif /* MINIMALISTIC */
8035}
8036
8037int
8038main(int argc, char **argv)
8039{
8040	int c;
8041	char *device = NULL;
8042	int unit = 0;
8043	struct cam_device *cam_dev = NULL;
8044	int timeout = 0, retry_count = 1;
8045	camcontrol_optret optreturn;
8046	char *tstr;
8047	const char *mainopt = "C:En:t:u:v";
8048	const char *subopt = NULL;
8049	char combinedopt[256];
8050	int error = 0, optstart = 2;
8051	int devopen = 1;
8052#ifndef MINIMALISTIC
8053	path_id_t bus;
8054	target_id_t target;
8055	lun_id_t lun;
8056#endif /* MINIMALISTIC */
8057
8058	cmdlist = CAM_CMD_NONE;
8059	arglist = CAM_ARG_NONE;
8060
8061	if (argc < 2) {
8062		usage(0);
8063		exit(1);
8064	}
8065
8066	/*
8067	 * Get the base option.
8068	 */
8069	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8070
8071	if (optreturn == CC_OR_AMBIGUOUS) {
8072		warnx("ambiguous option %s", argv[1]);
8073		usage(0);
8074		exit(1);
8075	} else if (optreturn == CC_OR_NOT_FOUND) {
8076		warnx("option %s not found", argv[1]);
8077		usage(0);
8078		exit(1);
8079	}
8080
8081	/*
8082	 * Ahh, getopt(3) is a pain.
8083	 *
8084	 * This is a gross hack.  There really aren't many other good
8085	 * options (excuse the pun) for parsing options in a situation like
8086	 * this.  getopt is kinda braindead, so you end up having to run
8087	 * through the options twice, and give each invocation of getopt
8088	 * the option string for the other invocation.
8089	 *
8090	 * You would think that you could just have two groups of options.
8091	 * The first group would get parsed by the first invocation of
8092	 * getopt, and the second group would get parsed by the second
8093	 * invocation of getopt.  It doesn't quite work out that way.  When
8094	 * the first invocation of getopt finishes, it leaves optind pointing
8095	 * to the argument _after_ the first argument in the second group.
8096	 * So when the second invocation of getopt comes around, it doesn't
8097	 * recognize the first argument it gets and then bails out.
8098	 *
8099	 * A nice alternative would be to have a flag for getopt that says
8100	 * "just keep parsing arguments even when you encounter an unknown
8101	 * argument", but there isn't one.  So there's no real clean way to
8102	 * easily parse two sets of arguments without having one invocation
8103	 * of getopt know about the other.
8104	 *
8105	 * Without this hack, the first invocation of getopt would work as
8106	 * long as the generic arguments are first, but the second invocation
8107	 * (in the subfunction) would fail in one of two ways.  In the case
8108	 * where you don't set optreset, it would fail because optind may be
8109	 * pointing to the argument after the one it should be pointing at.
8110	 * In the case where you do set optreset, and reset optind, it would
8111	 * fail because getopt would run into the first set of options, which
8112	 * it doesn't understand.
8113	 *
8114	 * All of this would "sort of" work if you could somehow figure out
8115	 * whether optind had been incremented one option too far.  The
8116	 * mechanics of that, however, are more daunting than just giving
8117	 * both invocations all of the expect options for either invocation.
8118	 *
8119	 * Needless to say, I wouldn't mind if someone invented a better
8120	 * (non-GPL!) command line parsing interface than getopt.  I
8121	 * wouldn't mind if someone added more knobs to getopt to make it
8122	 * work better.  Who knows, I may talk myself into doing it someday,
8123	 * if the standards weenies let me.  As it is, it just leads to
8124	 * hackery like this and causes people to avoid it in some cases.
8125	 *
8126	 * KDM, September 8th, 1998
8127	 */
8128	if (subopt != NULL)
8129		sprintf(combinedopt, "%s%s", mainopt, subopt);
8130	else
8131		sprintf(combinedopt, "%s", mainopt);
8132
8133	/*
8134	 * For these options we do not parse optional device arguments and
8135	 * we do not open a passthrough device.
8136	 */
8137	if ((cmdlist == CAM_CMD_RESCAN)
8138	 || (cmdlist == CAM_CMD_RESET)
8139	 || (cmdlist == CAM_CMD_DEVTREE)
8140	 || (cmdlist == CAM_CMD_USAGE)
8141	 || (cmdlist == CAM_CMD_DEBUG))
8142		devopen = 0;
8143
8144#ifndef MINIMALISTIC
8145	if ((devopen == 1)
8146	 && (argc > 2 && argv[2][0] != '-')) {
8147		char name[30];
8148		int rv;
8149
8150		if (isdigit(argv[2][0])) {
8151			/* device specified as bus:target[:lun] */
8152			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
8153			if (rv < 2)
8154				errx(1, "numeric device specification must "
8155				     "be either bus:target, or "
8156				     "bus:target:lun");
8157			/* default to 0 if lun was not specified */
8158			if ((arglist & CAM_ARG_LUN) == 0) {
8159				lun = 0;
8160				arglist |= CAM_ARG_LUN;
8161			}
8162			optstart++;
8163		} else {
8164			if (cam_get_device(argv[2], name, sizeof name, &unit)
8165			    == -1)
8166				errx(1, "%s", cam_errbuf);
8167			device = strdup(name);
8168			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
8169			optstart++;
8170		}
8171	}
8172#endif /* MINIMALISTIC */
8173	/*
8174	 * Start getopt processing at argv[2/3], since we've already
8175	 * accepted argv[1..2] as the command name, and as a possible
8176	 * device name.
8177	 */
8178	optind = optstart;
8179
8180	/*
8181	 * Now we run through the argument list looking for generic
8182	 * options, and ignoring options that possibly belong to
8183	 * subfunctions.
8184	 */
8185	while ((c = getopt(argc, argv, combinedopt))!= -1){
8186		switch(c) {
8187			case 'C':
8188				retry_count = strtol(optarg, NULL, 0);
8189				if (retry_count < 0)
8190					errx(1, "retry count %d is < 0",
8191					     retry_count);
8192				arglist |= CAM_ARG_RETRIES;
8193				break;
8194			case 'E':
8195				arglist |= CAM_ARG_ERR_RECOVER;
8196				break;
8197			case 'n':
8198				arglist |= CAM_ARG_DEVICE;
8199				tstr = optarg;
8200				while (isspace(*tstr) && (*tstr != '\0'))
8201					tstr++;
8202				device = (char *)strdup(tstr);
8203				break;
8204			case 't':
8205				timeout = strtol(optarg, NULL, 0);
8206				if (timeout < 0)
8207					errx(1, "invalid timeout %d", timeout);
8208				/* Convert the timeout from seconds to ms */
8209				timeout *= 1000;
8210				arglist |= CAM_ARG_TIMEOUT;
8211				break;
8212			case 'u':
8213				arglist |= CAM_ARG_UNIT;
8214				unit = strtol(optarg, NULL, 0);
8215				break;
8216			case 'v':
8217				arglist |= CAM_ARG_VERBOSE;
8218				break;
8219			default:
8220				break;
8221		}
8222	}
8223
8224#ifndef MINIMALISTIC
8225	/*
8226	 * For most commands we'll want to open the passthrough device
8227	 * associated with the specified device.  In the case of the rescan
8228	 * commands, we don't use a passthrough device at all, just the
8229	 * transport layer device.
8230	 */
8231	if (devopen == 1) {
8232		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
8233		 && (((arglist & CAM_ARG_DEVICE) == 0)
8234		  || ((arglist & CAM_ARG_UNIT) == 0))) {
8235			errx(1, "subcommand \"%s\" requires a valid device "
8236			     "identifier", argv[1]);
8237		}
8238
8239		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
8240				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
8241				cam_open_spec_device(device,unit,O_RDWR,NULL)))
8242		     == NULL)
8243			errx(1,"%s", cam_errbuf);
8244	}
8245#endif /* MINIMALISTIC */
8246
8247	/*
8248	 * Reset optind to 2, and reset getopt, so these routines can parse
8249	 * the arguments again.
8250	 */
8251	optind = optstart;
8252	optreset = 1;
8253
8254	switch(cmdlist) {
8255#ifndef MINIMALISTIC
8256		case CAM_CMD_DEVLIST:
8257			error = getdevlist(cam_dev);
8258			break;
8259		case CAM_CMD_HPA:
8260			error = atahpa(cam_dev, retry_count, timeout,
8261				       argc, argv, combinedopt);
8262			break;
8263#endif /* MINIMALISTIC */
8264		case CAM_CMD_DEVTREE:
8265			error = getdevtree(argc, argv, combinedopt);
8266			break;
8267#ifndef MINIMALISTIC
8268		case CAM_CMD_TUR:
8269			error = testunitready(cam_dev, retry_count, timeout, 0);
8270			break;
8271		case CAM_CMD_INQUIRY:
8272			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
8273					      retry_count, timeout);
8274			break;
8275		case CAM_CMD_IDENTIFY:
8276			error = ataidentify(cam_dev, retry_count, timeout);
8277			break;
8278		case CAM_CMD_STARTSTOP:
8279			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
8280					  arglist & CAM_ARG_EJECT, retry_count,
8281					  timeout);
8282			break;
8283#endif /* MINIMALISTIC */
8284		case CAM_CMD_RESCAN:
8285			error = dorescan_or_reset(argc, argv, 1);
8286			break;
8287		case CAM_CMD_RESET:
8288			error = dorescan_or_reset(argc, argv, 0);
8289			break;
8290#ifndef MINIMALISTIC
8291		case CAM_CMD_READ_DEFECTS:
8292			error = readdefects(cam_dev, argc, argv, combinedopt,
8293					    retry_count, timeout);
8294			break;
8295		case CAM_CMD_MODE_PAGE:
8296			modepage(cam_dev, argc, argv, combinedopt,
8297				 retry_count, timeout);
8298			break;
8299		case CAM_CMD_SCSI_CMD:
8300			error = scsicmd(cam_dev, argc, argv, combinedopt,
8301					retry_count, timeout);
8302			break;
8303		case CAM_CMD_SMP_CMD:
8304			error = smpcmd(cam_dev, argc, argv, combinedopt,
8305				       retry_count, timeout);
8306			break;
8307		case CAM_CMD_SMP_RG:
8308			error = smpreportgeneral(cam_dev, argc, argv,
8309						 combinedopt, retry_count,
8310						 timeout);
8311			break;
8312		case CAM_CMD_SMP_PC:
8313			error = smpphycontrol(cam_dev, argc, argv, combinedopt,
8314					      retry_count, timeout);
8315			break;
8316		case CAM_CMD_SMP_PHYLIST:
8317			error = smpphylist(cam_dev, argc, argv, combinedopt,
8318					   retry_count, timeout);
8319			break;
8320		case CAM_CMD_SMP_MANINFO:
8321			error = smpmaninfo(cam_dev, argc, argv, combinedopt,
8322					   retry_count, timeout);
8323			break;
8324		case CAM_CMD_DEBUG:
8325			error = camdebug(argc, argv, combinedopt);
8326			break;
8327		case CAM_CMD_TAG:
8328			error = tagcontrol(cam_dev, argc, argv, combinedopt);
8329			break;
8330		case CAM_CMD_RATE:
8331			error = ratecontrol(cam_dev, retry_count, timeout,
8332					    argc, argv, combinedopt);
8333			break;
8334		case CAM_CMD_FORMAT:
8335			error = scsiformat(cam_dev, argc, argv,
8336					   combinedopt, retry_count, timeout);
8337			break;
8338		case CAM_CMD_REPORTLUNS:
8339			error = scsireportluns(cam_dev, argc, argv,
8340					       combinedopt, retry_count,
8341					       timeout);
8342			break;
8343		case CAM_CMD_READCAP:
8344			error = scsireadcapacity(cam_dev, argc, argv,
8345						 combinedopt, retry_count,
8346						 timeout);
8347			break;
8348		case CAM_CMD_IDLE:
8349		case CAM_CMD_STANDBY:
8350		case CAM_CMD_SLEEP:
8351			error = atapm(cam_dev, argc, argv,
8352				      combinedopt, retry_count, timeout);
8353			break;
8354		case CAM_CMD_SECURITY:
8355			error = atasecurity(cam_dev, retry_count, timeout,
8356					    argc, argv, combinedopt);
8357			break;
8358		case CAM_CMD_DOWNLOAD_FW:
8359			error = fwdownload(cam_dev, argc, argv, combinedopt,
8360			    arglist & CAM_ARG_VERBOSE, retry_count, timeout,
8361			    get_disk_type(cam_dev));
8362			break;
8363		case CAM_CMD_SANITIZE:
8364			error = scsisanitize(cam_dev, argc, argv,
8365					     combinedopt, retry_count, timeout);
8366			break;
8367		case CAM_CMD_PERSIST:
8368			error = scsipersist(cam_dev, argc, argv, combinedopt,
8369			    retry_count, timeout, arglist & CAM_ARG_VERBOSE,
8370			    arglist & CAM_ARG_ERR_RECOVER);
8371			break;
8372#endif /* MINIMALISTIC */
8373		case CAM_CMD_USAGE:
8374			usage(1);
8375			break;
8376		default:
8377			usage(0);
8378			error = 1;
8379			break;
8380	}
8381
8382	if (cam_dev != NULL)
8383		cam_close_device(cam_dev);
8384
8385	exit(error);
8386}
8387