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