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