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