camcontrol.c revision 312951
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 312951 2017-01-29 14:29:02Z 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, valid_bytes;
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 (cdb_len)
4453		valid_bytes = ccb->csio.dxfer_len - ccb->csio.resid;
4454	else
4455		valid_bytes = ccb->ataio.dxfer_len - ccb->ataio.resid;
4456	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4457	 && (arglist & CAM_ARG_CMD_IN)
4458	 && (valid_bytes > 0)) {
4459		if (fd_data == 0) {
4460			buff_decode_visit(data_ptr, valid_bytes, datastr,
4461					  arg_put, NULL);
4462			fprintf(stdout, "\n");
4463		} else {
4464			ssize_t amt_written;
4465			int amt_to_write = valid_bytes;
4466			u_int8_t *buf_ptr = data_ptr;
4467
4468			for (amt_written = 0; (amt_to_write > 0) &&
4469			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4470				amt_to_write -= amt_written;
4471				buf_ptr += amt_written;
4472			}
4473			if (amt_written == -1) {
4474				warn("error writing data to stdout");
4475				error = 1;
4476				goto scsicmd_bailout;
4477			} else if ((amt_written == 0)
4478				&& (amt_to_write > 0)) {
4479				warnx("only wrote %u bytes out of %u",
4480				      valid_bytes - amt_to_write, valid_bytes);
4481			}
4482		}
4483	}
4484
4485scsicmd_bailout:
4486
4487	if ((data_bytes > 0) && (data_ptr != NULL))
4488		free(data_ptr);
4489
4490	cam_freeccb(ccb);
4491
4492	return(error);
4493}
4494
4495static int
4496camdebug(int argc, char **argv, char *combinedopt)
4497{
4498	int c, fd;
4499	path_id_t bus = CAM_BUS_WILDCARD;
4500	target_id_t target = CAM_TARGET_WILDCARD;
4501	lun_id_t lun = CAM_LUN_WILDCARD;
4502	char *tstr, *tmpstr = NULL;
4503	union ccb ccb;
4504	int error = 0;
4505
4506	bzero(&ccb, sizeof(union ccb));
4507
4508	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4509		switch(c) {
4510		case 'I':
4511			arglist |= CAM_ARG_DEBUG_INFO;
4512			ccb.cdbg.flags |= CAM_DEBUG_INFO;
4513			break;
4514		case 'P':
4515			arglist |= CAM_ARG_DEBUG_PERIPH;
4516			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4517			break;
4518		case 'S':
4519			arglist |= CAM_ARG_DEBUG_SUBTRACE;
4520			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4521			break;
4522		case 'T':
4523			arglist |= CAM_ARG_DEBUG_TRACE;
4524			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4525			break;
4526		case 'X':
4527			arglist |= CAM_ARG_DEBUG_XPT;
4528			ccb.cdbg.flags |= CAM_DEBUG_XPT;
4529			break;
4530		case 'c':
4531			arglist |= CAM_ARG_DEBUG_CDB;
4532			ccb.cdbg.flags |= CAM_DEBUG_CDB;
4533			break;
4534		case 'p':
4535			arglist |= CAM_ARG_DEBUG_PROBE;
4536			ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4537			break;
4538		default:
4539			break;
4540		}
4541	}
4542
4543	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4544		warnx("error opening transport layer device %s", XPT_DEVICE);
4545		warn("%s", XPT_DEVICE);
4546		return(1);
4547	}
4548	argc -= optind;
4549	argv += optind;
4550
4551	if (argc <= 0) {
4552		warnx("you must specify \"off\", \"all\" or a bus,");
4553		warnx("bus:target, or bus:target:lun");
4554		close(fd);
4555		return(1);
4556	}
4557
4558	tstr = *argv;
4559
4560	while (isspace(*tstr) && (*tstr != '\0'))
4561		tstr++;
4562
4563	if (strncmp(tstr, "off", 3) == 0) {
4564		ccb.cdbg.flags = CAM_DEBUG_NONE;
4565		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4566			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4567			     CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4568	} else if (strncmp(tstr, "all", 3) != 0) {
4569		tmpstr = (char *)strtok(tstr, ":");
4570		if ((tmpstr != NULL) && (*tmpstr != '\0')){
4571			bus = strtol(tmpstr, NULL, 0);
4572			arglist |= CAM_ARG_BUS;
4573			tmpstr = (char *)strtok(NULL, ":");
4574			if ((tmpstr != NULL) && (*tmpstr != '\0')){
4575				target = strtol(tmpstr, NULL, 0);
4576				arglist |= CAM_ARG_TARGET;
4577				tmpstr = (char *)strtok(NULL, ":");
4578				if ((tmpstr != NULL) && (*tmpstr != '\0')){
4579					lun = strtol(tmpstr, NULL, 0);
4580					arglist |= CAM_ARG_LUN;
4581				}
4582			}
4583		} else {
4584			error = 1;
4585			warnx("you must specify \"all\", \"off\", or a bus,");
4586			warnx("bus:target, or bus:target:lun to debug");
4587		}
4588	}
4589
4590	if (error == 0) {
4591
4592		ccb.ccb_h.func_code = XPT_DEBUG;
4593		ccb.ccb_h.path_id = bus;
4594		ccb.ccb_h.target_id = target;
4595		ccb.ccb_h.target_lun = lun;
4596
4597		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4598			warn("CAMIOCOMMAND ioctl failed");
4599			error = 1;
4600		}
4601
4602		if (error == 0) {
4603			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4604			     CAM_FUNC_NOTAVAIL) {
4605				warnx("CAM debugging not available");
4606				warnx("you need to put options CAMDEBUG in"
4607				      " your kernel config file!");
4608				error = 1;
4609			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4610				    CAM_REQ_CMP) {
4611				warnx("XPT_DEBUG CCB failed with status %#x",
4612				      ccb.ccb_h.status);
4613				error = 1;
4614			} else {
4615				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4616					fprintf(stderr,
4617						"Debugging turned off\n");
4618				} else {
4619					fprintf(stderr,
4620						"Debugging enabled for "
4621						"%d:%d:%jx\n",
4622						bus, target, (uintmax_t)lun);
4623				}
4624			}
4625		}
4626		close(fd);
4627	}
4628
4629	return(error);
4630}
4631
4632static int
4633tagcontrol(struct cam_device *device, int argc, char **argv,
4634	   char *combinedopt)
4635{
4636	int c;
4637	union ccb *ccb;
4638	int numtags = -1;
4639	int retval = 0;
4640	int quiet = 0;
4641	char pathstr[1024];
4642
4643	ccb = cam_getccb(device);
4644
4645	if (ccb == NULL) {
4646		warnx("tagcontrol: error allocating ccb");
4647		return(1);
4648	}
4649
4650	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4651		switch(c) {
4652		case 'N':
4653			numtags = strtol(optarg, NULL, 0);
4654			if (numtags < 0) {
4655				warnx("tag count %d is < 0", numtags);
4656				retval = 1;
4657				goto tagcontrol_bailout;
4658			}
4659			break;
4660		case 'q':
4661			quiet++;
4662			break;
4663		default:
4664			break;
4665		}
4666	}
4667
4668	cam_path_string(device, pathstr, sizeof(pathstr));
4669
4670	if (numtags >= 0) {
4671		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->crs);
4672		ccb->ccb_h.func_code = XPT_REL_SIMQ;
4673		ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4674		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4675		ccb->crs.openings = numtags;
4676
4677
4678		if (cam_send_ccb(device, ccb) < 0) {
4679			perror("error sending XPT_REL_SIMQ CCB");
4680			retval = 1;
4681			goto tagcontrol_bailout;
4682		}
4683
4684		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4685			warnx("XPT_REL_SIMQ CCB failed");
4686			cam_error_print(device, ccb, CAM_ESF_ALL,
4687					CAM_EPF_ALL, stderr);
4688			retval = 1;
4689			goto tagcontrol_bailout;
4690		}
4691
4692
4693		if (quiet == 0)
4694			fprintf(stdout, "%stagged openings now %d\n",
4695				pathstr, ccb->crs.openings);
4696	}
4697
4698	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgds);
4699
4700	ccb->ccb_h.func_code = XPT_GDEV_STATS;
4701
4702	if (cam_send_ccb(device, ccb) < 0) {
4703		perror("error sending XPT_GDEV_STATS CCB");
4704		retval = 1;
4705		goto tagcontrol_bailout;
4706	}
4707
4708	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4709		warnx("XPT_GDEV_STATS CCB failed");
4710		cam_error_print(device, ccb, CAM_ESF_ALL,
4711				CAM_EPF_ALL, stderr);
4712		retval = 1;
4713		goto tagcontrol_bailout;
4714	}
4715
4716	if (arglist & CAM_ARG_VERBOSE) {
4717		fprintf(stdout, "%s", pathstr);
4718		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4719		fprintf(stdout, "%s", pathstr);
4720		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4721		fprintf(stdout, "%s", pathstr);
4722		fprintf(stdout, "allocated     %d\n", ccb->cgds.allocated);
4723		fprintf(stdout, "%s", pathstr);
4724		fprintf(stdout, "queued        %d\n", ccb->cgds.queued);
4725		fprintf(stdout, "%s", pathstr);
4726		fprintf(stdout, "held          %d\n", ccb->cgds.held);
4727		fprintf(stdout, "%s", pathstr);
4728		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4729		fprintf(stdout, "%s", pathstr);
4730		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4731	} else {
4732		if (quiet == 0) {
4733			fprintf(stdout, "%s", pathstr);
4734			fprintf(stdout, "device openings: ");
4735		}
4736		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4737			ccb->cgds.dev_active);
4738	}
4739
4740tagcontrol_bailout:
4741
4742	cam_freeccb(ccb);
4743	return(retval);
4744}
4745
4746static void
4747cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4748{
4749	char pathstr[1024];
4750
4751	cam_path_string(device, pathstr, sizeof(pathstr));
4752
4753	if (cts->transport == XPORT_SPI) {
4754		struct ccb_trans_settings_spi *spi =
4755		    &cts->xport_specific.spi;
4756
4757		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4758
4759			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4760				spi->sync_period);
4761
4762			if (spi->sync_offset != 0) {
4763				u_int freq;
4764
4765				freq = scsi_calc_syncsrate(spi->sync_period);
4766				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4767					pathstr, freq / 1000, freq % 1000);
4768			}
4769		}
4770
4771		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4772			fprintf(stdout, "%soffset: %d\n", pathstr,
4773			    spi->sync_offset);
4774		}
4775
4776		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4777			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4778				(0x01 << spi->bus_width) * 8);
4779		}
4780
4781		if (spi->valid & CTS_SPI_VALID_DISC) {
4782			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4783				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4784				"enabled" : "disabled");
4785		}
4786	}
4787	if (cts->transport == XPORT_FC) {
4788		struct ccb_trans_settings_fc *fc =
4789		    &cts->xport_specific.fc;
4790
4791		if (fc->valid & CTS_FC_VALID_WWNN)
4792			fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4793			    (long long) fc->wwnn);
4794		if (fc->valid & CTS_FC_VALID_WWPN)
4795			fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4796			    (long long) fc->wwpn);
4797		if (fc->valid & CTS_FC_VALID_PORT)
4798			fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4799		if (fc->valid & CTS_FC_VALID_SPEED)
4800			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4801			    pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4802	}
4803	if (cts->transport == XPORT_SAS) {
4804		struct ccb_trans_settings_sas *sas =
4805		    &cts->xport_specific.sas;
4806
4807		if (sas->valid & CTS_SAS_VALID_SPEED)
4808			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4809			    pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4810	}
4811	if (cts->transport == XPORT_ATA) {
4812		struct ccb_trans_settings_pata *pata =
4813		    &cts->xport_specific.ata;
4814
4815		if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4816			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4817				ata_mode2string(pata->mode));
4818		}
4819		if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4820			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4821				pata->atapi);
4822		}
4823		if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4824			fprintf(stdout, "%sPIO transaction length: %d\n",
4825				pathstr, pata->bytecount);
4826		}
4827	}
4828	if (cts->transport == XPORT_SATA) {
4829		struct ccb_trans_settings_sata *sata =
4830		    &cts->xport_specific.sata;
4831
4832		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4833			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4834				sata->revision);
4835		}
4836		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4837			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4838				ata_mode2string(sata->mode));
4839		}
4840		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4841			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4842				sata->atapi);
4843		}
4844		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4845			fprintf(stdout, "%sPIO transaction length: %d\n",
4846				pathstr, sata->bytecount);
4847		}
4848		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4849			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4850				sata->pm_present);
4851		}
4852		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4853			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4854				sata->tags);
4855		}
4856		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4857			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4858				sata->caps);
4859		}
4860	}
4861	if (cts->protocol == PROTO_ATA) {
4862		struct ccb_trans_settings_ata *ata=
4863		    &cts->proto_specific.ata;
4864
4865		if (ata->valid & CTS_ATA_VALID_TQ) {
4866			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4867				(ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4868				"enabled" : "disabled");
4869		}
4870	}
4871	if (cts->protocol == PROTO_SCSI) {
4872		struct ccb_trans_settings_scsi *scsi=
4873		    &cts->proto_specific.scsi;
4874
4875		if (scsi->valid & CTS_SCSI_VALID_TQ) {
4876			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4877				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4878				"enabled" : "disabled");
4879		}
4880	}
4881
4882}
4883
4884/*
4885 * Get a path inquiry CCB for the specified device.
4886 */
4887static int
4888get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4889{
4890	union ccb *ccb;
4891	int retval = 0;
4892
4893	ccb = cam_getccb(device);
4894	if (ccb == NULL) {
4895		warnx("get_cpi: couldn't allocate CCB");
4896		return(1);
4897	}
4898	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
4899	ccb->ccb_h.func_code = XPT_PATH_INQ;
4900	if (cam_send_ccb(device, ccb) < 0) {
4901		warn("get_cpi: error sending Path Inquiry CCB");
4902		if (arglist & CAM_ARG_VERBOSE)
4903			cam_error_print(device, ccb, CAM_ESF_ALL,
4904					CAM_EPF_ALL, stderr);
4905		retval = 1;
4906		goto get_cpi_bailout;
4907	}
4908	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4909		if (arglist & CAM_ARG_VERBOSE)
4910			cam_error_print(device, ccb, CAM_ESF_ALL,
4911					CAM_EPF_ALL, stderr);
4912		retval = 1;
4913		goto get_cpi_bailout;
4914	}
4915	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4916
4917get_cpi_bailout:
4918	cam_freeccb(ccb);
4919	return(retval);
4920}
4921
4922/*
4923 * Get a get device CCB for the specified device.
4924 */
4925static int
4926get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4927{
4928	union ccb *ccb;
4929	int retval = 0;
4930
4931	ccb = cam_getccb(device);
4932	if (ccb == NULL) {
4933		warnx("get_cgd: couldn't allocate CCB");
4934		return(1);
4935	}
4936	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgd);
4937	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4938	if (cam_send_ccb(device, ccb) < 0) {
4939		warn("get_cgd: error sending Path Inquiry CCB");
4940		if (arglist & CAM_ARG_VERBOSE)
4941			cam_error_print(device, ccb, CAM_ESF_ALL,
4942					CAM_EPF_ALL, stderr);
4943		retval = 1;
4944		goto get_cgd_bailout;
4945	}
4946	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4947		if (arglist & CAM_ARG_VERBOSE)
4948			cam_error_print(device, ccb, CAM_ESF_ALL,
4949					CAM_EPF_ALL, stderr);
4950		retval = 1;
4951		goto get_cgd_bailout;
4952	}
4953	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4954
4955get_cgd_bailout:
4956	cam_freeccb(ccb);
4957	return(retval);
4958}
4959
4960/*
4961 * Returns 1 if the device has the VPD page, 0 if it does not, and -1 on an
4962 * error.
4963 */
4964int
4965dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count,
4966		 int timeout, int verbosemode)
4967{
4968	union ccb *ccb = NULL;
4969	struct scsi_vpd_supported_page_list sup_pages;
4970	int i;
4971	int retval = 0;
4972
4973	ccb = cam_getccb(dev);
4974	if (ccb == NULL) {
4975		warn("Unable to allocate CCB");
4976		retval = -1;
4977		goto bailout;
4978	}
4979
4980	/* cam_getccb cleans up the header, caller has to zero the payload */
4981	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
4982
4983	bzero(&sup_pages, sizeof(sup_pages));
4984
4985	scsi_inquiry(&ccb->csio,
4986		     /*retries*/ retry_count,
4987		     /*cbfcnp*/ NULL,
4988		     /* tag_action */ MSG_SIMPLE_Q_TAG,
4989		     /* inq_buf */ (u_int8_t *)&sup_pages,
4990		     /* inq_len */ sizeof(sup_pages),
4991		     /* evpd */ 1,
4992		     /* page_code */ SVPD_SUPPORTED_PAGE_LIST,
4993		     /* sense_len */ SSD_FULL_SIZE,
4994		     /* timeout */ timeout ? timeout : 5000);
4995
4996	/* Disable freezing the device queue */
4997	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4998
4999	if (retry_count != 0)
5000		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5001
5002	if (cam_send_ccb(dev, ccb) < 0) {
5003		cam_freeccb(ccb);
5004		ccb = NULL;
5005		retval = -1;
5006		goto bailout;
5007	}
5008
5009	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5010		if (verbosemode != 0)
5011			cam_error_print(dev, ccb, CAM_ESF_ALL,
5012					CAM_EPF_ALL, stderr);
5013		retval = -1;
5014		goto bailout;
5015	}
5016
5017	for (i = 0; i < sup_pages.length; i++) {
5018		if (sup_pages.list[i] == page_id) {
5019			retval = 1;
5020			goto bailout;
5021		}
5022	}
5023bailout:
5024	if (ccb != NULL)
5025		cam_freeccb(ccb);
5026
5027	return (retval);
5028}
5029
5030/*
5031 * devtype is filled in with the type of device.
5032 * Returns 0 for success, non-zero for failure.
5033 */
5034int
5035get_device_type(struct cam_device *dev, int retry_count, int timeout,
5036		    int verbosemode, camcontrol_devtype *devtype)
5037{
5038	struct ccb_getdev cgd;
5039	int retval = 0;
5040
5041	retval = get_cgd(dev, &cgd);
5042	if (retval != 0)
5043		goto bailout;
5044
5045	switch (cgd.protocol) {
5046	case PROTO_SCSI:
5047		break;
5048	case PROTO_ATA:
5049	case PROTO_ATAPI:
5050	case PROTO_SATAPM:
5051		*devtype = CC_DT_ATA;
5052		goto bailout;
5053		break; /*NOTREACHED*/
5054	default:
5055		*devtype = CC_DT_UNKNOWN;
5056		goto bailout;
5057		break; /*NOTREACHED*/
5058	}
5059
5060	/*
5061	 * Check for the ATA Information VPD page (0x89).  If this is an
5062	 * ATA device behind a SCSI to ATA translation layer, this VPD page
5063	 * should be present.
5064	 *
5065	 * If that VPD page isn't present, or we get an error back from the
5066	 * INQUIRY command, we'll just treat it as a normal SCSI device.
5067	 */
5068	retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5069				  timeout, verbosemode);
5070	if (retval == 1)
5071		*devtype = CC_DT_ATA_BEHIND_SCSI;
5072	else
5073		*devtype = CC_DT_SCSI;
5074
5075	retval = 0;
5076
5077bailout:
5078	return (retval);
5079}
5080
5081void
5082build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5083    uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5084    uint16_t sector_count, uint64_t lba, uint8_t command, uint8_t *data_ptr,
5085    uint16_t dxfer_len, uint8_t sense_len, uint32_t timeout,
5086    int is48bit, camcontrol_devtype devtype)
5087{
5088	if (devtype == CC_DT_ATA) {
5089		cam_fill_ataio(&ccb->ataio,
5090		    /*retries*/ retry_count,
5091		    /*cbfcnp*/ NULL,
5092		    /*flags*/ flags,
5093		    /*tag_action*/ tag_action,
5094		    /*data_ptr*/ data_ptr,
5095		    /*dxfer_len*/ dxfer_len,
5096		    /*timeout*/ timeout);
5097		if (is48bit || lba > ATA_MAX_28BIT_LBA)
5098			ata_48bit_cmd(&ccb->ataio, command, features, lba,
5099			    sector_count);
5100		else
5101			ata_28bit_cmd(&ccb->ataio, command, features, lba,
5102			    sector_count);
5103	} else {
5104		if (is48bit || lba > ATA_MAX_28BIT_LBA)
5105			protocol |= AP_EXTEND;
5106
5107		scsi_ata_pass_16(&ccb->csio,
5108		    /*retries*/ retry_count,
5109		    /*cbfcnp*/ NULL,
5110		    /*flags*/ flags,
5111		    /*tag_action*/ tag_action,
5112		    /*protocol*/ protocol,
5113		    /*ata_flags*/ ata_flags,
5114		    /*features*/ features,
5115		    /*sector_count*/ sector_count,
5116		    /*lba*/ lba,
5117		    /*command*/ command,
5118		    /*control*/ 0,
5119		    /*data_ptr*/ data_ptr,
5120		    /*dxfer_len*/ dxfer_len,
5121		    /*sense_len*/ sense_len,
5122		    /*timeout*/ timeout);
5123	}
5124}
5125
5126
5127static void
5128cpi_print(struct ccb_pathinq *cpi)
5129{
5130	char adapter_str[1024];
5131	int i;
5132
5133	snprintf(adapter_str, sizeof(adapter_str),
5134		 "%s%d:", cpi->dev_name, cpi->unit_number);
5135
5136	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5137		cpi->version_num);
5138
5139	for (i = 1; i < 0xff; i = i << 1) {
5140		const char *str;
5141
5142		if ((i & cpi->hba_inquiry) == 0)
5143			continue;
5144
5145		fprintf(stdout, "%s supports ", adapter_str);
5146
5147		switch(i) {
5148		case PI_MDP_ABLE:
5149			str = "MDP message";
5150			break;
5151		case PI_WIDE_32:
5152			str = "32 bit wide SCSI";
5153			break;
5154		case PI_WIDE_16:
5155			str = "16 bit wide SCSI";
5156			break;
5157		case PI_SDTR_ABLE:
5158			str = "SDTR message";
5159			break;
5160		case PI_LINKED_CDB:
5161			str = "linked CDBs";
5162			break;
5163		case PI_TAG_ABLE:
5164			str = "tag queue messages";
5165			break;
5166		case PI_SOFT_RST:
5167			str = "soft reset alternative";
5168			break;
5169		case PI_SATAPM:
5170			str = "SATA Port Multiplier";
5171			break;
5172		default:
5173			str = "unknown PI bit set";
5174			break;
5175		}
5176		fprintf(stdout, "%s\n", str);
5177	}
5178
5179	for (i = 1; i < 0xff; i = i << 1) {
5180		const char *str;
5181
5182		if ((i & cpi->hba_misc) == 0)
5183			continue;
5184
5185		fprintf(stdout, "%s ", adapter_str);
5186
5187		switch(i) {
5188		case PIM_SCANHILO:
5189			str = "bus scans from high ID to low ID";
5190			break;
5191		case PIM_NOREMOVE:
5192			str = "removable devices not included in scan";
5193			break;
5194		case PIM_NOINITIATOR:
5195			str = "initiator role not supported";
5196			break;
5197		case PIM_NOBUSRESET:
5198			str = "user has disabled initial BUS RESET or"
5199			      " controller is in target/mixed mode";
5200			break;
5201		case PIM_NO_6_BYTE:
5202			str = "do not send 6-byte commands";
5203			break;
5204		case PIM_SEQSCAN:
5205			str = "scan bus sequentially";
5206			break;
5207		default:
5208			str = "unknown PIM bit set";
5209			break;
5210		}
5211		fprintf(stdout, "%s\n", str);
5212	}
5213
5214	for (i = 1; i < 0xff; i = i << 1) {
5215		const char *str;
5216
5217		if ((i & cpi->target_sprt) == 0)
5218			continue;
5219
5220		fprintf(stdout, "%s supports ", adapter_str);
5221		switch(i) {
5222		case PIT_PROCESSOR:
5223			str = "target mode processor mode";
5224			break;
5225		case PIT_PHASE:
5226			str = "target mode phase cog. mode";
5227			break;
5228		case PIT_DISCONNECT:
5229			str = "disconnects in target mode";
5230			break;
5231		case PIT_TERM_IO:
5232			str = "terminate I/O message in target mode";
5233			break;
5234		case PIT_GRP_6:
5235			str = "group 6 commands in target mode";
5236			break;
5237		case PIT_GRP_7:
5238			str = "group 7 commands in target mode";
5239			break;
5240		default:
5241			str = "unknown PIT bit set";
5242			break;
5243		}
5244
5245		fprintf(stdout, "%s\n", str);
5246	}
5247	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5248		cpi->hba_eng_cnt);
5249	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5250		cpi->max_target);
5251	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5252		cpi->max_lun);
5253	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5254		adapter_str, cpi->hpath_id);
5255	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5256		cpi->initiator_id);
5257	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5258	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5259	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5260	    adapter_str, cpi->hba_vendor);
5261	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5262	    adapter_str, cpi->hba_device);
5263	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5264	    adapter_str, cpi->hba_subvendor);
5265	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5266	    adapter_str, cpi->hba_subdevice);
5267	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5268	fprintf(stdout, "%s base transfer speed: ", adapter_str);
5269	if (cpi->base_transfer_speed > 1000)
5270		fprintf(stdout, "%d.%03dMB/sec\n",
5271			cpi->base_transfer_speed / 1000,
5272			cpi->base_transfer_speed % 1000);
5273	else
5274		fprintf(stdout, "%dKB/sec\n",
5275			(cpi->base_transfer_speed % 1000) * 1000);
5276	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5277	    adapter_str, cpi->maxio);
5278}
5279
5280static int
5281get_print_cts(struct cam_device *device, int user_settings, int quiet,
5282	      struct ccb_trans_settings *cts)
5283{
5284	int retval;
5285	union ccb *ccb;
5286
5287	retval = 0;
5288	ccb = cam_getccb(device);
5289
5290	if (ccb == NULL) {
5291		warnx("get_print_cts: error allocating ccb");
5292		return(1);
5293	}
5294
5295	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5296
5297	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5298
5299	if (user_settings == 0)
5300		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5301	else
5302		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5303
5304	if (cam_send_ccb(device, ccb) < 0) {
5305		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5306		if (arglist & CAM_ARG_VERBOSE)
5307			cam_error_print(device, ccb, CAM_ESF_ALL,
5308					CAM_EPF_ALL, stderr);
5309		retval = 1;
5310		goto get_print_cts_bailout;
5311	}
5312
5313	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5314		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5315		if (arglist & CAM_ARG_VERBOSE)
5316			cam_error_print(device, ccb, CAM_ESF_ALL,
5317					CAM_EPF_ALL, stderr);
5318		retval = 1;
5319		goto get_print_cts_bailout;
5320	}
5321
5322	if (quiet == 0)
5323		cts_print(device, &ccb->cts);
5324
5325	if (cts != NULL)
5326		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5327
5328get_print_cts_bailout:
5329
5330	cam_freeccb(ccb);
5331
5332	return(retval);
5333}
5334
5335static int
5336ratecontrol(struct cam_device *device, int retry_count, int timeout,
5337	    int argc, char **argv, char *combinedopt)
5338{
5339	int c;
5340	union ccb *ccb;
5341	int user_settings = 0;
5342	int retval = 0;
5343	int disc_enable = -1, tag_enable = -1;
5344	int mode = -1;
5345	int offset = -1;
5346	double syncrate = -1;
5347	int bus_width = -1;
5348	int quiet = 0;
5349	int change_settings = 0, send_tur = 0;
5350	struct ccb_pathinq cpi;
5351
5352	ccb = cam_getccb(device);
5353	if (ccb == NULL) {
5354		warnx("ratecontrol: error allocating ccb");
5355		return(1);
5356	}
5357	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5358		switch(c){
5359		case 'a':
5360			send_tur = 1;
5361			break;
5362		case 'c':
5363			user_settings = 0;
5364			break;
5365		case 'D':
5366			if (strncasecmp(optarg, "enable", 6) == 0)
5367				disc_enable = 1;
5368			else if (strncasecmp(optarg, "disable", 7) == 0)
5369				disc_enable = 0;
5370			else {
5371				warnx("-D argument \"%s\" is unknown", optarg);
5372				retval = 1;
5373				goto ratecontrol_bailout;
5374			}
5375			change_settings = 1;
5376			break;
5377		case 'M':
5378			mode = ata_string2mode(optarg);
5379			if (mode < 0) {
5380				warnx("unknown mode '%s'", optarg);
5381				retval = 1;
5382				goto ratecontrol_bailout;
5383			}
5384			change_settings = 1;
5385			break;
5386		case 'O':
5387			offset = strtol(optarg, NULL, 0);
5388			if (offset < 0) {
5389				warnx("offset value %d is < 0", offset);
5390				retval = 1;
5391				goto ratecontrol_bailout;
5392			}
5393			change_settings = 1;
5394			break;
5395		case 'q':
5396			quiet++;
5397			break;
5398		case 'R':
5399			syncrate = atof(optarg);
5400			if (syncrate < 0) {
5401				warnx("sync rate %f is < 0", syncrate);
5402				retval = 1;
5403				goto ratecontrol_bailout;
5404			}
5405			change_settings = 1;
5406			break;
5407		case 'T':
5408			if (strncasecmp(optarg, "enable", 6) == 0)
5409				tag_enable = 1;
5410			else if (strncasecmp(optarg, "disable", 7) == 0)
5411				tag_enable = 0;
5412			else {
5413				warnx("-T argument \"%s\" is unknown", optarg);
5414				retval = 1;
5415				goto ratecontrol_bailout;
5416			}
5417			change_settings = 1;
5418			break;
5419		case 'U':
5420			user_settings = 1;
5421			break;
5422		case 'W':
5423			bus_width = strtol(optarg, NULL, 0);
5424			if (bus_width < 0) {
5425				warnx("bus width %d is < 0", bus_width);
5426				retval = 1;
5427				goto ratecontrol_bailout;
5428			}
5429			change_settings = 1;
5430			break;
5431		default:
5432			break;
5433		}
5434	}
5435	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
5436	/*
5437	 * Grab path inquiry information, so we can determine whether
5438	 * or not the initiator is capable of the things that the user
5439	 * requests.
5440	 */
5441	ccb->ccb_h.func_code = XPT_PATH_INQ;
5442	if (cam_send_ccb(device, ccb) < 0) {
5443		perror("error sending XPT_PATH_INQ CCB");
5444		if (arglist & CAM_ARG_VERBOSE) {
5445			cam_error_print(device, ccb, CAM_ESF_ALL,
5446					CAM_EPF_ALL, stderr);
5447		}
5448		retval = 1;
5449		goto ratecontrol_bailout;
5450	}
5451	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5452		warnx("XPT_PATH_INQ CCB failed");
5453		if (arglist & CAM_ARG_VERBOSE) {
5454			cam_error_print(device, ccb, CAM_ESF_ALL,
5455					CAM_EPF_ALL, stderr);
5456		}
5457		retval = 1;
5458		goto ratecontrol_bailout;
5459	}
5460	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5461	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5462	if (quiet == 0) {
5463		fprintf(stdout, "%s parameters:\n",
5464		    user_settings ? "User" : "Current");
5465	}
5466	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5467	if (retval != 0)
5468		goto ratecontrol_bailout;
5469
5470	if (arglist & CAM_ARG_VERBOSE)
5471		cpi_print(&cpi);
5472
5473	if (change_settings) {
5474		int didsettings = 0;
5475		struct ccb_trans_settings_spi *spi = NULL;
5476		struct ccb_trans_settings_pata *pata = NULL;
5477		struct ccb_trans_settings_sata *sata = NULL;
5478		struct ccb_trans_settings_ata *ata = NULL;
5479		struct ccb_trans_settings_scsi *scsi = NULL;
5480
5481		if (ccb->cts.transport == XPORT_SPI)
5482			spi = &ccb->cts.xport_specific.spi;
5483		if (ccb->cts.transport == XPORT_ATA)
5484			pata = &ccb->cts.xport_specific.ata;
5485		if (ccb->cts.transport == XPORT_SATA)
5486			sata = &ccb->cts.xport_specific.sata;
5487		if (ccb->cts.protocol == PROTO_ATA)
5488			ata = &ccb->cts.proto_specific.ata;
5489		if (ccb->cts.protocol == PROTO_SCSI)
5490			scsi = &ccb->cts.proto_specific.scsi;
5491		ccb->cts.xport_specific.valid = 0;
5492		ccb->cts.proto_specific.valid = 0;
5493		if (spi && disc_enable != -1) {
5494			spi->valid |= CTS_SPI_VALID_DISC;
5495			if (disc_enable == 0)
5496				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5497			else
5498				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5499			didsettings++;
5500		}
5501		if (tag_enable != -1) {
5502			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5503				warnx("HBA does not support tagged queueing, "
5504				      "so you cannot modify tag settings");
5505				retval = 1;
5506				goto ratecontrol_bailout;
5507			}
5508			if (ata) {
5509				ata->valid |= CTS_SCSI_VALID_TQ;
5510				if (tag_enable == 0)
5511					ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5512				else
5513					ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5514				didsettings++;
5515			} else if (scsi) {
5516				scsi->valid |= CTS_SCSI_VALID_TQ;
5517				if (tag_enable == 0)
5518					scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5519				else
5520					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5521				didsettings++;
5522			}
5523		}
5524		if (spi && offset != -1) {
5525			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5526				warnx("HBA is not capable of changing offset");
5527				retval = 1;
5528				goto ratecontrol_bailout;
5529			}
5530			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5531			spi->sync_offset = offset;
5532			didsettings++;
5533		}
5534		if (spi && syncrate != -1) {
5535			int prelim_sync_period;
5536
5537			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5538				warnx("HBA is not capable of changing "
5539				      "transfer rates");
5540				retval = 1;
5541				goto ratecontrol_bailout;
5542			}
5543			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5544			/*
5545			 * The sync rate the user gives us is in MHz.
5546			 * We need to translate it into KHz for this
5547			 * calculation.
5548			 */
5549			syncrate *= 1000;
5550			/*
5551			 * Next, we calculate a "preliminary" sync period
5552			 * in tenths of a nanosecond.
5553			 */
5554			if (syncrate == 0)
5555				prelim_sync_period = 0;
5556			else
5557				prelim_sync_period = 10000000 / syncrate;
5558			spi->sync_period =
5559				scsi_calc_syncparam(prelim_sync_period);
5560			didsettings++;
5561		}
5562		if (sata && syncrate != -1) {
5563			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5564				warnx("HBA is not capable of changing "
5565				      "transfer rates");
5566				retval = 1;
5567				goto ratecontrol_bailout;
5568			}
5569			if  (!user_settings) {
5570				warnx("You can modify only user rate "
5571				    "settings for SATA");
5572				retval = 1;
5573				goto ratecontrol_bailout;
5574			}
5575			sata->revision = ata_speed2revision(syncrate * 100);
5576			if (sata->revision < 0) {
5577				warnx("Invalid rate %f", syncrate);
5578				retval = 1;
5579				goto ratecontrol_bailout;
5580			}
5581			sata->valid |= CTS_SATA_VALID_REVISION;
5582			didsettings++;
5583		}
5584		if ((pata || sata) && mode != -1) {
5585			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5586				warnx("HBA is not capable of changing "
5587				      "transfer rates");
5588				retval = 1;
5589				goto ratecontrol_bailout;
5590			}
5591			if  (!user_settings) {
5592				warnx("You can modify only user mode "
5593				    "settings for ATA/SATA");
5594				retval = 1;
5595				goto ratecontrol_bailout;
5596			}
5597			if (pata) {
5598				pata->mode = mode;
5599				pata->valid |= CTS_ATA_VALID_MODE;
5600			} else {
5601				sata->mode = mode;
5602				sata->valid |= CTS_SATA_VALID_MODE;
5603			}
5604			didsettings++;
5605		}
5606		/*
5607		 * The bus_width argument goes like this:
5608		 * 0 == 8 bit
5609		 * 1 == 16 bit
5610		 * 2 == 32 bit
5611		 * Therefore, if you shift the number of bits given on the
5612		 * command line right by 4, you should get the correct
5613		 * number.
5614		 */
5615		if (spi && bus_width != -1) {
5616			/*
5617			 * We might as well validate things here with a
5618			 * decipherable error message, rather than what
5619			 * will probably be an indecipherable error message
5620			 * by the time it gets back to us.
5621			 */
5622			if ((bus_width == 16)
5623			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5624				warnx("HBA does not support 16 bit bus width");
5625				retval = 1;
5626				goto ratecontrol_bailout;
5627			} else if ((bus_width == 32)
5628				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5629				warnx("HBA does not support 32 bit bus width");
5630				retval = 1;
5631				goto ratecontrol_bailout;
5632			} else if ((bus_width != 8)
5633				&& (bus_width != 16)
5634				&& (bus_width != 32)) {
5635				warnx("Invalid bus width %d", bus_width);
5636				retval = 1;
5637				goto ratecontrol_bailout;
5638			}
5639			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5640			spi->bus_width = bus_width >> 4;
5641			didsettings++;
5642		}
5643		if  (didsettings == 0) {
5644			goto ratecontrol_bailout;
5645		}
5646		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5647		if (cam_send_ccb(device, ccb) < 0) {
5648			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5649			if (arglist & CAM_ARG_VERBOSE) {
5650				cam_error_print(device, ccb, CAM_ESF_ALL,
5651						CAM_EPF_ALL, stderr);
5652			}
5653			retval = 1;
5654			goto ratecontrol_bailout;
5655		}
5656		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5657			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5658			if (arglist & CAM_ARG_VERBOSE) {
5659				cam_error_print(device, ccb, CAM_ESF_ALL,
5660						CAM_EPF_ALL, stderr);
5661			}
5662			retval = 1;
5663			goto ratecontrol_bailout;
5664		}
5665	}
5666	if (send_tur) {
5667		retval = testunitready(device, retry_count, timeout,
5668				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5669		/*
5670		 * If the TUR didn't succeed, just bail.
5671		 */
5672		if (retval != 0) {
5673			if (quiet == 0)
5674				fprintf(stderr, "Test Unit Ready failed\n");
5675			goto ratecontrol_bailout;
5676		}
5677	}
5678	if ((change_settings || send_tur) && !quiet &&
5679	    (ccb->cts.transport == XPORT_ATA ||
5680	     ccb->cts.transport == XPORT_SATA || send_tur)) {
5681		fprintf(stdout, "New parameters:\n");
5682		retval = get_print_cts(device, user_settings, 0, NULL);
5683	}
5684
5685ratecontrol_bailout:
5686	cam_freeccb(ccb);
5687	return(retval);
5688}
5689
5690static int
5691scsiformat(struct cam_device *device, int argc, char **argv,
5692	   char *combinedopt, int retry_count, int timeout)
5693{
5694	union ccb *ccb;
5695	int c;
5696	int ycount = 0, quiet = 0;
5697	int error = 0, retval = 0;
5698	int use_timeout = 10800 * 1000;
5699	int immediate = 1;
5700	struct format_defect_list_header fh;
5701	u_int8_t *data_ptr = NULL;
5702	u_int32_t dxfer_len = 0;
5703	u_int8_t byte2 = 0;
5704	int num_warnings = 0;
5705	int reportonly = 0;
5706
5707	ccb = cam_getccb(device);
5708
5709	if (ccb == NULL) {
5710		warnx("scsiformat: error allocating ccb");
5711		return(1);
5712	}
5713
5714	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5715
5716	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5717		switch(c) {
5718		case 'q':
5719			quiet++;
5720			break;
5721		case 'r':
5722			reportonly = 1;
5723			break;
5724		case 'w':
5725			immediate = 0;
5726			break;
5727		case 'y':
5728			ycount++;
5729			break;
5730		}
5731	}
5732
5733	if (reportonly)
5734		goto doreport;
5735
5736	if (quiet == 0) {
5737		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5738			"following device:\n");
5739
5740		error = scsidoinquiry(device, argc, argv, combinedopt,
5741				      retry_count, timeout);
5742
5743		if (error != 0) {
5744			warnx("scsiformat: error sending inquiry");
5745			goto scsiformat_bailout;
5746		}
5747	}
5748
5749	if (ycount == 0) {
5750		if (!get_confirmation()) {
5751			error = 1;
5752			goto scsiformat_bailout;
5753		}
5754	}
5755
5756	if (timeout != 0)
5757		use_timeout = timeout;
5758
5759	if (quiet == 0) {
5760		fprintf(stdout, "Current format timeout is %d seconds\n",
5761			use_timeout / 1000);
5762	}
5763
5764	/*
5765	 * If the user hasn't disabled questions and didn't specify a
5766	 * timeout on the command line, ask them if they want the current
5767	 * timeout.
5768	 */
5769	if ((ycount == 0)
5770	 && (timeout == 0)) {
5771		char str[1024];
5772		int new_timeout = 0;
5773
5774		fprintf(stdout, "Enter new timeout in seconds or press\n"
5775			"return to keep the current timeout [%d] ",
5776			use_timeout / 1000);
5777
5778		if (fgets(str, sizeof(str), stdin) != NULL) {
5779			if (str[0] != '\0')
5780				new_timeout = atoi(str);
5781		}
5782
5783		if (new_timeout != 0) {
5784			use_timeout = new_timeout * 1000;
5785			fprintf(stdout, "Using new timeout value %d\n",
5786				use_timeout / 1000);
5787		}
5788	}
5789
5790	/*
5791	 * Keep this outside the if block below to silence any unused
5792	 * variable warnings.
5793	 */
5794	bzero(&fh, sizeof(fh));
5795
5796	/*
5797	 * If we're in immediate mode, we've got to include the format
5798	 * header
5799	 */
5800	if (immediate != 0) {
5801		fh.byte2 = FU_DLH_IMMED;
5802		data_ptr = (u_int8_t *)&fh;
5803		dxfer_len = sizeof(fh);
5804		byte2 = FU_FMT_DATA;
5805	} else if (quiet == 0) {
5806		fprintf(stdout, "Formatting...");
5807		fflush(stdout);
5808	}
5809
5810	scsi_format_unit(&ccb->csio,
5811			 /* retries */ retry_count,
5812			 /* cbfcnp */ NULL,
5813			 /* tag_action */ MSG_SIMPLE_Q_TAG,
5814			 /* byte2 */ byte2,
5815			 /* ileave */ 0,
5816			 /* data_ptr */ data_ptr,
5817			 /* dxfer_len */ dxfer_len,
5818			 /* sense_len */ SSD_FULL_SIZE,
5819			 /* timeout */ use_timeout);
5820
5821	/* Disable freezing the device queue */
5822	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5823
5824	if (arglist & CAM_ARG_ERR_RECOVER)
5825		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5826
5827	if (((retval = cam_send_ccb(device, ccb)) < 0)
5828	 || ((immediate == 0)
5829	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5830		const char errstr[] = "error sending format command";
5831
5832		if (retval < 0)
5833			warn(errstr);
5834		else
5835			warnx(errstr);
5836
5837		if (arglist & CAM_ARG_VERBOSE) {
5838			cam_error_print(device, ccb, CAM_ESF_ALL,
5839					CAM_EPF_ALL, stderr);
5840		}
5841		error = 1;
5842		goto scsiformat_bailout;
5843	}
5844
5845	/*
5846	 * If we ran in non-immediate mode, we already checked for errors
5847	 * above and printed out any necessary information.  If we're in
5848	 * immediate mode, we need to loop through and get status
5849	 * information periodically.
5850	 */
5851	if (immediate == 0) {
5852		if (quiet == 0) {
5853			fprintf(stdout, "Format Complete\n");
5854		}
5855		goto scsiformat_bailout;
5856	}
5857
5858doreport:
5859	do {
5860		cam_status status;
5861
5862		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5863
5864		/*
5865		 * There's really no need to do error recovery or
5866		 * retries here, since we're just going to sit in a
5867		 * loop and wait for the device to finish formatting.
5868		 */
5869		scsi_test_unit_ready(&ccb->csio,
5870				     /* retries */ 0,
5871				     /* cbfcnp */ NULL,
5872				     /* tag_action */ MSG_SIMPLE_Q_TAG,
5873				     /* sense_len */ SSD_FULL_SIZE,
5874				     /* timeout */ 5000);
5875
5876		/* Disable freezing the device queue */
5877		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5878
5879		retval = cam_send_ccb(device, ccb);
5880
5881		/*
5882		 * If we get an error from the ioctl, bail out.  SCSI
5883		 * errors are expected.
5884		 */
5885		if (retval < 0) {
5886			warn("error sending CAMIOCOMMAND ioctl");
5887			if (arglist & CAM_ARG_VERBOSE) {
5888				cam_error_print(device, ccb, CAM_ESF_ALL,
5889						CAM_EPF_ALL, stderr);
5890			}
5891			error = 1;
5892			goto scsiformat_bailout;
5893		}
5894
5895		status = ccb->ccb_h.status & CAM_STATUS_MASK;
5896
5897		if ((status != CAM_REQ_CMP)
5898		 && (status == CAM_SCSI_STATUS_ERROR)
5899		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5900			struct scsi_sense_data *sense;
5901			int error_code, sense_key, asc, ascq;
5902
5903			sense = &ccb->csio.sense_data;
5904			scsi_extract_sense_len(sense, ccb->csio.sense_len -
5905			    ccb->csio.sense_resid, &error_code, &sense_key,
5906			    &asc, &ascq, /*show_errors*/ 1);
5907
5908			/*
5909			 * According to the SCSI-2 and SCSI-3 specs, a
5910			 * drive that is in the middle of a format should
5911			 * return NOT READY with an ASC of "logical unit
5912			 * not ready, format in progress".  The sense key
5913			 * specific bytes will then be a progress indicator.
5914			 */
5915			if ((sense_key == SSD_KEY_NOT_READY)
5916			 && (asc == 0x04) && (ascq == 0x04)) {
5917				uint8_t sks[3];
5918
5919				if ((scsi_get_sks(sense, ccb->csio.sense_len -
5920				     ccb->csio.sense_resid, sks) == 0)
5921				 && (quiet == 0)) {
5922					int val;
5923					u_int64_t percentage;
5924
5925					val = scsi_2btoul(&sks[1]);
5926					percentage = 10000 * val;
5927
5928					fprintf(stdout,
5929						"\rFormatting:  %ju.%02u %% "
5930						"(%d/%d) done",
5931						(uintmax_t)(percentage /
5932						(0x10000 * 100)),
5933						(unsigned)((percentage /
5934						0x10000) % 100),
5935						val, 0x10000);
5936					fflush(stdout);
5937				} else if ((quiet == 0)
5938					&& (++num_warnings <= 1)) {
5939					warnx("Unexpected SCSI Sense Key "
5940					      "Specific value returned "
5941					      "during format:");
5942					scsi_sense_print(device, &ccb->csio,
5943							 stderr);
5944					warnx("Unable to print status "
5945					      "information, but format will "
5946					      "proceed.");
5947					warnx("will exit when format is "
5948					      "complete");
5949				}
5950				sleep(1);
5951			} else {
5952				warnx("Unexpected SCSI error during format");
5953				cam_error_print(device, ccb, CAM_ESF_ALL,
5954						CAM_EPF_ALL, stderr);
5955				error = 1;
5956				goto scsiformat_bailout;
5957			}
5958
5959		} else if (status != CAM_REQ_CMP) {
5960			warnx("Unexpected CAM status %#x", status);
5961			if (arglist & CAM_ARG_VERBOSE)
5962				cam_error_print(device, ccb, CAM_ESF_ALL,
5963						CAM_EPF_ALL, stderr);
5964			error = 1;
5965			goto scsiformat_bailout;
5966		}
5967
5968	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5969
5970	if (quiet == 0)
5971		fprintf(stdout, "\nFormat Complete\n");
5972
5973scsiformat_bailout:
5974
5975	cam_freeccb(ccb);
5976
5977	return(error);
5978}
5979
5980static int
5981scsisanitize(struct cam_device *device, int argc, char **argv,
5982	     char *combinedopt, int retry_count, int timeout)
5983{
5984	union ccb *ccb;
5985	u_int8_t action = 0;
5986	int c;
5987	int ycount = 0, quiet = 0;
5988	int error = 0, retval = 0;
5989	int use_timeout = 10800 * 1000;
5990	int immediate = 1;
5991	int invert = 0;
5992	int passes = 0;
5993	int ause = 0;
5994	int fd = -1;
5995	const char *pattern = NULL;
5996	u_int8_t *data_ptr = NULL;
5997	u_int32_t dxfer_len = 0;
5998	u_int8_t byte2 = 0;
5999	int num_warnings = 0;
6000	int reportonly = 0;
6001
6002	ccb = cam_getccb(device);
6003
6004	if (ccb == NULL) {
6005		warnx("scsisanitize: error allocating ccb");
6006		return(1);
6007	}
6008
6009	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6010
6011	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6012		switch(c) {
6013		case 'a':
6014			if (strcasecmp(optarg, "overwrite") == 0)
6015				action = SSZ_SERVICE_ACTION_OVERWRITE;
6016			else if (strcasecmp(optarg, "block") == 0)
6017				action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6018			else if (strcasecmp(optarg, "crypto") == 0)
6019				action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6020			else if (strcasecmp(optarg, "exitfailure") == 0)
6021				action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6022			else {
6023				warnx("invalid service operation \"%s\"",
6024				      optarg);
6025				error = 1;
6026				goto scsisanitize_bailout;
6027			}
6028			break;
6029		case 'c':
6030			passes = strtol(optarg, NULL, 0);
6031			if (passes < 1 || passes > 31) {
6032				warnx("invalid passes value %d", passes);
6033				error = 1;
6034				goto scsisanitize_bailout;
6035			}
6036			break;
6037		case 'I':
6038			invert = 1;
6039			break;
6040		case 'P':
6041			pattern = optarg;
6042			break;
6043		case 'q':
6044			quiet++;
6045			break;
6046		case 'U':
6047			ause = 1;
6048			break;
6049		case 'r':
6050			reportonly = 1;
6051			break;
6052		case 'w':
6053			immediate = 0;
6054			break;
6055		case 'y':
6056			ycount++;
6057			break;
6058		}
6059	}
6060
6061	if (reportonly)
6062		goto doreport;
6063
6064	if (action == 0) {
6065		warnx("an action is required");
6066		error = 1;
6067		goto scsisanitize_bailout;
6068	} else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6069		struct scsi_sanitize_parameter_list *pl;
6070		struct stat sb;
6071		ssize_t sz, amt;
6072
6073		if (pattern == NULL) {
6074			warnx("overwrite action requires -P argument");
6075			error = 1;
6076			goto scsisanitize_bailout;
6077		}
6078		fd = open(pattern, O_RDONLY);
6079		if (fd < 0) {
6080			warn("cannot open pattern file %s", pattern);
6081			error = 1;
6082			goto scsisanitize_bailout;
6083		}
6084		if (fstat(fd, &sb) < 0) {
6085			warn("cannot stat pattern file %s", pattern);
6086			error = 1;
6087			goto scsisanitize_bailout;
6088		}
6089		sz = sb.st_size;
6090		if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6091			warnx("pattern file size exceeds maximum value %d",
6092			      SSZPL_MAX_PATTERN_LENGTH);
6093			error = 1;
6094			goto scsisanitize_bailout;
6095		}
6096		dxfer_len = sizeof(*pl) + sz;
6097		data_ptr = calloc(1, dxfer_len);
6098		if (data_ptr == NULL) {
6099			warnx("cannot allocate parameter list buffer");
6100			error = 1;
6101			goto scsisanitize_bailout;
6102		}
6103
6104		amt = read(fd, data_ptr + sizeof(*pl), sz);
6105		if (amt < 0) {
6106			warn("cannot read pattern file");
6107			error = 1;
6108			goto scsisanitize_bailout;
6109		} else if (amt != sz) {
6110			warnx("short pattern file read");
6111			error = 1;
6112			goto scsisanitize_bailout;
6113		}
6114
6115		pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6116		if (passes == 0)
6117			pl->byte1 = 1;
6118		else
6119			pl->byte1 = passes;
6120		if (invert != 0)
6121			pl->byte1 |= SSZPL_INVERT;
6122		scsi_ulto2b(sz, pl->length);
6123	} else {
6124		const char *arg;
6125
6126		if (passes != 0)
6127			arg = "-c";
6128		else if (invert != 0)
6129			arg = "-I";
6130		else if (pattern != NULL)
6131			arg = "-P";
6132		else
6133			arg = NULL;
6134		if (arg != NULL) {
6135			warnx("%s argument only valid with overwrite "
6136			      "operation", arg);
6137			error = 1;
6138			goto scsisanitize_bailout;
6139		}
6140	}
6141
6142	if (quiet == 0) {
6143		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6144			"following device:\n");
6145
6146		error = scsidoinquiry(device, argc, argv, combinedopt,
6147				      retry_count, timeout);
6148
6149		if (error != 0) {
6150			warnx("scsisanitize: error sending inquiry");
6151			goto scsisanitize_bailout;
6152		}
6153	}
6154
6155	if (ycount == 0) {
6156		if (!get_confirmation()) {
6157			error = 1;
6158			goto scsisanitize_bailout;
6159		}
6160	}
6161
6162	if (timeout != 0)
6163		use_timeout = timeout;
6164
6165	if (quiet == 0) {
6166		fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6167			use_timeout / 1000);
6168	}
6169
6170	/*
6171	 * If the user hasn't disabled questions and didn't specify a
6172	 * timeout on the command line, ask them if they want the current
6173	 * timeout.
6174	 */
6175	if ((ycount == 0)
6176	 && (timeout == 0)) {
6177		char str[1024];
6178		int new_timeout = 0;
6179
6180		fprintf(stdout, "Enter new timeout in seconds or press\n"
6181			"return to keep the current timeout [%d] ",
6182			use_timeout / 1000);
6183
6184		if (fgets(str, sizeof(str), stdin) != NULL) {
6185			if (str[0] != '\0')
6186				new_timeout = atoi(str);
6187		}
6188
6189		if (new_timeout != 0) {
6190			use_timeout = new_timeout * 1000;
6191			fprintf(stdout, "Using new timeout value %d\n",
6192				use_timeout / 1000);
6193		}
6194	}
6195
6196	byte2 = action;
6197	if (ause != 0)
6198		byte2 |= SSZ_UNRESTRICTED_EXIT;
6199	if (immediate != 0)
6200		byte2 |= SSZ_IMMED;
6201
6202	scsi_sanitize(&ccb->csio,
6203		      /* retries */ retry_count,
6204		      /* cbfcnp */ NULL,
6205		      /* tag_action */ MSG_SIMPLE_Q_TAG,
6206		      /* byte2 */ byte2,
6207		      /* control */ 0,
6208		      /* data_ptr */ data_ptr,
6209		      /* dxfer_len */ dxfer_len,
6210		      /* sense_len */ SSD_FULL_SIZE,
6211		      /* timeout */ use_timeout);
6212
6213	/* Disable freezing the device queue */
6214	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6215
6216	if (arglist & CAM_ARG_ERR_RECOVER)
6217		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6218
6219	if (cam_send_ccb(device, ccb) < 0) {
6220		warn("error sending sanitize command");
6221		error = 1;
6222		goto scsisanitize_bailout;
6223	}
6224
6225	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6226		struct scsi_sense_data *sense;
6227		int error_code, sense_key, asc, ascq;
6228
6229		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6230		    CAM_SCSI_STATUS_ERROR) {
6231			sense = &ccb->csio.sense_data;
6232			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6233			    ccb->csio.sense_resid, &error_code, &sense_key,
6234			    &asc, &ascq, /*show_errors*/ 1);
6235
6236			if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6237			    asc == 0x20 && ascq == 0x00)
6238				warnx("sanitize is not supported by "
6239				      "this device");
6240			else
6241				warnx("error sanitizing this device");
6242		} else
6243			warnx("error sanitizing this device");
6244
6245		if (arglist & CAM_ARG_VERBOSE) {
6246			cam_error_print(device, ccb, CAM_ESF_ALL,
6247					CAM_EPF_ALL, stderr);
6248		}
6249		error = 1;
6250		goto scsisanitize_bailout;
6251	}
6252
6253	/*
6254	 * If we ran in non-immediate mode, we already checked for errors
6255	 * above and printed out any necessary information.  If we're in
6256	 * immediate mode, we need to loop through and get status
6257	 * information periodically.
6258	 */
6259	if (immediate == 0) {
6260		if (quiet == 0) {
6261			fprintf(stdout, "Sanitize Complete\n");
6262		}
6263		goto scsisanitize_bailout;
6264	}
6265
6266doreport:
6267	do {
6268		cam_status status;
6269
6270		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6271
6272		/*
6273		 * There's really no need to do error recovery or
6274		 * retries here, since we're just going to sit in a
6275		 * loop and wait for the device to finish sanitizing.
6276		 */
6277		scsi_test_unit_ready(&ccb->csio,
6278				     /* retries */ 0,
6279				     /* cbfcnp */ NULL,
6280				     /* tag_action */ MSG_SIMPLE_Q_TAG,
6281				     /* sense_len */ SSD_FULL_SIZE,
6282				     /* timeout */ 5000);
6283
6284		/* Disable freezing the device queue */
6285		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6286
6287		retval = cam_send_ccb(device, ccb);
6288
6289		/*
6290		 * If we get an error from the ioctl, bail out.  SCSI
6291		 * errors are expected.
6292		 */
6293		if (retval < 0) {
6294			warn("error sending CAMIOCOMMAND ioctl");
6295			if (arglist & CAM_ARG_VERBOSE) {
6296				cam_error_print(device, ccb, CAM_ESF_ALL,
6297						CAM_EPF_ALL, stderr);
6298			}
6299			error = 1;
6300			goto scsisanitize_bailout;
6301		}
6302
6303		status = ccb->ccb_h.status & CAM_STATUS_MASK;
6304
6305		if ((status != CAM_REQ_CMP)
6306		 && (status == CAM_SCSI_STATUS_ERROR)
6307		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6308			struct scsi_sense_data *sense;
6309			int error_code, sense_key, asc, ascq;
6310
6311			sense = &ccb->csio.sense_data;
6312			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6313			    ccb->csio.sense_resid, &error_code, &sense_key,
6314			    &asc, &ascq, /*show_errors*/ 1);
6315
6316			/*
6317			 * According to the SCSI-3 spec, a drive that is in the
6318			 * middle of a sanitize should return NOT READY with an
6319			 * ASC of "logical unit not ready, sanitize in
6320			 * progress". The sense key specific bytes will then
6321			 * be a progress indicator.
6322			 */
6323			if ((sense_key == SSD_KEY_NOT_READY)
6324			 && (asc == 0x04) && (ascq == 0x1b)) {
6325				uint8_t sks[3];
6326
6327				if ((scsi_get_sks(sense, ccb->csio.sense_len -
6328				     ccb->csio.sense_resid, sks) == 0)
6329				 && (quiet == 0)) {
6330					int val;
6331					u_int64_t percentage;
6332
6333					val = scsi_2btoul(&sks[1]);
6334					percentage = 10000 * val;
6335
6336					fprintf(stdout,
6337						"\rSanitizing:  %ju.%02u %% "
6338						"(%d/%d) done",
6339						(uintmax_t)(percentage /
6340						(0x10000 * 100)),
6341						(unsigned)((percentage /
6342						0x10000) % 100),
6343						val, 0x10000);
6344					fflush(stdout);
6345				} else if ((quiet == 0)
6346					&& (++num_warnings <= 1)) {
6347					warnx("Unexpected SCSI Sense Key "
6348					      "Specific value returned "
6349					      "during sanitize:");
6350					scsi_sense_print(device, &ccb->csio,
6351							 stderr);
6352					warnx("Unable to print status "
6353					      "information, but sanitze will "
6354					      "proceed.");
6355					warnx("will exit when sanitize is "
6356					      "complete");
6357				}
6358				sleep(1);
6359			} else {
6360				warnx("Unexpected SCSI error during sanitize");
6361				cam_error_print(device, ccb, CAM_ESF_ALL,
6362						CAM_EPF_ALL, stderr);
6363				error = 1;
6364				goto scsisanitize_bailout;
6365			}
6366
6367		} else if (status != CAM_REQ_CMP) {
6368			warnx("Unexpected CAM status %#x", status);
6369			if (arglist & CAM_ARG_VERBOSE)
6370				cam_error_print(device, ccb, CAM_ESF_ALL,
6371						CAM_EPF_ALL, stderr);
6372			error = 1;
6373			goto scsisanitize_bailout;
6374		}
6375	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6376
6377	if (quiet == 0)
6378		fprintf(stdout, "\nSanitize Complete\n");
6379
6380scsisanitize_bailout:
6381	if (fd >= 0)
6382		close(fd);
6383	if (data_ptr != NULL)
6384		free(data_ptr);
6385	cam_freeccb(ccb);
6386
6387	return(error);
6388}
6389
6390static int
6391scsireportluns(struct cam_device *device, int argc, char **argv,
6392	       char *combinedopt, int retry_count, int timeout)
6393{
6394	union ccb *ccb;
6395	int c, countonly, lunsonly;
6396	struct scsi_report_luns_data *lundata;
6397	int alloc_len;
6398	uint8_t report_type;
6399	uint32_t list_len, i, j;
6400	int retval;
6401
6402	retval = 0;
6403	lundata = NULL;
6404	report_type = RPL_REPORT_DEFAULT;
6405	ccb = cam_getccb(device);
6406
6407	if (ccb == NULL) {
6408		warnx("%s: error allocating ccb", __func__);
6409		return (1);
6410	}
6411
6412	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6413
6414	countonly = 0;
6415	lunsonly = 0;
6416
6417	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6418		switch (c) {
6419		case 'c':
6420			countonly++;
6421			break;
6422		case 'l':
6423			lunsonly++;
6424			break;
6425		case 'r':
6426			if (strcasecmp(optarg, "default") == 0)
6427				report_type = RPL_REPORT_DEFAULT;
6428			else if (strcasecmp(optarg, "wellknown") == 0)
6429				report_type = RPL_REPORT_WELLKNOWN;
6430			else if (strcasecmp(optarg, "all") == 0)
6431				report_type = RPL_REPORT_ALL;
6432			else {
6433				warnx("%s: invalid report type \"%s\"",
6434				      __func__, optarg);
6435				retval = 1;
6436				goto bailout;
6437			}
6438			break;
6439		default:
6440			break;
6441		}
6442	}
6443
6444	if ((countonly != 0)
6445	 && (lunsonly != 0)) {
6446		warnx("%s: you can only specify one of -c or -l", __func__);
6447		retval = 1;
6448		goto bailout;
6449	}
6450	/*
6451	 * According to SPC-4, the allocation length must be at least 16
6452	 * bytes -- enough for the header and one LUN.
6453	 */
6454	alloc_len = sizeof(*lundata) + 8;
6455
6456retry:
6457
6458	lundata = malloc(alloc_len);
6459
6460	if (lundata == NULL) {
6461		warn("%s: error mallocing %d bytes", __func__, alloc_len);
6462		retval = 1;
6463		goto bailout;
6464	}
6465
6466	scsi_report_luns(&ccb->csio,
6467			 /*retries*/ retry_count,
6468			 /*cbfcnp*/ NULL,
6469			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6470			 /*select_report*/ report_type,
6471			 /*rpl_buf*/ lundata,
6472			 /*alloc_len*/ alloc_len,
6473			 /*sense_len*/ SSD_FULL_SIZE,
6474			 /*timeout*/ timeout ? timeout : 5000);
6475
6476	/* Disable freezing the device queue */
6477	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6478
6479	if (arglist & CAM_ARG_ERR_RECOVER)
6480		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6481
6482	if (cam_send_ccb(device, ccb) < 0) {
6483		warn("error sending REPORT LUNS command");
6484
6485		if (arglist & CAM_ARG_VERBOSE)
6486			cam_error_print(device, ccb, CAM_ESF_ALL,
6487					CAM_EPF_ALL, stderr);
6488
6489		retval = 1;
6490		goto bailout;
6491	}
6492
6493	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6494		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6495		retval = 1;
6496		goto bailout;
6497	}
6498
6499
6500	list_len = scsi_4btoul(lundata->length);
6501
6502	/*
6503	 * If we need to list the LUNs, and our allocation
6504	 * length was too short, reallocate and retry.
6505	 */
6506	if ((countonly == 0)
6507	 && (list_len > (alloc_len - sizeof(*lundata)))) {
6508		alloc_len = list_len + sizeof(*lundata);
6509		free(lundata);
6510		goto retry;
6511	}
6512
6513	if (lunsonly == 0)
6514		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6515			((list_len / 8) > 1) ? "s" : "");
6516
6517	if (countonly != 0)
6518		goto bailout;
6519
6520	for (i = 0; i < (list_len / 8); i++) {
6521		int no_more;
6522
6523		no_more = 0;
6524		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6525			if (j != 0)
6526				fprintf(stdout, ",");
6527			switch (lundata->luns[i].lundata[j] &
6528				RPL_LUNDATA_ATYP_MASK) {
6529			case RPL_LUNDATA_ATYP_PERIPH:
6530				if ((lundata->luns[i].lundata[j] &
6531				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6532					fprintf(stdout, "%d:",
6533						lundata->luns[i].lundata[j] &
6534						RPL_LUNDATA_PERIPH_BUS_MASK);
6535				else if ((j == 0)
6536				      && ((lundata->luns[i].lundata[j+2] &
6537					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6538					no_more = 1;
6539
6540				fprintf(stdout, "%d",
6541					lundata->luns[i].lundata[j+1]);
6542				break;
6543			case RPL_LUNDATA_ATYP_FLAT: {
6544				uint8_t tmplun[2];
6545				tmplun[0] = lundata->luns[i].lundata[j] &
6546					RPL_LUNDATA_FLAT_LUN_MASK;
6547				tmplun[1] = lundata->luns[i].lundata[j+1];
6548
6549				fprintf(stdout, "%d", scsi_2btoul(tmplun));
6550				no_more = 1;
6551				break;
6552			}
6553			case RPL_LUNDATA_ATYP_LUN:
6554				fprintf(stdout, "%d:%d:%d",
6555					(lundata->luns[i].lundata[j+1] &
6556					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6557					lundata->luns[i].lundata[j] &
6558					RPL_LUNDATA_LUN_TARG_MASK,
6559					lundata->luns[i].lundata[j+1] &
6560					RPL_LUNDATA_LUN_LUN_MASK);
6561				break;
6562			case RPL_LUNDATA_ATYP_EXTLUN: {
6563				int field_len_code, eam_code;
6564
6565				eam_code = lundata->luns[i].lundata[j] &
6566					RPL_LUNDATA_EXT_EAM_MASK;
6567				field_len_code = (lundata->luns[i].lundata[j] &
6568					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6569
6570				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6571				 && (field_len_code == 0x00)) {
6572					fprintf(stdout, "%d",
6573						lundata->luns[i].lundata[j+1]);
6574				} else if ((eam_code ==
6575					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6576					&& (field_len_code == 0x03)) {
6577					uint8_t tmp_lun[8];
6578
6579					/*
6580					 * This format takes up all 8 bytes.
6581					 * If we aren't starting at offset 0,
6582					 * that's a bug.
6583					 */
6584					if (j != 0) {
6585						fprintf(stdout, "Invalid "
6586							"offset %d for "
6587							"Extended LUN not "
6588							"specified format", j);
6589						no_more = 1;
6590						break;
6591					}
6592					bzero(tmp_lun, sizeof(tmp_lun));
6593					bcopy(&lundata->luns[i].lundata[j+1],
6594					      &tmp_lun[1], sizeof(tmp_lun) - 1);
6595					fprintf(stdout, "%#jx",
6596					       (intmax_t)scsi_8btou64(tmp_lun));
6597					no_more = 1;
6598				} else {
6599					fprintf(stderr, "Unknown Extended LUN"
6600						"Address method %#x, length "
6601						"code %#x", eam_code,
6602						field_len_code);
6603					no_more = 1;
6604				}
6605				break;
6606			}
6607			default:
6608				fprintf(stderr, "Unknown LUN address method "
6609					"%#x\n", lundata->luns[i].lundata[0] &
6610					RPL_LUNDATA_ATYP_MASK);
6611				break;
6612			}
6613			/*
6614			 * For the flat addressing method, there are no
6615			 * other levels after it.
6616			 */
6617			if (no_more != 0)
6618				break;
6619		}
6620		fprintf(stdout, "\n");
6621	}
6622
6623bailout:
6624
6625	cam_freeccb(ccb);
6626
6627	free(lundata);
6628
6629	return (retval);
6630}
6631
6632static int
6633scsireadcapacity(struct cam_device *device, int argc, char **argv,
6634		 char *combinedopt, int retry_count, int timeout)
6635{
6636	union ccb *ccb;
6637	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6638	struct scsi_read_capacity_data rcap;
6639	struct scsi_read_capacity_data_long rcaplong;
6640	uint64_t maxsector;
6641	uint32_t block_len;
6642	int retval;
6643	int c;
6644
6645	blocksizeonly = 0;
6646	humanize = 0;
6647	numblocks = 0;
6648	quiet = 0;
6649	sizeonly = 0;
6650	baseten = 0;
6651	retval = 0;
6652
6653	ccb = cam_getccb(device);
6654
6655	if (ccb == NULL) {
6656		warnx("%s: error allocating ccb", __func__);
6657		return (1);
6658	}
6659
6660	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6661
6662	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6663		switch (c) {
6664		case 'b':
6665			blocksizeonly++;
6666			break;
6667		case 'h':
6668			humanize++;
6669			baseten = 0;
6670			break;
6671		case 'H':
6672			humanize++;
6673			baseten++;
6674			break;
6675		case 'N':
6676			numblocks++;
6677			break;
6678		case 'q':
6679			quiet++;
6680			break;
6681		case 's':
6682			sizeonly++;
6683			break;
6684		default:
6685			break;
6686		}
6687	}
6688
6689	if ((blocksizeonly != 0)
6690	 && (numblocks != 0)) {
6691		warnx("%s: you can only specify one of -b or -N", __func__);
6692		retval = 1;
6693		goto bailout;
6694	}
6695
6696	if ((blocksizeonly != 0)
6697	 && (sizeonly != 0)) {
6698		warnx("%s: you can only specify one of -b or -s", __func__);
6699		retval = 1;
6700		goto bailout;
6701	}
6702
6703	if ((humanize != 0)
6704	 && (quiet != 0)) {
6705		warnx("%s: you can only specify one of -h/-H or -q", __func__);
6706		retval = 1;
6707		goto bailout;
6708	}
6709
6710	if ((humanize != 0)
6711	 && (blocksizeonly != 0)) {
6712		warnx("%s: you can only specify one of -h/-H or -b", __func__);
6713		retval = 1;
6714		goto bailout;
6715	}
6716
6717	scsi_read_capacity(&ccb->csio,
6718			   /*retries*/ retry_count,
6719			   /*cbfcnp*/ NULL,
6720			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
6721			   &rcap,
6722			   SSD_FULL_SIZE,
6723			   /*timeout*/ timeout ? timeout : 5000);
6724
6725	/* Disable freezing the device queue */
6726	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6727
6728	if (arglist & CAM_ARG_ERR_RECOVER)
6729		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6730
6731	if (cam_send_ccb(device, ccb) < 0) {
6732		warn("error sending READ CAPACITY command");
6733
6734		if (arglist & CAM_ARG_VERBOSE)
6735			cam_error_print(device, ccb, CAM_ESF_ALL,
6736					CAM_EPF_ALL, stderr);
6737
6738		retval = 1;
6739		goto bailout;
6740	}
6741
6742	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6743		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6744		retval = 1;
6745		goto bailout;
6746	}
6747
6748	maxsector = scsi_4btoul(rcap.addr);
6749	block_len = scsi_4btoul(rcap.length);
6750
6751	/*
6752	 * A last block of 2^32-1 means that the true capacity is over 2TB,
6753	 * and we need to issue the long READ CAPACITY to get the real
6754	 * capacity.  Otherwise, we're all set.
6755	 */
6756	if (maxsector != 0xffffffff)
6757		goto do_print;
6758
6759	scsi_read_capacity_16(&ccb->csio,
6760			      /*retries*/ retry_count,
6761			      /*cbfcnp*/ NULL,
6762			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
6763			      /*lba*/ 0,
6764			      /*reladdr*/ 0,
6765			      /*pmi*/ 0,
6766			      /*rcap_buf*/ (uint8_t *)&rcaplong,
6767			      /*rcap_buf_len*/ sizeof(rcaplong),
6768			      /*sense_len*/ SSD_FULL_SIZE,
6769			      /*timeout*/ timeout ? timeout : 5000);
6770
6771	/* Disable freezing the device queue */
6772	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6773
6774	if (arglist & CAM_ARG_ERR_RECOVER)
6775		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6776
6777	if (cam_send_ccb(device, ccb) < 0) {
6778		warn("error sending READ CAPACITY (16) command");
6779
6780		if (arglist & CAM_ARG_VERBOSE)
6781			cam_error_print(device, ccb, CAM_ESF_ALL,
6782					CAM_EPF_ALL, stderr);
6783
6784		retval = 1;
6785		goto bailout;
6786	}
6787
6788	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6789		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6790		retval = 1;
6791		goto bailout;
6792	}
6793
6794	maxsector = scsi_8btou64(rcaplong.addr);
6795	block_len = scsi_4btoul(rcaplong.length);
6796
6797do_print:
6798	if (blocksizeonly == 0) {
6799		/*
6800		 * Humanize implies !quiet, and also implies numblocks.
6801		 */
6802		if (humanize != 0) {
6803			char tmpstr[6];
6804			int64_t tmpbytes;
6805			int ret;
6806
6807			tmpbytes = (maxsector + 1) * block_len;
6808			ret = humanize_number(tmpstr, sizeof(tmpstr),
6809					      tmpbytes, "", HN_AUTOSCALE,
6810					      HN_B | HN_DECIMAL |
6811					      ((baseten != 0) ?
6812					      HN_DIVISOR_1000 : 0));
6813			if (ret == -1) {
6814				warnx("%s: humanize_number failed!", __func__);
6815				retval = 1;
6816				goto bailout;
6817			}
6818			fprintf(stdout, "Device Size: %s%s", tmpstr,
6819				(sizeonly == 0) ?  ", " : "\n");
6820		} else if (numblocks != 0) {
6821			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6822				"Blocks: " : "", (uintmax_t)maxsector + 1,
6823				(sizeonly == 0) ? ", " : "\n");
6824		} else {
6825			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6826				"Last Block: " : "", (uintmax_t)maxsector,
6827				(sizeonly == 0) ? ", " : "\n");
6828		}
6829	}
6830	if (sizeonly == 0)
6831		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6832			"Block Length: " : "", block_len, (quiet == 0) ?
6833			" bytes" : "");
6834bailout:
6835	cam_freeccb(ccb);
6836
6837	return (retval);
6838}
6839
6840static int
6841smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6842       int retry_count, int timeout)
6843{
6844	int c, error = 0;
6845	union ccb *ccb;
6846	uint8_t *smp_request = NULL, *smp_response = NULL;
6847	int request_size = 0, response_size = 0;
6848	int fd_request = 0, fd_response = 0;
6849	char *datastr = NULL;
6850	struct get_hook hook;
6851	int retval;
6852	int flags = 0;
6853
6854	/*
6855	 * Note that at the moment we don't support sending SMP CCBs to
6856	 * devices that aren't probed by CAM.
6857	 */
6858	ccb = cam_getccb(device);
6859	if (ccb == NULL) {
6860		warnx("%s: error allocating CCB", __func__);
6861		return (1);
6862	}
6863
6864	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
6865
6866	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6867		switch (c) {
6868		case 'R':
6869			arglist |= CAM_ARG_CMD_IN;
6870			response_size = strtol(optarg, NULL, 0);
6871			if (response_size <= 0) {
6872				warnx("invalid number of response bytes %d",
6873				      response_size);
6874				error = 1;
6875				goto smpcmd_bailout;
6876			}
6877			hook.argc = argc - optind;
6878			hook.argv = argv + optind;
6879			hook.got = 0;
6880			optind++;
6881			datastr = cget(&hook, NULL);
6882			/*
6883			 * If the user supplied "-" instead of a format, he
6884			 * wants the data to be written to stdout.
6885			 */
6886			if ((datastr != NULL)
6887			 && (datastr[0] == '-'))
6888				fd_response = 1;
6889
6890			smp_response = (u_int8_t *)malloc(response_size);
6891			if (smp_response == NULL) {
6892				warn("can't malloc memory for SMP response");
6893				error = 1;
6894				goto smpcmd_bailout;
6895			}
6896			break;
6897		case 'r':
6898			arglist |= CAM_ARG_CMD_OUT;
6899			request_size = strtol(optarg, NULL, 0);
6900			if (request_size <= 0) {
6901				warnx("invalid number of request bytes %d",
6902				      request_size);
6903				error = 1;
6904				goto smpcmd_bailout;
6905			}
6906			hook.argc = argc - optind;
6907			hook.argv = argv + optind;
6908			hook.got = 0;
6909			datastr = cget(&hook, NULL);
6910			smp_request = (u_int8_t *)malloc(request_size);
6911			if (smp_request == NULL) {
6912				warn("can't malloc memory for SMP request");
6913				error = 1;
6914				goto smpcmd_bailout;
6915			}
6916			bzero(smp_request, request_size);
6917			/*
6918			 * If the user supplied "-" instead of a format, he
6919			 * wants the data to be read from stdin.
6920			 */
6921			if ((datastr != NULL)
6922			 && (datastr[0] == '-'))
6923				fd_request = 1;
6924			else
6925				buff_encode_visit(smp_request, request_size,
6926						  datastr,
6927						  iget, &hook);
6928			optind += hook.got;
6929			break;
6930		default:
6931			break;
6932		}
6933	}
6934
6935	/*
6936	 * If fd_data is set, and we're writing to the device, we need to
6937	 * read the data the user wants written from stdin.
6938	 */
6939	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6940		ssize_t amt_read;
6941		int amt_to_read = request_size;
6942		u_int8_t *buf_ptr = smp_request;
6943
6944		for (amt_read = 0; amt_to_read > 0;
6945		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6946			if (amt_read == -1) {
6947				warn("error reading data from stdin");
6948				error = 1;
6949				goto smpcmd_bailout;
6950			}
6951			amt_to_read -= amt_read;
6952			buf_ptr += amt_read;
6953		}
6954	}
6955
6956	if (((arglist & CAM_ARG_CMD_IN) == 0)
6957	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6958		warnx("%s: need both the request (-r) and response (-R) "
6959		      "arguments", __func__);
6960		error = 1;
6961		goto smpcmd_bailout;
6962	}
6963
6964	flags |= CAM_DEV_QFRZDIS;
6965
6966	cam_fill_smpio(&ccb->smpio,
6967		       /*retries*/ retry_count,
6968		       /*cbfcnp*/ NULL,
6969		       /*flags*/ flags,
6970		       /*smp_request*/ smp_request,
6971		       /*smp_request_len*/ request_size,
6972		       /*smp_response*/ smp_response,
6973		       /*smp_response_len*/ response_size,
6974		       /*timeout*/ timeout ? timeout : 5000);
6975
6976	ccb->smpio.flags = SMP_FLAG_NONE;
6977
6978	if (((retval = cam_send_ccb(device, ccb)) < 0)
6979	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6980		const char warnstr[] = "error sending command";
6981
6982		if (retval < 0)
6983			warn(warnstr);
6984		else
6985			warnx(warnstr);
6986
6987		if (arglist & CAM_ARG_VERBOSE) {
6988			cam_error_print(device, ccb, CAM_ESF_ALL,
6989					CAM_EPF_ALL, stderr);
6990		}
6991	}
6992
6993	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6994	 && (response_size > 0)) {
6995		if (fd_response == 0) {
6996			buff_decode_visit(smp_response, response_size,
6997					  datastr, arg_put, NULL);
6998			fprintf(stdout, "\n");
6999		} else {
7000			ssize_t amt_written;
7001			int amt_to_write = response_size;
7002			u_int8_t *buf_ptr = smp_response;
7003
7004			for (amt_written = 0; (amt_to_write > 0) &&
7005			     (amt_written = write(STDOUT_FILENO, buf_ptr,
7006						  amt_to_write)) > 0;){
7007				amt_to_write -= amt_written;
7008				buf_ptr += amt_written;
7009			}
7010			if (amt_written == -1) {
7011				warn("error writing data to stdout");
7012				error = 1;
7013				goto smpcmd_bailout;
7014			} else if ((amt_written == 0)
7015				&& (amt_to_write > 0)) {
7016				warnx("only wrote %u bytes out of %u",
7017				      response_size - amt_to_write,
7018				      response_size);
7019			}
7020		}
7021	}
7022smpcmd_bailout:
7023	if (ccb != NULL)
7024		cam_freeccb(ccb);
7025
7026	if (smp_request != NULL)
7027		free(smp_request);
7028
7029	if (smp_response != NULL)
7030		free(smp_response);
7031
7032	return (error);
7033}
7034
7035static int
7036smpreportgeneral(struct cam_device *device, int argc, char **argv,
7037		 char *combinedopt, int retry_count, int timeout)
7038{
7039	union ccb *ccb;
7040	struct smp_report_general_request *request = NULL;
7041	struct smp_report_general_response *response = NULL;
7042	struct sbuf *sb = NULL;
7043	int error = 0;
7044	int c, long_response = 0;
7045	int retval;
7046
7047	/*
7048	 * Note that at the moment we don't support sending SMP CCBs to
7049	 * devices that aren't probed by CAM.
7050	 */
7051	ccb = cam_getccb(device);
7052	if (ccb == NULL) {
7053		warnx("%s: error allocating CCB", __func__);
7054		return (1);
7055	}
7056
7057	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7058
7059	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7060		switch (c) {
7061		case 'l':
7062			long_response = 1;
7063			break;
7064		default:
7065			break;
7066		}
7067	}
7068	request = malloc(sizeof(*request));
7069	if (request == NULL) {
7070		warn("%s: unable to allocate %zd bytes", __func__,
7071		     sizeof(*request));
7072		error = 1;
7073		goto bailout;
7074	}
7075
7076	response = malloc(sizeof(*response));
7077	if (response == NULL) {
7078		warn("%s: unable to allocate %zd bytes", __func__,
7079		     sizeof(*response));
7080		error = 1;
7081		goto bailout;
7082	}
7083
7084try_long:
7085	smp_report_general(&ccb->smpio,
7086			   retry_count,
7087			   /*cbfcnp*/ NULL,
7088			   request,
7089			   /*request_len*/ sizeof(*request),
7090			   (uint8_t *)response,
7091			   /*response_len*/ sizeof(*response),
7092			   /*long_response*/ long_response,
7093			   timeout);
7094
7095	if (((retval = cam_send_ccb(device, ccb)) < 0)
7096	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7097		const char warnstr[] = "error sending command";
7098
7099		if (retval < 0)
7100			warn(warnstr);
7101		else
7102			warnx(warnstr);
7103
7104		if (arglist & CAM_ARG_VERBOSE) {
7105			cam_error_print(device, ccb, CAM_ESF_ALL,
7106					CAM_EPF_ALL, stderr);
7107		}
7108		error = 1;
7109		goto bailout;
7110	}
7111
7112	/*
7113	 * If the device supports the long response bit, try again and see
7114	 * if we can get all of the data.
7115	 */
7116	if ((response->long_response & SMP_RG_LONG_RESPONSE)
7117	 && (long_response == 0)) {
7118		ccb->ccb_h.status = CAM_REQ_INPROG;
7119		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7120		long_response = 1;
7121		goto try_long;
7122	}
7123
7124	/*
7125	 * XXX KDM detect and decode SMP errors here.
7126	 */
7127	sb = sbuf_new_auto();
7128	if (sb == NULL) {
7129		warnx("%s: error allocating sbuf", __func__);
7130		goto bailout;
7131	}
7132
7133	smp_report_general_sbuf(response, sizeof(*response), sb);
7134
7135	if (sbuf_finish(sb) != 0) {
7136		warnx("%s: sbuf_finish", __func__);
7137		goto bailout;
7138	}
7139
7140	printf("%s", sbuf_data(sb));
7141
7142bailout:
7143	if (ccb != NULL)
7144		cam_freeccb(ccb);
7145
7146	if (request != NULL)
7147		free(request);
7148
7149	if (response != NULL)
7150		free(response);
7151
7152	if (sb != NULL)
7153		sbuf_delete(sb);
7154
7155	return (error);
7156}
7157
7158static struct camcontrol_opts phy_ops[] = {
7159	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7160	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7161	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7162	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7163	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7164	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7165	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7166	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7167	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7168	{NULL, 0, 0, NULL}
7169};
7170
7171static int
7172smpphycontrol(struct cam_device *device, int argc, char **argv,
7173	      char *combinedopt, int retry_count, int timeout)
7174{
7175	union ccb *ccb;
7176	struct smp_phy_control_request *request = NULL;
7177	struct smp_phy_control_response *response = NULL;
7178	int long_response = 0;
7179	int retval = 0;
7180	int phy = -1;
7181	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7182	int phy_op_set = 0;
7183	uint64_t attached_dev_name = 0;
7184	int dev_name_set = 0;
7185	uint32_t min_plr = 0, max_plr = 0;
7186	uint32_t pp_timeout_val = 0;
7187	int slumber_partial = 0;
7188	int set_pp_timeout_val = 0;
7189	int c;
7190
7191	/*
7192	 * Note that at the moment we don't support sending SMP CCBs to
7193	 * devices that aren't probed by CAM.
7194	 */
7195	ccb = cam_getccb(device);
7196	if (ccb == NULL) {
7197		warnx("%s: error allocating CCB", __func__);
7198		return (1);
7199	}
7200
7201	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7202
7203	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7204		switch (c) {
7205		case 'a':
7206		case 'A':
7207		case 's':
7208		case 'S': {
7209			int enable = -1;
7210
7211			if (strcasecmp(optarg, "enable") == 0)
7212				enable = 1;
7213			else if (strcasecmp(optarg, "disable") == 0)
7214				enable = 2;
7215			else {
7216				warnx("%s: Invalid argument %s", __func__,
7217				      optarg);
7218				retval = 1;
7219				goto bailout;
7220			}
7221			switch (c) {
7222			case 's':
7223				slumber_partial |= enable <<
7224						   SMP_PC_SAS_SLUMBER_SHIFT;
7225				break;
7226			case 'S':
7227				slumber_partial |= enable <<
7228						   SMP_PC_SAS_PARTIAL_SHIFT;
7229				break;
7230			case 'a':
7231				slumber_partial |= enable <<
7232						   SMP_PC_SATA_SLUMBER_SHIFT;
7233				break;
7234			case 'A':
7235				slumber_partial |= enable <<
7236						   SMP_PC_SATA_PARTIAL_SHIFT;
7237				break;
7238			default:
7239				warnx("%s: programmer error", __func__);
7240				retval = 1;
7241				goto bailout;
7242				break; /*NOTREACHED*/
7243			}
7244			break;
7245		}
7246		case 'd':
7247			attached_dev_name = (uintmax_t)strtoumax(optarg,
7248								 NULL,0);
7249			dev_name_set = 1;
7250			break;
7251		case 'l':
7252			long_response = 1;
7253			break;
7254		case 'm':
7255			/*
7256			 * We don't do extensive checking here, so this
7257			 * will continue to work when new speeds come out.
7258			 */
7259			min_plr = strtoul(optarg, NULL, 0);
7260			if ((min_plr == 0)
7261			 || (min_plr > 0xf)) {
7262				warnx("%s: invalid link rate %x",
7263				      __func__, min_plr);
7264				retval = 1;
7265				goto bailout;
7266			}
7267			break;
7268		case 'M':
7269			/*
7270			 * We don't do extensive checking here, so this
7271			 * will continue to work when new speeds come out.
7272			 */
7273			max_plr = strtoul(optarg, NULL, 0);
7274			if ((max_plr == 0)
7275			 || (max_plr > 0xf)) {
7276				warnx("%s: invalid link rate %x",
7277				      __func__, max_plr);
7278				retval = 1;
7279				goto bailout;
7280			}
7281			break;
7282		case 'o': {
7283			camcontrol_optret optreturn;
7284			cam_argmask argnums;
7285			const char *subopt;
7286
7287			if (phy_op_set != 0) {
7288				warnx("%s: only one phy operation argument "
7289				      "(-o) allowed", __func__);
7290				retval = 1;
7291				goto bailout;
7292			}
7293
7294			phy_op_set = 1;
7295
7296			/*
7297			 * Allow the user to specify the phy operation
7298			 * numerically, as well as with a name.  This will
7299			 * future-proof it a bit, so options that are added
7300			 * in future specs can be used.
7301			 */
7302			if (isdigit(optarg[0])) {
7303				phy_operation = strtoul(optarg, NULL, 0);
7304				if ((phy_operation == 0)
7305				 || (phy_operation > 0xff)) {
7306					warnx("%s: invalid phy operation %#x",
7307					      __func__, phy_operation);
7308					retval = 1;
7309					goto bailout;
7310				}
7311				break;
7312			}
7313			optreturn = getoption(phy_ops, optarg, &phy_operation,
7314					      &argnums, &subopt);
7315
7316			if (optreturn == CC_OR_AMBIGUOUS) {
7317				warnx("%s: ambiguous option %s", __func__,
7318				      optarg);
7319				usage(0);
7320				retval = 1;
7321				goto bailout;
7322			} else if (optreturn == CC_OR_NOT_FOUND) {
7323				warnx("%s: option %s not found", __func__,
7324				      optarg);
7325				usage(0);
7326				retval = 1;
7327				goto bailout;
7328			}
7329			break;
7330		}
7331		case 'p':
7332			phy = atoi(optarg);
7333			break;
7334		case 'T':
7335			pp_timeout_val = strtoul(optarg, NULL, 0);
7336			if (pp_timeout_val > 15) {
7337				warnx("%s: invalid partial pathway timeout "
7338				      "value %u, need a value less than 16",
7339				      __func__, pp_timeout_val);
7340				retval = 1;
7341				goto bailout;
7342			}
7343			set_pp_timeout_val = 1;
7344			break;
7345		default:
7346			break;
7347		}
7348	}
7349
7350	if (phy == -1) {
7351		warnx("%s: a PHY (-p phy) argument is required",__func__);
7352		retval = 1;
7353		goto bailout;
7354	}
7355
7356	if (((dev_name_set != 0)
7357	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7358	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7359	  && (dev_name_set == 0))) {
7360		warnx("%s: -d name and -o setdevname arguments both "
7361		      "required to set device name", __func__);
7362		retval = 1;
7363		goto bailout;
7364	}
7365
7366	request = malloc(sizeof(*request));
7367	if (request == NULL) {
7368		warn("%s: unable to allocate %zd bytes", __func__,
7369		     sizeof(*request));
7370		retval = 1;
7371		goto bailout;
7372	}
7373
7374	response = malloc(sizeof(*response));
7375	if (response == NULL) {
7376		warn("%s: unable to allocate %zd bytes", __func__,
7377		     sizeof(*response));
7378		retval = 1;
7379		goto bailout;
7380	}
7381
7382	smp_phy_control(&ccb->smpio,
7383			retry_count,
7384			/*cbfcnp*/ NULL,
7385			request,
7386			sizeof(*request),
7387			(uint8_t *)response,
7388			sizeof(*response),
7389			long_response,
7390			/*expected_exp_change_count*/ 0,
7391			phy,
7392			phy_operation,
7393			(set_pp_timeout_val != 0) ? 1 : 0,
7394			attached_dev_name,
7395			min_plr,
7396			max_plr,
7397			slumber_partial,
7398			pp_timeout_val,
7399			timeout);
7400
7401	if (((retval = cam_send_ccb(device, ccb)) < 0)
7402	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7403		const char warnstr[] = "error sending command";
7404
7405		if (retval < 0)
7406			warn(warnstr);
7407		else
7408			warnx(warnstr);
7409
7410		if (arglist & CAM_ARG_VERBOSE) {
7411			/*
7412			 * Use CAM_EPF_NORMAL so we only get one line of
7413			 * SMP command decoding.
7414			 */
7415			cam_error_print(device, ccb, CAM_ESF_ALL,
7416					CAM_EPF_NORMAL, stderr);
7417		}
7418		retval = 1;
7419		goto bailout;
7420	}
7421
7422	/* XXX KDM print out something here for success? */
7423bailout:
7424	if (ccb != NULL)
7425		cam_freeccb(ccb);
7426
7427	if (request != NULL)
7428		free(request);
7429
7430	if (response != NULL)
7431		free(response);
7432
7433	return (retval);
7434}
7435
7436static int
7437smpmaninfo(struct cam_device *device, int argc, char **argv,
7438	   char *combinedopt, int retry_count, int timeout)
7439{
7440	union ccb *ccb;
7441	struct smp_report_manuf_info_request request;
7442	struct smp_report_manuf_info_response response;
7443	struct sbuf *sb = NULL;
7444	int long_response = 0;
7445	int retval = 0;
7446	int c;
7447
7448	/*
7449	 * Note that at the moment we don't support sending SMP CCBs to
7450	 * devices that aren't probed by CAM.
7451	 */
7452	ccb = cam_getccb(device);
7453	if (ccb == NULL) {
7454		warnx("%s: error allocating CCB", __func__);
7455		return (1);
7456	}
7457
7458	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7459
7460	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7461		switch (c) {
7462		case 'l':
7463			long_response = 1;
7464			break;
7465		default:
7466			break;
7467		}
7468	}
7469	bzero(&request, sizeof(request));
7470	bzero(&response, sizeof(response));
7471
7472	smp_report_manuf_info(&ccb->smpio,
7473			      retry_count,
7474			      /*cbfcnp*/ NULL,
7475			      &request,
7476			      sizeof(request),
7477			      (uint8_t *)&response,
7478			      sizeof(response),
7479			      long_response,
7480			      timeout);
7481
7482	if (((retval = cam_send_ccb(device, ccb)) < 0)
7483	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7484		const char warnstr[] = "error sending command";
7485
7486		if (retval < 0)
7487			warn(warnstr);
7488		else
7489			warnx(warnstr);
7490
7491		if (arglist & CAM_ARG_VERBOSE) {
7492			cam_error_print(device, ccb, CAM_ESF_ALL,
7493					CAM_EPF_ALL, stderr);
7494		}
7495		retval = 1;
7496		goto bailout;
7497	}
7498
7499	sb = sbuf_new_auto();
7500	if (sb == NULL) {
7501		warnx("%s: error allocating sbuf", __func__);
7502		goto bailout;
7503	}
7504
7505	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7506
7507	if (sbuf_finish(sb) != 0) {
7508		warnx("%s: sbuf_finish", __func__);
7509		goto bailout;
7510	}
7511
7512	printf("%s", sbuf_data(sb));
7513
7514bailout:
7515
7516	if (ccb != NULL)
7517		cam_freeccb(ccb);
7518
7519	if (sb != NULL)
7520		sbuf_delete(sb);
7521
7522	return (retval);
7523}
7524
7525static int
7526getdevid(struct cam_devitem *item)
7527{
7528	int retval = 0;
7529	union ccb *ccb = NULL;
7530
7531	struct cam_device *dev;
7532
7533	dev = cam_open_btl(item->dev_match.path_id,
7534			   item->dev_match.target_id,
7535			   item->dev_match.target_lun, O_RDWR, NULL);
7536
7537	if (dev == NULL) {
7538		warnx("%s", cam_errbuf);
7539		retval = 1;
7540		goto bailout;
7541	}
7542
7543	item->device_id_len = 0;
7544
7545	ccb = cam_getccb(dev);
7546	if (ccb == NULL) {
7547		warnx("%s: error allocating CCB", __func__);
7548		retval = 1;
7549		goto bailout;
7550	}
7551
7552	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai);
7553
7554	/*
7555	 * On the first try, we just probe for the size of the data, and
7556	 * then allocate that much memory and try again.
7557	 */
7558retry:
7559	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7560	ccb->ccb_h.flags = CAM_DIR_IN;
7561	ccb->cdai.flags = CDAI_FLAG_NONE;
7562	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7563	ccb->cdai.bufsiz = item->device_id_len;
7564	if (item->device_id_len != 0)
7565		ccb->cdai.buf = (uint8_t *)item->device_id;
7566
7567	if (cam_send_ccb(dev, ccb) < 0) {
7568		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7569		retval = 1;
7570		goto bailout;
7571	}
7572
7573	if (ccb->ccb_h.status != CAM_REQ_CMP) {
7574		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7575		retval = 1;
7576		goto bailout;
7577	}
7578
7579	if (item->device_id_len == 0) {
7580		/*
7581		 * This is our first time through.  Allocate the buffer,
7582		 * and then go back to get the data.
7583		 */
7584		if (ccb->cdai.provsiz == 0) {
7585			warnx("%s: invalid .provsiz field returned with "
7586			     "XPT_GDEV_ADVINFO CCB", __func__);
7587			retval = 1;
7588			goto bailout;
7589		}
7590		item->device_id_len = ccb->cdai.provsiz;
7591		item->device_id = malloc(item->device_id_len);
7592		if (item->device_id == NULL) {
7593			warn("%s: unable to allocate %d bytes", __func__,
7594			     item->device_id_len);
7595			retval = 1;
7596			goto bailout;
7597		}
7598		ccb->ccb_h.status = CAM_REQ_INPROG;
7599		goto retry;
7600	}
7601
7602bailout:
7603	if (dev != NULL)
7604		cam_close_device(dev);
7605
7606	if (ccb != NULL)
7607		cam_freeccb(ccb);
7608
7609	return (retval);
7610}
7611
7612/*
7613 * XXX KDM merge this code with getdevtree()?
7614 */
7615static int
7616buildbusdevlist(struct cam_devlist *devlist)
7617{
7618	union ccb ccb;
7619	int bufsize, fd = -1;
7620	struct dev_match_pattern *patterns;
7621	struct cam_devitem *item = NULL;
7622	int skip_device = 0;
7623	int retval = 0;
7624
7625	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7626		warn("couldn't open %s", XPT_DEVICE);
7627		return(1);
7628	}
7629
7630	bzero(&ccb, sizeof(union ccb));
7631
7632	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7633	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7634	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7635
7636	ccb.ccb_h.func_code = XPT_DEV_MATCH;
7637	bufsize = sizeof(struct dev_match_result) * 100;
7638	ccb.cdm.match_buf_len = bufsize;
7639	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7640	if (ccb.cdm.matches == NULL) {
7641		warnx("can't malloc memory for matches");
7642		close(fd);
7643		return(1);
7644	}
7645	ccb.cdm.num_matches = 0;
7646	ccb.cdm.num_patterns = 2;
7647	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7648		ccb.cdm.num_patterns;
7649
7650	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7651	if (patterns == NULL) {
7652		warnx("can't malloc memory for patterns");
7653		retval = 1;
7654		goto bailout;
7655	}
7656
7657	ccb.cdm.patterns = patterns;
7658	bzero(patterns, ccb.cdm.pattern_buf_len);
7659
7660	patterns[0].type = DEV_MATCH_DEVICE;
7661	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7662	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7663	patterns[1].type = DEV_MATCH_PERIPH;
7664	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7665	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7666
7667	/*
7668	 * We do the ioctl multiple times if necessary, in case there are
7669	 * more than 100 nodes in the EDT.
7670	 */
7671	do {
7672		unsigned int i;
7673
7674		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7675			warn("error sending CAMIOCOMMAND ioctl");
7676			retval = 1;
7677			goto bailout;
7678		}
7679
7680		if ((ccb.ccb_h.status != CAM_REQ_CMP)
7681		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7682		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7683			warnx("got CAM error %#x, CDM error %d\n",
7684			      ccb.ccb_h.status, ccb.cdm.status);
7685			retval = 1;
7686			goto bailout;
7687		}
7688
7689		for (i = 0; i < ccb.cdm.num_matches; i++) {
7690			switch (ccb.cdm.matches[i].type) {
7691			case DEV_MATCH_DEVICE: {
7692				struct device_match_result *dev_result;
7693
7694				dev_result =
7695				     &ccb.cdm.matches[i].result.device_result;
7696
7697				if (dev_result->flags &
7698				    DEV_RESULT_UNCONFIGURED) {
7699					skip_device = 1;
7700					break;
7701				} else
7702					skip_device = 0;
7703
7704				item = malloc(sizeof(*item));
7705				if (item == NULL) {
7706					warn("%s: unable to allocate %zd bytes",
7707					     __func__, sizeof(*item));
7708					retval = 1;
7709					goto bailout;
7710				}
7711				bzero(item, sizeof(*item));
7712				bcopy(dev_result, &item->dev_match,
7713				      sizeof(*dev_result));
7714				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7715						   links);
7716
7717				if (getdevid(item) != 0) {
7718					retval = 1;
7719					goto bailout;
7720				}
7721				break;
7722			}
7723			case DEV_MATCH_PERIPH: {
7724				struct periph_match_result *periph_result;
7725
7726				periph_result =
7727				      &ccb.cdm.matches[i].result.periph_result;
7728
7729				if (skip_device != 0)
7730					break;
7731				item->num_periphs++;
7732				item->periph_matches = realloc(
7733					item->periph_matches,
7734					item->num_periphs *
7735					sizeof(struct periph_match_result));
7736				if (item->periph_matches == NULL) {
7737					warn("%s: error allocating periph "
7738					     "list", __func__);
7739					retval = 1;
7740					goto bailout;
7741				}
7742				bcopy(periph_result, &item->periph_matches[
7743				      item->num_periphs - 1],
7744				      sizeof(*periph_result));
7745				break;
7746			}
7747			default:
7748				fprintf(stderr, "%s: unexpected match "
7749					"type %d\n", __func__,
7750					ccb.cdm.matches[i].type);
7751				retval = 1;
7752				goto bailout;
7753				break; /*NOTREACHED*/
7754			}
7755		}
7756	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
7757		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7758bailout:
7759
7760	if (fd != -1)
7761		close(fd);
7762
7763	free(patterns);
7764
7765	free(ccb.cdm.matches);
7766
7767	if (retval != 0)
7768		freebusdevlist(devlist);
7769
7770	return (retval);
7771}
7772
7773static void
7774freebusdevlist(struct cam_devlist *devlist)
7775{
7776	struct cam_devitem *item, *item2;
7777
7778	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7779		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7780			      links);
7781		free(item->device_id);
7782		free(item->periph_matches);
7783		free(item);
7784	}
7785}
7786
7787static struct cam_devitem *
7788findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7789{
7790	struct cam_devitem *item;
7791
7792	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7793		struct scsi_vpd_id_descriptor *idd;
7794
7795		/*
7796		 * XXX KDM look for LUN IDs as well?
7797		 */
7798		idd = scsi_get_devid(item->device_id,
7799					   item->device_id_len,
7800					   scsi_devid_is_sas_target);
7801		if (idd == NULL)
7802			continue;
7803
7804		if (scsi_8btou64(idd->identifier) == sasaddr)
7805			return (item);
7806	}
7807
7808	return (NULL);
7809}
7810
7811static int
7812smpphylist(struct cam_device *device, int argc, char **argv,
7813	   char *combinedopt, int retry_count, int timeout)
7814{
7815	struct smp_report_general_request *rgrequest = NULL;
7816	struct smp_report_general_response *rgresponse = NULL;
7817	struct smp_discover_request *disrequest = NULL;
7818	struct smp_discover_response *disresponse = NULL;
7819	struct cam_devlist devlist;
7820	union ccb *ccb;
7821	int long_response = 0;
7822	int num_phys = 0;
7823	int quiet = 0;
7824	int retval;
7825	int i, c;
7826
7827	/*
7828	 * Note that at the moment we don't support sending SMP CCBs to
7829	 * devices that aren't probed by CAM.
7830	 */
7831	ccb = cam_getccb(device);
7832	if (ccb == NULL) {
7833		warnx("%s: error allocating CCB", __func__);
7834		return (1);
7835	}
7836
7837	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7838	STAILQ_INIT(&devlist.dev_queue);
7839
7840	rgrequest = malloc(sizeof(*rgrequest));
7841	if (rgrequest == NULL) {
7842		warn("%s: unable to allocate %zd bytes", __func__,
7843		     sizeof(*rgrequest));
7844		retval = 1;
7845		goto bailout;
7846	}
7847
7848	rgresponse = malloc(sizeof(*rgresponse));
7849	if (rgresponse == NULL) {
7850		warn("%s: unable to allocate %zd bytes", __func__,
7851		     sizeof(*rgresponse));
7852		retval = 1;
7853		goto bailout;
7854	}
7855
7856	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7857		switch (c) {
7858		case 'l':
7859			long_response = 1;
7860			break;
7861		case 'q':
7862			quiet = 1;
7863			break;
7864		default:
7865			break;
7866		}
7867	}
7868
7869	smp_report_general(&ccb->smpio,
7870			   retry_count,
7871			   /*cbfcnp*/ NULL,
7872			   rgrequest,
7873			   /*request_len*/ sizeof(*rgrequest),
7874			   (uint8_t *)rgresponse,
7875			   /*response_len*/ sizeof(*rgresponse),
7876			   /*long_response*/ long_response,
7877			   timeout);
7878
7879	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7880
7881	if (((retval = cam_send_ccb(device, ccb)) < 0)
7882	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7883		const char warnstr[] = "error sending command";
7884
7885		if (retval < 0)
7886			warn(warnstr);
7887		else
7888			warnx(warnstr);
7889
7890		if (arglist & CAM_ARG_VERBOSE) {
7891			cam_error_print(device, ccb, CAM_ESF_ALL,
7892					CAM_EPF_ALL, stderr);
7893		}
7894		retval = 1;
7895		goto bailout;
7896	}
7897
7898	num_phys = rgresponse->num_phys;
7899
7900	if (num_phys == 0) {
7901		if (quiet == 0)
7902			fprintf(stdout, "%s: No Phys reported\n", __func__);
7903		retval = 1;
7904		goto bailout;
7905	}
7906
7907	devlist.path_id = device->path_id;
7908
7909	retval = buildbusdevlist(&devlist);
7910	if (retval != 0)
7911		goto bailout;
7912
7913	if (quiet == 0) {
7914		fprintf(stdout, "%d PHYs:\n", num_phys);
7915		fprintf(stdout, "PHY  Attached SAS Address\n");
7916	}
7917
7918	disrequest = malloc(sizeof(*disrequest));
7919	if (disrequest == NULL) {
7920		warn("%s: unable to allocate %zd bytes", __func__,
7921		     sizeof(*disrequest));
7922		retval = 1;
7923		goto bailout;
7924	}
7925
7926	disresponse = malloc(sizeof(*disresponse));
7927	if (disresponse == NULL) {
7928		warn("%s: unable to allocate %zd bytes", __func__,
7929		     sizeof(*disresponse));
7930		retval = 1;
7931		goto bailout;
7932	}
7933
7934	for (i = 0; i < num_phys; i++) {
7935		struct cam_devitem *item;
7936		struct device_match_result *dev_match;
7937		char vendor[16], product[48], revision[16];
7938		char tmpstr[256];
7939		int j;
7940
7941		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7942
7943		ccb->ccb_h.status = CAM_REQ_INPROG;
7944		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7945
7946		smp_discover(&ccb->smpio,
7947			     retry_count,
7948			     /*cbfcnp*/ NULL,
7949			     disrequest,
7950			     sizeof(*disrequest),
7951			     (uint8_t *)disresponse,
7952			     sizeof(*disresponse),
7953			     long_response,
7954			     /*ignore_zone_group*/ 0,
7955			     /*phy*/ i,
7956			     timeout);
7957
7958		if (((retval = cam_send_ccb(device, ccb)) < 0)
7959		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7960		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7961			const char warnstr[] = "error sending command";
7962
7963			if (retval < 0)
7964				warn(warnstr);
7965			else
7966				warnx(warnstr);
7967
7968			if (arglist & CAM_ARG_VERBOSE) {
7969				cam_error_print(device, ccb, CAM_ESF_ALL,
7970						CAM_EPF_ALL, stderr);
7971			}
7972			retval = 1;
7973			goto bailout;
7974		}
7975
7976		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7977			if (quiet == 0)
7978				fprintf(stdout, "%3d  <vacant>\n", i);
7979			continue;
7980		}
7981
7982		if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7983			item = NULL;
7984		} else {
7985			item = findsasdevice(&devlist,
7986			    scsi_8btou64(disresponse->attached_sas_address));
7987		}
7988
7989		if ((quiet == 0)
7990		 || (item != NULL)) {
7991			fprintf(stdout, "%3d  0x%016jx", i,
7992				(uintmax_t)scsi_8btou64(
7993				disresponse->attached_sas_address));
7994			if (item == NULL) {
7995				fprintf(stdout, "\n");
7996				continue;
7997			}
7998		} else if (quiet != 0)
7999			continue;
8000
8001		dev_match = &item->dev_match;
8002
8003		if (dev_match->protocol == PROTO_SCSI) {
8004			cam_strvis(vendor, dev_match->inq_data.vendor,
8005				   sizeof(dev_match->inq_data.vendor),
8006				   sizeof(vendor));
8007			cam_strvis(product, dev_match->inq_data.product,
8008				   sizeof(dev_match->inq_data.product),
8009				   sizeof(product));
8010			cam_strvis(revision, dev_match->inq_data.revision,
8011				   sizeof(dev_match->inq_data.revision),
8012				   sizeof(revision));
8013			sprintf(tmpstr, "<%s %s %s>", vendor, product,
8014				revision);
8015		} else if ((dev_match->protocol == PROTO_ATA)
8016			|| (dev_match->protocol == PROTO_SATAPM)) {
8017			cam_strvis(product, dev_match->ident_data.model,
8018				   sizeof(dev_match->ident_data.model),
8019				   sizeof(product));
8020			cam_strvis(revision, dev_match->ident_data.revision,
8021				   sizeof(dev_match->ident_data.revision),
8022				   sizeof(revision));
8023			sprintf(tmpstr, "<%s %s>", product, revision);
8024		} else {
8025			sprintf(tmpstr, "<>");
8026		}
8027		fprintf(stdout, "   %-33s ", tmpstr);
8028
8029		/*
8030		 * If we have 0 periphs, that's a bug...
8031		 */
8032		if (item->num_periphs == 0) {
8033			fprintf(stdout, "\n");
8034			continue;
8035		}
8036
8037		fprintf(stdout, "(");
8038		for (j = 0; j < item->num_periphs; j++) {
8039			if (j > 0)
8040				fprintf(stdout, ",");
8041
8042			fprintf(stdout, "%s%d",
8043				item->periph_matches[j].periph_name,
8044				item->periph_matches[j].unit_number);
8045
8046		}
8047		fprintf(stdout, ")\n");
8048	}
8049bailout:
8050	if (ccb != NULL)
8051		cam_freeccb(ccb);
8052
8053	free(rgrequest);
8054
8055	free(rgresponse);
8056
8057	free(disrequest);
8058
8059	free(disresponse);
8060
8061	freebusdevlist(&devlist);
8062
8063	return (retval);
8064}
8065
8066static int
8067atapm(struct cam_device *device, int argc, char **argv,
8068		 char *combinedopt, int retry_count, int timeout)
8069{
8070	union ccb *ccb;
8071	int retval = 0;
8072	int t = -1;
8073	int c;
8074	u_char cmd, sc;
8075
8076	ccb = cam_getccb(device);
8077
8078	if (ccb == NULL) {
8079		warnx("%s: error allocating ccb", __func__);
8080		return (1);
8081	}
8082
8083	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8084		switch (c) {
8085		case 't':
8086			t = atoi(optarg);
8087			break;
8088		default:
8089			break;
8090		}
8091	}
8092	if (strcmp(argv[1], "idle") == 0) {
8093		if (t == -1)
8094			cmd = ATA_IDLE_IMMEDIATE;
8095		else
8096			cmd = ATA_IDLE_CMD;
8097	} else if (strcmp(argv[1], "standby") == 0) {
8098		if (t == -1)
8099			cmd = ATA_STANDBY_IMMEDIATE;
8100		else
8101			cmd = ATA_STANDBY_CMD;
8102	} else {
8103		cmd = ATA_SLEEP;
8104		t = -1;
8105	}
8106
8107	if (t < 0)
8108		sc = 0;
8109	else if (t <= (240 * 5))
8110		sc = (t + 4) / 5;
8111	else if (t <= (252 * 5))
8112		/* special encoding for 21 minutes */
8113		sc = 252;
8114	else if (t <= (11 * 30 * 60))
8115		sc = (t - 1) / (30 * 60) + 241;
8116	else
8117		sc = 253;
8118
8119	retval = ata_do_28bit_cmd(device,
8120	    ccb,
8121	    /*retries*/retry_count,
8122	    /*flags*/CAM_DIR_NONE,
8123	    /*protocol*/AP_PROTO_NON_DATA,
8124	    /*tag_action*/MSG_SIMPLE_Q_TAG,
8125	    /*command*/cmd,
8126	    /*features*/0,
8127	    /*lba*/0,
8128	    /*sector_count*/sc,
8129	    /*data_ptr*/NULL,
8130	    /*dxfer_len*/0,
8131	    /*timeout*/timeout ? timeout : 30 * 1000,
8132	    /*quiet*/1);
8133
8134	cam_freeccb(ccb);
8135	return (retval);
8136}
8137
8138static int
8139ataaxm(struct cam_device *device, int argc, char **argv,
8140		 char *combinedopt, int retry_count, int timeout)
8141{
8142	union ccb *ccb;
8143	int retval = 0;
8144	int l = -1;
8145	int c;
8146	u_char cmd, sc;
8147
8148	ccb = cam_getccb(device);
8149
8150	if (ccb == NULL) {
8151		warnx("%s: error allocating ccb", __func__);
8152		return (1);
8153	}
8154
8155	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8156		switch (c) {
8157		case 'l':
8158			l = atoi(optarg);
8159			break;
8160		default:
8161			break;
8162		}
8163	}
8164	sc = 0;
8165	if (strcmp(argv[1], "apm") == 0) {
8166		if (l == -1)
8167			cmd = 0x85;
8168		else {
8169			cmd = 0x05;
8170			sc = l;
8171		}
8172	} else /* aam */ {
8173		if (l == -1)
8174			cmd = 0xC2;
8175		else {
8176			cmd = 0x42;
8177			sc = l;
8178		}
8179	}
8180
8181	retval = ata_do_28bit_cmd(device,
8182	    ccb,
8183	    /*retries*/retry_count,
8184	    /*flags*/CAM_DIR_NONE,
8185	    /*protocol*/AP_PROTO_NON_DATA,
8186	    /*tag_action*/MSG_SIMPLE_Q_TAG,
8187	    /*command*/ATA_SETFEATURES,
8188	    /*features*/cmd,
8189	    /*lba*/0,
8190	    /*sector_count*/sc,
8191	    /*data_ptr*/NULL,
8192	    /*dxfer_len*/0,
8193	    /*timeout*/timeout ? timeout : 30 * 1000,
8194	    /*quiet*/1);
8195
8196	cam_freeccb(ccb);
8197	return (retval);
8198}
8199
8200int
8201scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8202	       int show_sa_errors, int sa_set, int service_action,
8203	       int timeout_desc, int retry_count, int timeout, int verbosemode,
8204	       uint32_t *fill_len, uint8_t **data_ptr)
8205{
8206	union ccb *ccb = NULL;
8207	uint8_t *buf = NULL;
8208	uint32_t alloc_len = 0, num_opcodes;
8209	uint32_t valid_len = 0;
8210	uint32_t avail_len = 0;
8211	struct scsi_report_supported_opcodes_all *all_hdr;
8212	struct scsi_report_supported_opcodes_one *one;
8213	int options = 0;
8214	int retval = 0;
8215
8216	/*
8217	 * Make it clear that we haven't yet allocated or filled anything.
8218	 */
8219	*fill_len = 0;
8220	*data_ptr = NULL;
8221
8222	ccb = cam_getccb(device);
8223	if (ccb == NULL) {
8224		warnx("couldn't allocate CCB");
8225		retval = 1;
8226		goto bailout;
8227	}
8228
8229	/* cam_getccb cleans up the header, caller has to zero the payload */
8230	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8231
8232	if (opcode_set != 0) {
8233		options |= RSO_OPTIONS_OC;
8234		num_opcodes = 1;
8235		alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8236	} else {
8237		num_opcodes = 256;
8238		alloc_len = sizeof(*all_hdr) + (num_opcodes *
8239		    sizeof(struct scsi_report_supported_opcodes_descr));
8240	}
8241
8242	if (timeout_desc != 0) {
8243		options |= RSO_RCTD;
8244		alloc_len += num_opcodes *
8245		    sizeof(struct scsi_report_supported_opcodes_timeout);
8246	}
8247
8248	if (sa_set != 0) {
8249		options |= RSO_OPTIONS_OC_SA;
8250		if (show_sa_errors != 0)
8251			options &= ~RSO_OPTIONS_OC;
8252	}
8253
8254retry_alloc:
8255	if (buf != NULL) {
8256		free(buf);
8257		buf = NULL;
8258	}
8259
8260	buf = malloc(alloc_len);
8261	if (buf == NULL) {
8262		warn("Unable to allocate %u bytes", alloc_len);
8263		retval = 1;
8264		goto bailout;
8265	}
8266	bzero(buf, alloc_len);
8267
8268	scsi_report_supported_opcodes(&ccb->csio,
8269				      /*retries*/ retry_count,
8270				      /*cbfcnp*/ NULL,
8271				      /*tag_action*/ MSG_SIMPLE_Q_TAG,
8272				      /*options*/ options,
8273				      /*req_opcode*/ opcode,
8274				      /*req_service_action*/ service_action,
8275				      /*data_ptr*/ buf,
8276				      /*dxfer_len*/ alloc_len,
8277				      /*sense_len*/ SSD_FULL_SIZE,
8278				      /*timeout*/ timeout ? timeout : 10000);
8279
8280	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8281
8282	if (retry_count != 0)
8283		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
8284
8285	if (cam_send_ccb(device, ccb) < 0) {
8286		perror("error sending REPORT SUPPORTED OPERATION CODES");
8287		retval = 1;
8288		goto bailout;
8289	}
8290
8291	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8292		if (verbosemode != 0)
8293			cam_error_print(device, ccb, CAM_ESF_ALL,
8294					CAM_EPF_ALL, stderr);
8295
8296		retval = 1;
8297		goto bailout;
8298	}
8299
8300	valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
8301
8302	if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
8303	 && (valid_len >= sizeof(*all_hdr))) {
8304		all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
8305		avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
8306	} else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
8307		&& (valid_len >= sizeof(*one))) {
8308		uint32_t cdb_length;
8309
8310		one = (struct scsi_report_supported_opcodes_one *)buf;
8311		cdb_length = scsi_2btoul(one->cdb_length);
8312		avail_len = sizeof(*one) + cdb_length;
8313		if (one->support & RSO_ONE_CTDP) {
8314			struct scsi_report_supported_opcodes_timeout *td;
8315
8316			td = (struct scsi_report_supported_opcodes_timeout *)
8317			    &buf[avail_len];
8318			if (valid_len >= (avail_len + sizeof(td->length))) {
8319				avail_len += scsi_2btoul(td->length) +
8320				    sizeof(td->length);
8321			} else {
8322				avail_len += sizeof(*td);
8323			}
8324		}
8325	}
8326
8327	/*
8328	 * avail_len could be zero if we didn't get enough data back from
8329	 * thet target to determine
8330	 */
8331	if ((avail_len != 0)
8332	 && (avail_len > valid_len)) {
8333		alloc_len = avail_len;
8334		goto retry_alloc;
8335	}
8336
8337	*fill_len = valid_len;
8338	*data_ptr = buf;
8339bailout:
8340	if (retval != 0)
8341		free(buf);
8342
8343	cam_freeccb(ccb);
8344
8345	return (retval);
8346}
8347
8348static int
8349scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
8350		   int req_sa, uint8_t *buf, uint32_t valid_len)
8351{
8352	struct scsi_report_supported_opcodes_one *one;
8353	struct scsi_report_supported_opcodes_timeout *td;
8354	uint32_t cdb_len = 0, td_len = 0;
8355	const char *op_desc = NULL;
8356	unsigned int i;
8357	int retval = 0;
8358
8359	one = (struct scsi_report_supported_opcodes_one *)buf;
8360
8361	/*
8362	 * If we don't have the full single opcode descriptor, no point in
8363	 * continuing.
8364	 */
8365	if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8366	    cdb_length)) {
8367		warnx("Only %u bytes returned, not enough to verify support",
8368		      valid_len);
8369		retval = 1;
8370		goto bailout;
8371	}
8372
8373	op_desc = scsi_op_desc(req_opcode, &device->inq_data);
8374
8375	printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
8376	       req_opcode);
8377	if (sa_set != 0)
8378		printf(", SA 0x%x", req_sa);
8379	printf(": ");
8380
8381	switch (one->support & RSO_ONE_SUP_MASK) {
8382	case RSO_ONE_SUP_UNAVAIL:
8383		printf("No command support information currently available\n");
8384		break;
8385	case RSO_ONE_SUP_NOT_SUP:
8386		printf("Command not supported\n");
8387		retval = 1;
8388		goto bailout;
8389		break; /*NOTREACHED*/
8390	case RSO_ONE_SUP_AVAIL:
8391		printf("Command is supported, complies with a SCSI standard\n");
8392		break;
8393	case RSO_ONE_SUP_VENDOR:
8394		printf("Command is supported, vendor-specific "
8395		       "implementation\n");
8396		break;
8397	default:
8398		printf("Unknown command support flags 0x%#x\n",
8399		       one->support & RSO_ONE_SUP_MASK);
8400		break;
8401	}
8402
8403	/*
8404	 * If we don't have the CDB length, it isn't exactly an error, the
8405	 * command probably isn't supported.
8406	 */
8407	if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8408	    cdb_usage))
8409		goto bailout;
8410
8411	cdb_len = scsi_2btoul(one->cdb_length);
8412
8413	/*
8414	 * If our valid data doesn't include the full reported length,
8415	 * return.  The caller should have detected this and adjusted his
8416	 * allocation length to get all of the available data.
8417	 */
8418	if (valid_len < sizeof(*one) + cdb_len) {
8419		retval = 1;
8420		goto bailout;
8421	}
8422
8423	/*
8424	 * If all we have is the opcode, there is no point in printing out
8425	 * the usage bitmap.
8426	 */
8427	if (cdb_len <= 1) {
8428		retval = 1;
8429		goto bailout;
8430	}
8431
8432	printf("CDB usage bitmap:");
8433	for (i = 0; i < cdb_len; i++) {
8434		printf(" %02x", one->cdb_usage[i]);
8435	}
8436	printf("\n");
8437
8438	/*
8439	 * If we don't have a timeout descriptor, we're done.
8440	 */
8441	if ((one->support & RSO_ONE_CTDP) == 0)
8442		goto bailout;
8443
8444	/*
8445	 * If we don't have enough valid length to include the timeout
8446	 * descriptor length, we're done.
8447	 */
8448	if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
8449		goto bailout;
8450
8451	td = (struct scsi_report_supported_opcodes_timeout *)
8452	    &buf[sizeof(*one) + cdb_len];
8453	td_len = scsi_2btoul(td->length);
8454	td_len += sizeof(td->length);
8455
8456	/*
8457	 * If we don't have the full timeout descriptor, we're done.
8458	 */
8459	if (td_len < sizeof(*td))
8460		goto bailout;
8461
8462	/*
8463	 * If we don't have enough valid length to contain the full timeout
8464	 * descriptor, we're done.
8465	 */
8466	if (valid_len < (sizeof(*one) + cdb_len + td_len))
8467		goto bailout;
8468
8469	printf("Timeout information:\n");
8470	printf("Command-specific:    0x%02x\n", td->cmd_specific);
8471	printf("Nominal timeout:     %u seconds\n",
8472	       scsi_4btoul(td->nominal_time));
8473	printf("Recommended timeout: %u seconds\n",
8474	       scsi_4btoul(td->recommended_time));
8475
8476bailout:
8477	return (retval);
8478}
8479
8480static int
8481scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
8482		 uint32_t valid_len)
8483{
8484	struct scsi_report_supported_opcodes_all *hdr;
8485	struct scsi_report_supported_opcodes_descr *desc;
8486	uint32_t avail_len = 0, used_len = 0;
8487	uint8_t *cur_ptr;
8488	int retval = 0;
8489
8490	if (valid_len < sizeof(*hdr)) {
8491		warnx("%s: not enough returned data (%u bytes) opcode list",
8492		      __func__, valid_len);
8493		retval = 1;
8494		goto bailout;
8495	}
8496	hdr = (struct scsi_report_supported_opcodes_all *)buf;
8497	avail_len = scsi_4btoul(hdr->length);
8498	avail_len += sizeof(hdr->length);
8499	/*
8500	 * Take the lesser of the amount of data the drive claims is
8501	 * available, and the amount of data the HBA says was returned.
8502	 */
8503	avail_len = MIN(avail_len, valid_len);
8504
8505	used_len = sizeof(hdr->length);
8506
8507	printf("%-6s %4s %8s ",
8508	       "Opcode", "SA", "CDB len" );
8509
8510	if (td_req != 0)
8511		printf("%5s %6s %6s ", "CS", "Nom", "Rec");
8512	printf(" Description\n");
8513
8514	while ((avail_len - used_len) > sizeof(*desc)) {
8515		struct scsi_report_supported_opcodes_timeout *td;
8516		uint32_t td_len;
8517		const char *op_desc = NULL;
8518
8519		cur_ptr = &buf[used_len];
8520		desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
8521
8522		op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
8523		if (op_desc == NULL)
8524			op_desc = "UNKNOWN";
8525
8526		printf("0x%02x   %#4x %8u ", desc->opcode,
8527		       scsi_2btoul(desc->service_action),
8528		       scsi_2btoul(desc->cdb_length));
8529
8530		used_len += sizeof(*desc);
8531
8532		if ((desc->flags & RSO_CTDP) == 0) {
8533			printf(" %s\n", op_desc);
8534			continue;
8535		}
8536
8537		/*
8538		 * If we don't have enough space to fit a timeout
8539		 * descriptor, then we're done.
8540		 */
8541		if (avail_len - used_len < sizeof(*td)) {
8542			used_len = avail_len;
8543			printf(" %s\n", op_desc);
8544			continue;
8545		}
8546		cur_ptr = &buf[used_len];
8547		td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
8548		td_len = scsi_2btoul(td->length);
8549		td_len += sizeof(td->length);
8550
8551		used_len += td_len;
8552		/*
8553		 * If the given timeout descriptor length is less than what
8554		 * we understand, skip it.
8555		 */
8556		if (td_len < sizeof(*td)) {
8557			printf(" %s\n", op_desc);
8558			continue;
8559		}
8560
8561		printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
8562		       scsi_4btoul(td->nominal_time),
8563		       scsi_4btoul(td->recommended_time), op_desc);
8564	}
8565bailout:
8566	return (retval);
8567}
8568
8569static int
8570scsiopcodes(struct cam_device *device, int argc, char **argv,
8571	    char *combinedopt, int retry_count, int timeout, int verbosemode)
8572{
8573	int c;
8574	uint32_t opcode = 0, service_action = 0;
8575	int td_set = 0, opcode_set = 0, sa_set = 0;
8576	int show_sa_errors = 1;
8577	uint32_t valid_len = 0;
8578	uint8_t *buf = NULL;
8579	char *endptr;
8580	int retval = 0;
8581
8582	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8583		switch (c) {
8584		case 'N':
8585			show_sa_errors = 0;
8586			break;
8587		case 'o':
8588			opcode = strtoul(optarg, &endptr, 0);
8589			if (*endptr != '\0') {
8590				warnx("Invalid opcode \"%s\", must be a number",
8591				      optarg);
8592				retval = 1;
8593				goto bailout;
8594			}
8595			if (opcode > 0xff) {
8596				warnx("Invalid opcode 0x%#x, must be between"
8597				      "0 and 0xff inclusive", opcode);
8598				retval = 1;
8599				goto bailout;
8600			}
8601			opcode_set = 1;
8602			break;
8603		case 's':
8604			service_action = strtoul(optarg, &endptr, 0);
8605			if (*endptr != '\0') {
8606				warnx("Invalid service action \"%s\", must "
8607				      "be a number", optarg);
8608				retval = 1;
8609				goto bailout;
8610			}
8611			if (service_action > 0xffff) {
8612				warnx("Invalid service action 0x%#x, must "
8613				      "be between 0 and 0xffff inclusive",
8614				      service_action);
8615				retval = 1;
8616			}
8617			sa_set = 1;
8618			break;
8619		case 'T':
8620			td_set = 1;
8621			break;
8622		default:
8623			break;
8624		}
8625	}
8626
8627	if ((sa_set != 0)
8628	 && (opcode_set == 0)) {
8629		warnx("You must specify an opcode with -o if a service "
8630		      "action is given");
8631		retval = 1;
8632		goto bailout;
8633	}
8634	retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
8635				sa_set, service_action, td_set, retry_count,
8636				timeout, verbosemode, &valid_len, &buf);
8637	if (retval != 0)
8638		goto bailout;
8639
8640	if ((opcode_set != 0)
8641	 || (sa_set != 0)) {
8642		retval = scsiprintoneopcode(device, opcode, sa_set,
8643					    service_action, buf, valid_len);
8644	} else {
8645		retval = scsiprintopcodes(device, td_set, buf, valid_len);
8646	}
8647
8648bailout:
8649	free(buf);
8650
8651	return (retval);
8652}
8653
8654#endif /* MINIMALISTIC */
8655
8656static int
8657scsireprobe(struct cam_device *device)
8658{
8659	union ccb *ccb;
8660	int retval = 0;
8661
8662	ccb = cam_getccb(device);
8663
8664	if (ccb == NULL) {
8665		warnx("%s: error allocating ccb", __func__);
8666		return (1);
8667	}
8668
8669	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8670
8671	ccb->ccb_h.func_code = XPT_REPROBE_LUN;
8672
8673	if (cam_send_ccb(device, ccb) < 0) {
8674		warn("error sending XPT_REPROBE_LUN CCB");
8675		retval = 1;
8676		goto bailout;
8677	}
8678
8679	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8680		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
8681		retval = 1;
8682		goto bailout;
8683	}
8684
8685bailout:
8686	cam_freeccb(ccb);
8687
8688	return (retval);
8689}
8690
8691void
8692usage(int printlong)
8693{
8694
8695	fprintf(printlong ? stdout : stderr,
8696"usage:  camcontrol <command>  [device id][generic args][command args]\n"
8697"        camcontrol devlist    [-b] [-v]\n"
8698#ifndef MINIMALISTIC
8699"        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8700"        camcontrol tur        [dev_id][generic args]\n"
8701"        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
8702"        camcontrol identify   [dev_id][generic args] [-v]\n"
8703"        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8704"        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8705"                              [-q] [-s]\n"
8706"        camcontrol start      [dev_id][generic args]\n"
8707"        camcontrol stop       [dev_id][generic args]\n"
8708"        camcontrol load       [dev_id][generic args]\n"
8709"        camcontrol eject      [dev_id][generic args]\n"
8710"        camcontrol reprobe    [dev_id][generic args]\n"
8711#endif /* MINIMALISTIC */
8712"        camcontrol rescan     <all | bus[:target:lun]>\n"
8713"        camcontrol reset      <all | bus[:target:lun]>\n"
8714#ifndef MINIMALISTIC
8715"        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
8716"                              [-q][-s][-S offset][-X]\n"
8717"        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
8718"                              [-P pagectl][-e | -b][-d]\n"
8719"        camcontrol cmd        [dev_id][generic args]\n"
8720"                              <-a cmd [args] | -c cmd [args]>\n"
8721"                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8722"        camcontrol smpcmd     [dev_id][generic args]\n"
8723"                              <-r len fmt [args]> <-R len fmt [args]>\n"
8724"        camcontrol smprg      [dev_id][generic args][-l]\n"
8725"        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
8726"                              [-o operation][-d name][-m rate][-M rate]\n"
8727"                              [-T pp_timeout][-a enable|disable]\n"
8728"                              [-A enable|disable][-s enable|disable]\n"
8729"                              [-S enable|disable]\n"
8730"        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8731"        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8732"        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
8733"                              <all|bus[:target[:lun]]|off>\n"
8734"        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
8735"        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
8736"                              [-D <enable|disable>][-M mode][-O offset]\n"
8737"                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
8738"                              [-U][-W bus_width]\n"
8739"        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
8740"        camcontrol sanitize   [dev_id][generic args]\n"
8741"                              [-a overwrite|block|crypto|exitfailure]\n"
8742"                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8743"                              [-y]\n"
8744"        camcontrol idle       [dev_id][generic args][-t time]\n"
8745"        camcontrol standby    [dev_id][generic args][-t time]\n"
8746"        camcontrol sleep      [dev_id][generic args]\n"
8747"        camcontrol apm        [dev_id][generic args][-l level]\n"
8748"        camcontrol aam        [dev_id][generic args][-l level]\n"
8749"        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
8750"                              [-s][-y]\n"
8751"        camcontrol security   [dev_id][generic args]\n"
8752"                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8753"                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8754"                              [-U <user|master>] [-y]\n"
8755"        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8756"                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
8757"        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
8758"                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8759"                              [-s scope][-S][-T type][-U]\n"
8760"        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
8761"                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
8762"                              [-p part][-s start][-T type][-V vol]\n"
8763"        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
8764"                              [-N][-T]\n"
8765#endif /* MINIMALISTIC */
8766"        camcontrol help\n");
8767	if (!printlong)
8768		return;
8769#ifndef MINIMALISTIC
8770	fprintf(stdout,
8771"Specify one of the following options:\n"
8772"devlist     list all CAM devices\n"
8773"periphlist  list all CAM peripheral drivers attached to a device\n"
8774"tur         send a test unit ready to the named device\n"
8775"inquiry     send a SCSI inquiry command to the named device\n"
8776"identify    send a ATA identify command to the named device\n"
8777"reportluns  send a SCSI report luns command to the device\n"
8778"readcap     send a SCSI read capacity command to the device\n"
8779"start       send a Start Unit command to the device\n"
8780"stop        send a Stop Unit command to the device\n"
8781"load        send a Start Unit command to the device with the load bit set\n"
8782"eject       send a Stop Unit command to the device with the eject bit set\n"
8783"reprobe     update capacity information of the given device\n"
8784"rescan      rescan all busses, the given bus, or bus:target:lun\n"
8785"reset       reset all busses, the given bus, or bus:target:lun\n"
8786"defects     read the defect list of the specified device\n"
8787"modepage    display or edit (-e) the given mode page\n"
8788"cmd         send the given SCSI command, may need -i or -o as well\n"
8789"smpcmd      send the given SMP command, requires -o and -i\n"
8790"smprg       send the SMP Report General command\n"
8791"smppc       send the SMP PHY Control command, requires -p\n"
8792"smpphylist  display phys attached to a SAS expander\n"
8793"smpmaninfo  send the SMP Report Manufacturer Info command\n"
8794"debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
8795"tags        report or set the number of transaction slots for a device\n"
8796"negotiate   report or set device negotiation parameters\n"
8797"format      send the SCSI FORMAT UNIT command to the named device\n"
8798"sanitize    send the SCSI SANITIZE command to the named device\n"
8799"idle        send the ATA IDLE command to the named device\n"
8800"standby     send the ATA STANDBY command to the named device\n"
8801"sleep       send the ATA SLEEP command to the named device\n"
8802"fwdownload  program firmware of the named device with the given image\n"
8803"security    report or send ATA security commands to the named device\n"
8804"persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8805"attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
8806"opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
8807"help        this message\n"
8808"Device Identifiers:\n"
8809"bus:target        specify the bus and target, lun defaults to 0\n"
8810"bus:target:lun    specify the bus, target and lun\n"
8811"deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
8812"Generic arguments:\n"
8813"-v                be verbose, print out sense information\n"
8814"-t timeout        command timeout in seconds, overrides default timeout\n"
8815"-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
8816"-u unit           specify unit number, e.g. \"0\", \"5\"\n"
8817"-E                have the kernel attempt to perform SCSI error recovery\n"
8818"-C count          specify the SCSI command retry count (needs -E to work)\n"
8819"modepage arguments:\n"
8820"-l                list all available mode pages\n"
8821"-m page           specify the mode page to view or edit\n"
8822"-e                edit the specified mode page\n"
8823"-b                force view to binary mode\n"
8824"-d                disable block descriptors for mode sense\n"
8825"-P pgctl          page control field 0-3\n"
8826"defects arguments:\n"
8827"-f format         specify defect list format (block, bfi or phys)\n"
8828"-G                get the grown defect list\n"
8829"-P                get the permanent defect list\n"
8830"inquiry arguments:\n"
8831"-D                get the standard inquiry data\n"
8832"-S                get the serial number\n"
8833"-R                get the transfer rate, etc.\n"
8834"reportluns arguments:\n"
8835"-c                only report a count of available LUNs\n"
8836"-l                only print out luns, and not a count\n"
8837"-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
8838"readcap arguments\n"
8839"-b                only report the blocksize\n"
8840"-h                human readable device size, base 2\n"
8841"-H                human readable device size, base 10\n"
8842"-N                print the number of blocks instead of last block\n"
8843"-q                quiet, print numbers only\n"
8844"-s                only report the last block/device size\n"
8845"cmd arguments:\n"
8846"-c cdb [args]     specify the SCSI CDB\n"
8847"-i len fmt        specify input data and input data format\n"
8848"-o len fmt [args] specify output data and output data fmt\n"
8849"smpcmd arguments:\n"
8850"-r len fmt [args] specify the SMP command to be sent\n"
8851"-R len fmt [args] specify SMP response format\n"
8852"smprg arguments:\n"
8853"-l                specify the long response format\n"
8854"smppc arguments:\n"
8855"-p phy            specify the PHY to operate on\n"
8856"-l                specify the long request/response format\n"
8857"-o operation      specify the phy control operation\n"
8858"-d name           set the attached device name\n"
8859"-m rate           set the minimum physical link rate\n"
8860"-M rate           set the maximum physical link rate\n"
8861"-T pp_timeout     set the partial pathway timeout value\n"
8862"-a enable|disable enable or disable SATA slumber\n"
8863"-A enable|disable enable or disable SATA partial phy power\n"
8864"-s enable|disable enable or disable SAS slumber\n"
8865"-S enable|disable enable or disable SAS partial phy power\n"
8866"smpphylist arguments:\n"
8867"-l                specify the long response format\n"
8868"-q                only print phys with attached devices\n"
8869"smpmaninfo arguments:\n"
8870"-l                specify the long response format\n"
8871"debug arguments:\n"
8872"-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
8873"-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
8874"-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
8875"-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
8876"tags arguments:\n"
8877"-N tags           specify the number of tags to use for this device\n"
8878"-q                be quiet, don't report the number of tags\n"
8879"-v                report a number of tag-related parameters\n"
8880"negotiate arguments:\n"
8881"-a                send a test unit ready after negotiation\n"
8882"-c                report/set current negotiation settings\n"
8883"-D <arg>          \"enable\" or \"disable\" disconnection\n"
8884"-M mode           set ATA mode\n"
8885"-O offset         set command delay offset\n"
8886"-q                be quiet, don't report anything\n"
8887"-R syncrate       synchronization rate in MHz\n"
8888"-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
8889"-U                report/set user negotiation settings\n"
8890"-W bus_width      set the bus width in bits (8, 16 or 32)\n"
8891"-v                also print a Path Inquiry CCB for the controller\n"
8892"format arguments:\n"
8893"-q                be quiet, don't print status messages\n"
8894"-r                run in report only mode\n"
8895"-w                don't send immediate format command\n"
8896"-y                don't ask any questions\n"
8897"sanitize arguments:\n"
8898"-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
8899"-c passes         overwrite passes to perform (1 to 31)\n"
8900"-I                invert overwrite pattern after each pass\n"
8901"-P pattern        path to overwrite pattern file\n"
8902"-q                be quiet, don't print status messages\n"
8903"-r                run in report only mode\n"
8904"-U                run operation in unrestricted completion exit mode\n"
8905"-w                don't send immediate sanitize command\n"
8906"-y                don't ask any questions\n"
8907"idle/standby arguments:\n"
8908"-t <arg>          number of seconds before respective state.\n"
8909"fwdownload arguments:\n"
8910"-f fw_image       path to firmware image file\n"
8911"-q                don't print informational messages, only errors\n"
8912"-s                run in simulation mode\n"
8913"-v                print info for every firmware segment sent to device\n"
8914"-y                don't ask any questions\n"
8915"security arguments:\n"
8916"-d pwd            disable security using the given password for the selected\n"
8917"                  user\n"
8918"-e pwd            erase the device using the given pwd for the selected user\n"
8919"-f                freeze the security configuration of the specified device\n"
8920"-h pwd            enhanced erase the device using the given pwd for the\n"
8921"                  selected user\n"
8922"-k pwd            unlock the device using the given pwd for the selected\n"
8923"                  user\n"
8924"-l <high|maximum> specifies which security level to set: high or maximum\n"
8925"-q                be quiet, do not print any status messages\n"
8926"-s pwd            password the device (enable security) using the given\n"
8927"                  pwd for the selected user\n"
8928"-T timeout        overrides the timeout (seconds) used for erase operation\n"
8929"-U <user|master>  specifies which user to set: user or master\n"
8930"-y                don't ask any questions\n"
8931"hpa arguments:\n"
8932"-f                freeze the HPA configuration of the device\n"
8933"-l                lock the HPA configuration of the device\n"
8934"-P                make the HPA max sectors persist\n"
8935"-p pwd            Set the HPA configuration password required for unlock\n"
8936"                  calls\n"
8937"-q                be quiet, do not print any status messages\n"
8938"-s sectors        configures the maximum user accessible sectors of the\n"
8939"                  device\n"
8940"-U pwd            unlock the HPA configuration of the device\n"
8941"-y                don't ask any questions\n"
8942"persist arguments:\n"
8943"-i action         specify read_keys, read_reservation, report_cap, or\n"
8944"                  read_full_status\n"
8945"-o action         specify register, register_ignore, reserve, release,\n"
8946"                  clear, preempt, preempt_abort, register_move, replace_lost\n"
8947"-a                set the All Target Ports (ALL_TG_PT) bit\n"
8948"-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8949"-k key            specify the Reservation Key\n"
8950"-K sa_key         specify the Service Action Reservation Key\n"
8951"-p                set the Activate Persist Through Power Loss bit\n"
8952"-R rtp            specify the Relative Target Port\n"
8953"-s scope          specify the scope: lun, extent, element or a number\n"
8954"-S                specify Transport ID for register, requires -I\n"
8955"-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8956"                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8957"-U                unregister the current initiator for register_move\n"
8958"attrib arguments:\n"
8959"-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
8960"                  supp_attr\n"
8961"-w attr           specify an attribute to write, one -w argument per attr\n"
8962"-a attr_num       only display this attribute number\n"
8963"-c                get cached attributes\n"
8964"-e elem_addr      request attributes for the given element in a changer\n"
8965"-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
8966"                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
8967"                  field_none, field_desc, field_num, field_size, field_rw\n"
8968"-p partition      request attributes for the given partition\n"
8969"-s start_attr     request attributes starting at the given number\n"
8970"-T elem_type      specify the element type (used with -e)\n"
8971"-V logical_vol    specify the logical volume ID\n"
8972"opcodes arguments:\n"
8973"-o opcode         specify the individual opcode to list\n"
8974"-s service_action specify the service action for the opcode\n"
8975"-N                do not return SCSI error for unsupported SA\n"
8976"-T                request nominal and recommended timeout values\n"
8977);
8978#endif /* MINIMALISTIC */
8979}
8980
8981int
8982main(int argc, char **argv)
8983{
8984	int c;
8985	char *device = NULL;
8986	int unit = 0;
8987	struct cam_device *cam_dev = NULL;
8988	int timeout = 0, retry_count = 1;
8989	camcontrol_optret optreturn;
8990	char *tstr;
8991	const char *mainopt = "C:En:t:u:v";
8992	const char *subopt = NULL;
8993	char combinedopt[256];
8994	int error = 0, optstart = 2;
8995	int devopen = 1;
8996#ifndef MINIMALISTIC
8997	path_id_t bus;
8998	target_id_t target;
8999	lun_id_t lun;
9000#endif /* MINIMALISTIC */
9001
9002	cmdlist = CAM_CMD_NONE;
9003	arglist = CAM_ARG_NONE;
9004
9005	if (argc < 2) {
9006		usage(0);
9007		exit(1);
9008	}
9009
9010	/*
9011	 * Get the base option.
9012	 */
9013	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
9014
9015	if (optreturn == CC_OR_AMBIGUOUS) {
9016		warnx("ambiguous option %s", argv[1]);
9017		usage(0);
9018		exit(1);
9019	} else if (optreturn == CC_OR_NOT_FOUND) {
9020		warnx("option %s not found", argv[1]);
9021		usage(0);
9022		exit(1);
9023	}
9024
9025	/*
9026	 * Ahh, getopt(3) is a pain.
9027	 *
9028	 * This is a gross hack.  There really aren't many other good
9029	 * options (excuse the pun) for parsing options in a situation like
9030	 * this.  getopt is kinda braindead, so you end up having to run
9031	 * through the options twice, and give each invocation of getopt
9032	 * the option string for the other invocation.
9033	 *
9034	 * You would think that you could just have two groups of options.
9035	 * The first group would get parsed by the first invocation of
9036	 * getopt, and the second group would get parsed by the second
9037	 * invocation of getopt.  It doesn't quite work out that way.  When
9038	 * the first invocation of getopt finishes, it leaves optind pointing
9039	 * to the argument _after_ the first argument in the second group.
9040	 * So when the second invocation of getopt comes around, it doesn't
9041	 * recognize the first argument it gets and then bails out.
9042	 *
9043	 * A nice alternative would be to have a flag for getopt that says
9044	 * "just keep parsing arguments even when you encounter an unknown
9045	 * argument", but there isn't one.  So there's no real clean way to
9046	 * easily parse two sets of arguments without having one invocation
9047	 * of getopt know about the other.
9048	 *
9049	 * Without this hack, the first invocation of getopt would work as
9050	 * long as the generic arguments are first, but the second invocation
9051	 * (in the subfunction) would fail in one of two ways.  In the case
9052	 * where you don't set optreset, it would fail because optind may be
9053	 * pointing to the argument after the one it should be pointing at.
9054	 * In the case where you do set optreset, and reset optind, it would
9055	 * fail because getopt would run into the first set of options, which
9056	 * it doesn't understand.
9057	 *
9058	 * All of this would "sort of" work if you could somehow figure out
9059	 * whether optind had been incremented one option too far.  The
9060	 * mechanics of that, however, are more daunting than just giving
9061	 * both invocations all of the expect options for either invocation.
9062	 *
9063	 * Needless to say, I wouldn't mind if someone invented a better
9064	 * (non-GPL!) command line parsing interface than getopt.  I
9065	 * wouldn't mind if someone added more knobs to getopt to make it
9066	 * work better.  Who knows, I may talk myself into doing it someday,
9067	 * if the standards weenies let me.  As it is, it just leads to
9068	 * hackery like this and causes people to avoid it in some cases.
9069	 *
9070	 * KDM, September 8th, 1998
9071	 */
9072	if (subopt != NULL)
9073		sprintf(combinedopt, "%s%s", mainopt, subopt);
9074	else
9075		sprintf(combinedopt, "%s", mainopt);
9076
9077	/*
9078	 * For these options we do not parse optional device arguments and
9079	 * we do not open a passthrough device.
9080	 */
9081	if ((cmdlist == CAM_CMD_RESCAN)
9082	 || (cmdlist == CAM_CMD_RESET)
9083	 || (cmdlist == CAM_CMD_DEVTREE)
9084	 || (cmdlist == CAM_CMD_USAGE)
9085	 || (cmdlist == CAM_CMD_DEBUG))
9086		devopen = 0;
9087
9088#ifndef MINIMALISTIC
9089	if ((devopen == 1)
9090	 && (argc > 2 && argv[2][0] != '-')) {
9091		char name[30];
9092		int rv;
9093
9094		if (isdigit(argv[2][0])) {
9095			/* device specified as bus:target[:lun] */
9096			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9097			if (rv < 2)
9098				errx(1, "numeric device specification must "
9099				     "be either bus:target, or "
9100				     "bus:target:lun");
9101			/* default to 0 if lun was not specified */
9102			if ((arglist & CAM_ARG_LUN) == 0) {
9103				lun = 0;
9104				arglist |= CAM_ARG_LUN;
9105			}
9106			optstart++;
9107		} else {
9108			if (cam_get_device(argv[2], name, sizeof name, &unit)
9109			    == -1)
9110				errx(1, "%s", cam_errbuf);
9111			device = strdup(name);
9112			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9113			optstart++;
9114		}
9115	}
9116#endif /* MINIMALISTIC */
9117	/*
9118	 * Start getopt processing at argv[2/3], since we've already
9119	 * accepted argv[1..2] as the command name, and as a possible
9120	 * device name.
9121	 */
9122	optind = optstart;
9123
9124	/*
9125	 * Now we run through the argument list looking for generic
9126	 * options, and ignoring options that possibly belong to
9127	 * subfunctions.
9128	 */
9129	while ((c = getopt(argc, argv, combinedopt))!= -1){
9130		switch(c) {
9131			case 'C':
9132				retry_count = strtol(optarg, NULL, 0);
9133				if (retry_count < 0)
9134					errx(1, "retry count %d is < 0",
9135					     retry_count);
9136				arglist |= CAM_ARG_RETRIES;
9137				break;
9138			case 'E':
9139				arglist |= CAM_ARG_ERR_RECOVER;
9140				break;
9141			case 'n':
9142				arglist |= CAM_ARG_DEVICE;
9143				tstr = optarg;
9144				while (isspace(*tstr) && (*tstr != '\0'))
9145					tstr++;
9146				device = (char *)strdup(tstr);
9147				break;
9148			case 't':
9149				timeout = strtol(optarg, NULL, 0);
9150				if (timeout < 0)
9151					errx(1, "invalid timeout %d", timeout);
9152				/* Convert the timeout from seconds to ms */
9153				timeout *= 1000;
9154				arglist |= CAM_ARG_TIMEOUT;
9155				break;
9156			case 'u':
9157				arglist |= CAM_ARG_UNIT;
9158				unit = strtol(optarg, NULL, 0);
9159				break;
9160			case 'v':
9161				arglist |= CAM_ARG_VERBOSE;
9162				break;
9163			default:
9164				break;
9165		}
9166	}
9167
9168#ifndef MINIMALISTIC
9169	/*
9170	 * For most commands we'll want to open the passthrough device
9171	 * associated with the specified device.  In the case of the rescan
9172	 * commands, we don't use a passthrough device at all, just the
9173	 * transport layer device.
9174	 */
9175	if (devopen == 1) {
9176		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
9177		 && (((arglist & CAM_ARG_DEVICE) == 0)
9178		  || ((arglist & CAM_ARG_UNIT) == 0))) {
9179			errx(1, "subcommand \"%s\" requires a valid device "
9180			     "identifier", argv[1]);
9181		}
9182
9183		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
9184				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
9185				cam_open_spec_device(device,unit,O_RDWR,NULL)))
9186		     == NULL)
9187			errx(1,"%s", cam_errbuf);
9188	}
9189#endif /* MINIMALISTIC */
9190
9191	/*
9192	 * Reset optind to 2, and reset getopt, so these routines can parse
9193	 * the arguments again.
9194	 */
9195	optind = optstart;
9196	optreset = 1;
9197
9198	switch(cmdlist) {
9199#ifndef MINIMALISTIC
9200		case CAM_CMD_DEVLIST:
9201			error = getdevlist(cam_dev);
9202			break;
9203		case CAM_CMD_HPA:
9204			error = atahpa(cam_dev, retry_count, timeout,
9205				       argc, argv, combinedopt);
9206			break;
9207#endif /* MINIMALISTIC */
9208		case CAM_CMD_DEVTREE:
9209			error = getdevtree(argc, argv, combinedopt);
9210			break;
9211#ifndef MINIMALISTIC
9212		case CAM_CMD_TUR:
9213			error = testunitready(cam_dev, retry_count, timeout, 0);
9214			break;
9215		case CAM_CMD_INQUIRY:
9216			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
9217					      retry_count, timeout);
9218			break;
9219		case CAM_CMD_IDENTIFY:
9220			error = ataidentify(cam_dev, retry_count, timeout);
9221			break;
9222		case CAM_CMD_STARTSTOP:
9223			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
9224					  arglist & CAM_ARG_EJECT, retry_count,
9225					  timeout);
9226			break;
9227#endif /* MINIMALISTIC */
9228		case CAM_CMD_RESCAN:
9229			error = dorescan_or_reset(argc, argv, 1);
9230			break;
9231		case CAM_CMD_RESET:
9232			error = dorescan_or_reset(argc, argv, 0);
9233			break;
9234#ifndef MINIMALISTIC
9235		case CAM_CMD_READ_DEFECTS:
9236			error = readdefects(cam_dev, argc, argv, combinedopt,
9237					    retry_count, timeout);
9238			break;
9239		case CAM_CMD_MODE_PAGE:
9240			modepage(cam_dev, argc, argv, combinedopt,
9241				 retry_count, timeout);
9242			break;
9243		case CAM_CMD_SCSI_CMD:
9244			error = scsicmd(cam_dev, argc, argv, combinedopt,
9245					retry_count, timeout);
9246			break;
9247		case CAM_CMD_SMP_CMD:
9248			error = smpcmd(cam_dev, argc, argv, combinedopt,
9249				       retry_count, timeout);
9250			break;
9251		case CAM_CMD_SMP_RG:
9252			error = smpreportgeneral(cam_dev, argc, argv,
9253						 combinedopt, retry_count,
9254						 timeout);
9255			break;
9256		case CAM_CMD_SMP_PC:
9257			error = smpphycontrol(cam_dev, argc, argv, combinedopt,
9258					      retry_count, timeout);
9259			break;
9260		case CAM_CMD_SMP_PHYLIST:
9261			error = smpphylist(cam_dev, argc, argv, combinedopt,
9262					   retry_count, timeout);
9263			break;
9264		case CAM_CMD_SMP_MANINFO:
9265			error = smpmaninfo(cam_dev, argc, argv, combinedopt,
9266					   retry_count, timeout);
9267			break;
9268		case CAM_CMD_DEBUG:
9269			error = camdebug(argc, argv, combinedopt);
9270			break;
9271		case CAM_CMD_TAG:
9272			error = tagcontrol(cam_dev, argc, argv, combinedopt);
9273			break;
9274		case CAM_CMD_RATE:
9275			error = ratecontrol(cam_dev, retry_count, timeout,
9276					    argc, argv, combinedopt);
9277			break;
9278		case CAM_CMD_FORMAT:
9279			error = scsiformat(cam_dev, argc, argv,
9280					   combinedopt, retry_count, timeout);
9281			break;
9282		case CAM_CMD_REPORTLUNS:
9283			error = scsireportluns(cam_dev, argc, argv,
9284					       combinedopt, retry_count,
9285					       timeout);
9286			break;
9287		case CAM_CMD_READCAP:
9288			error = scsireadcapacity(cam_dev, argc, argv,
9289						 combinedopt, retry_count,
9290						 timeout);
9291			break;
9292		case CAM_CMD_IDLE:
9293		case CAM_CMD_STANDBY:
9294		case CAM_CMD_SLEEP:
9295			error = atapm(cam_dev, argc, argv,
9296				      combinedopt, retry_count, timeout);
9297			break;
9298		case CAM_CMD_APM:
9299		case CAM_CMD_AAM:
9300			error = ataaxm(cam_dev, argc, argv,
9301				      combinedopt, retry_count, timeout);
9302			break;
9303		case CAM_CMD_SECURITY:
9304			error = atasecurity(cam_dev, retry_count, timeout,
9305					    argc, argv, combinedopt);
9306			break;
9307		case CAM_CMD_DOWNLOAD_FW:
9308			error = fwdownload(cam_dev, argc, argv, combinedopt,
9309			    arglist & CAM_ARG_VERBOSE, retry_count, timeout);
9310			break;
9311		case CAM_CMD_SANITIZE:
9312			error = scsisanitize(cam_dev, argc, argv,
9313					     combinedopt, retry_count, timeout);
9314			break;
9315		case CAM_CMD_PERSIST:
9316			error = scsipersist(cam_dev, argc, argv, combinedopt,
9317			    retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9318			    arglist & CAM_ARG_ERR_RECOVER);
9319			break;
9320		case CAM_CMD_ATTRIB:
9321			error = scsiattrib(cam_dev, argc, argv, combinedopt,
9322			    retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9323			    arglist & CAM_ARG_ERR_RECOVER);
9324			break;
9325		case CAM_CMD_OPCODES:
9326			error = scsiopcodes(cam_dev, argc, argv, combinedopt,
9327			    retry_count, timeout, arglist & CAM_ARG_VERBOSE);
9328			break;
9329		case CAM_CMD_REPROBE:
9330			error = scsireprobe(cam_dev);
9331			break;
9332
9333#endif /* MINIMALISTIC */
9334		case CAM_CMD_USAGE:
9335			usage(1);
9336			break;
9337		default:
9338			usage(0);
9339			error = 1;
9340			break;
9341	}
9342
9343	if (cam_dev != NULL)
9344		cam_close_device(cam_dev);
9345
9346	exit(error);
9347}
9348