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