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