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