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