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