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