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