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