camcontrol.c revision 216361
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 216361 2010-12-10 21:38:51Z ken $");
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
143struct 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
210cam_cmdmask cmdlist;
211cam_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                   %02x%02x%02x%02x\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(sense, &error_code, &sense_key, &asc, &ascq);
1911
1912		/*
1913		 * According to the SCSI spec, if the disk doesn't support
1914		 * the requested format, it will generally return a sense
1915		 * key of RECOVERED ERROR, and an additional sense code
1916		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1917		 * also check to make sure that the returned length is
1918		 * greater than 0, and then print out whatever format the
1919		 * disk gave us.
1920		 */
1921		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1922		 && (asc == 0x1c) && (ascq == 0x00)
1923		 && (returned_length > 0)) {
1924			warnx("requested defect format not available");
1925			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1926			case SRDD10_BLOCK_FORMAT:
1927				warnx("Device returned block format");
1928				break;
1929			case SRDD10_BYTES_FROM_INDEX_FORMAT:
1930				warnx("Device returned bytes from index"
1931				      " format");
1932				break;
1933			case SRDD10_PHYSICAL_SECTOR_FORMAT:
1934				warnx("Device returned physical sector format");
1935				break;
1936			default:
1937				error = 1;
1938				warnx("Device returned unknown defect"
1939				     " data format %#x", returned_format);
1940				goto defect_bailout;
1941				break; /* NOTREACHED */
1942			}
1943		} else {
1944			error = 1;
1945			warnx("Error returned from read defect data command");
1946			if (arglist & CAM_ARG_VERBOSE)
1947				cam_error_print(device, ccb, CAM_ESF_ALL,
1948						CAM_EPF_ALL, stderr);
1949			goto defect_bailout;
1950		}
1951	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1952		error = 1;
1953		warnx("Error returned from read defect data command");
1954		if (arglist & CAM_ARG_VERBOSE)
1955			cam_error_print(device, ccb, CAM_ESF_ALL,
1956					CAM_EPF_ALL, stderr);
1957		goto defect_bailout;
1958	}
1959
1960	/*
1961	 * XXX KDM  I should probably clean up the printout format for the
1962	 * disk defects.
1963	 */
1964	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1965		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1966		{
1967			struct scsi_defect_desc_phys_sector *dlist;
1968
1969			dlist = (struct scsi_defect_desc_phys_sector *)
1970				(defect_list +
1971				sizeof(struct scsi_read_defect_data_hdr_10));
1972
1973			num_returned = returned_length /
1974				sizeof(struct scsi_defect_desc_phys_sector);
1975
1976			fprintf(stderr, "Got %d defect", num_returned);
1977
1978			if ((lists_specified == 0) || (num_returned == 0)) {
1979				fprintf(stderr, "s.\n");
1980				break;
1981			} else if (num_returned == 1)
1982				fprintf(stderr, ":\n");
1983			else
1984				fprintf(stderr, "s:\n");
1985
1986			for (i = 0; i < num_returned; i++) {
1987				fprintf(stdout, "%d:%d:%d\n",
1988					scsi_3btoul(dlist[i].cylinder),
1989					dlist[i].head,
1990					scsi_4btoul(dlist[i].sector));
1991			}
1992			break;
1993		}
1994		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1995		{
1996			struct scsi_defect_desc_bytes_from_index *dlist;
1997
1998			dlist = (struct scsi_defect_desc_bytes_from_index *)
1999				(defect_list +
2000				sizeof(struct scsi_read_defect_data_hdr_10));
2001
2002			num_returned = returned_length /
2003			      sizeof(struct scsi_defect_desc_bytes_from_index);
2004
2005			fprintf(stderr, "Got %d defect", num_returned);
2006
2007			if ((lists_specified == 0) || (num_returned == 0)) {
2008				fprintf(stderr, "s.\n");
2009				break;
2010			} else if (num_returned == 1)
2011				fprintf(stderr, ":\n");
2012			else
2013				fprintf(stderr, "s:\n");
2014
2015			for (i = 0; i < num_returned; i++) {
2016				fprintf(stdout, "%d:%d:%d\n",
2017					scsi_3btoul(dlist[i].cylinder),
2018					dlist[i].head,
2019					scsi_4btoul(dlist[i].bytes_from_index));
2020			}
2021			break;
2022		}
2023		case SRDDH10_BLOCK_FORMAT:
2024		{
2025			struct scsi_defect_desc_block *dlist;
2026
2027			dlist = (struct scsi_defect_desc_block *)(defect_list +
2028				sizeof(struct scsi_read_defect_data_hdr_10));
2029
2030			num_returned = returned_length /
2031			      sizeof(struct scsi_defect_desc_block);
2032
2033			fprintf(stderr, "Got %d defect", num_returned);
2034
2035			if ((lists_specified == 0) || (num_returned == 0)) {
2036				fprintf(stderr, "s.\n");
2037				break;
2038			} else if (num_returned == 1)
2039				fprintf(stderr, ":\n");
2040			else
2041				fprintf(stderr, "s:\n");
2042
2043			for (i = 0; i < num_returned; i++)
2044				fprintf(stdout, "%u\n",
2045					scsi_4btoul(dlist[i].address));
2046			break;
2047		}
2048		default:
2049			fprintf(stderr, "Unknown defect format %d\n",
2050				returned_format & SRDDH10_DLIST_FORMAT_MASK);
2051			error = 1;
2052			break;
2053	}
2054defect_bailout:
2055
2056	if (defect_list != NULL)
2057		free(defect_list);
2058
2059	if (ccb != NULL)
2060		cam_freeccb(ccb);
2061
2062	return(error);
2063}
2064#endif /* MINIMALISTIC */
2065
2066#if 0
2067void
2068reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2069{
2070	union ccb *ccb;
2071
2072	ccb = cam_getccb(device);
2073
2074	cam_freeccb(ccb);
2075}
2076#endif
2077
2078#ifndef MINIMALISTIC
2079void
2080mode_sense(struct cam_device *device, int mode_page, int page_control,
2081	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2082{
2083	union ccb *ccb;
2084	int retval;
2085
2086	ccb = cam_getccb(device);
2087
2088	if (ccb == NULL)
2089		errx(1, "mode_sense: couldn't allocate CCB");
2090
2091	bzero(&(&ccb->ccb_h)[1],
2092	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2093
2094	scsi_mode_sense(&ccb->csio,
2095			/* retries */ retry_count,
2096			/* cbfcnp */ NULL,
2097			/* tag_action */ MSG_SIMPLE_Q_TAG,
2098			/* dbd */ dbd,
2099			/* page_code */ page_control << 6,
2100			/* page */ mode_page,
2101			/* param_buf */ data,
2102			/* param_len */ datalen,
2103			/* sense_len */ SSD_FULL_SIZE,
2104			/* timeout */ timeout ? timeout : 5000);
2105
2106	if (arglist & CAM_ARG_ERR_RECOVER)
2107		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2108
2109	/* Disable freezing the device queue */
2110	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2111
2112	if (((retval = cam_send_ccb(device, ccb)) < 0)
2113	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2114		if (arglist & CAM_ARG_VERBOSE) {
2115			cam_error_print(device, ccb, CAM_ESF_ALL,
2116					CAM_EPF_ALL, stderr);
2117		}
2118		cam_freeccb(ccb);
2119		cam_close_device(device);
2120		if (retval < 0)
2121			err(1, "error sending mode sense command");
2122		else
2123			errx(1, "error sending mode sense command");
2124	}
2125
2126	cam_freeccb(ccb);
2127}
2128
2129void
2130mode_select(struct cam_device *device, int save_pages, int retry_count,
2131	   int timeout, u_int8_t *data, int datalen)
2132{
2133	union ccb *ccb;
2134	int retval;
2135
2136	ccb = cam_getccb(device);
2137
2138	if (ccb == NULL)
2139		errx(1, "mode_select: couldn't allocate CCB");
2140
2141	bzero(&(&ccb->ccb_h)[1],
2142	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2143
2144	scsi_mode_select(&ccb->csio,
2145			 /* retries */ retry_count,
2146			 /* cbfcnp */ NULL,
2147			 /* tag_action */ MSG_SIMPLE_Q_TAG,
2148			 /* scsi_page_fmt */ 1,
2149			 /* save_pages */ save_pages,
2150			 /* param_buf */ data,
2151			 /* param_len */ datalen,
2152			 /* sense_len */ SSD_FULL_SIZE,
2153			 /* timeout */ timeout ? timeout : 5000);
2154
2155	if (arglist & CAM_ARG_ERR_RECOVER)
2156		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2157
2158	/* Disable freezing the device queue */
2159	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2160
2161	if (((retval = cam_send_ccb(device, ccb)) < 0)
2162	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2163		if (arglist & CAM_ARG_VERBOSE) {
2164			cam_error_print(device, ccb, CAM_ESF_ALL,
2165					CAM_EPF_ALL, stderr);
2166		}
2167		cam_freeccb(ccb);
2168		cam_close_device(device);
2169
2170		if (retval < 0)
2171			err(1, "error sending mode select command");
2172		else
2173			errx(1, "error sending mode select command");
2174
2175	}
2176
2177	cam_freeccb(ccb);
2178}
2179
2180void
2181modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2182	 int retry_count, int timeout)
2183{
2184	int c, mode_page = -1, page_control = 0;
2185	int binary = 0, list = 0;
2186
2187	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2188		switch(c) {
2189		case 'b':
2190			binary = 1;
2191			break;
2192		case 'd':
2193			arglist |= CAM_ARG_DBD;
2194			break;
2195		case 'e':
2196			arglist |= CAM_ARG_MODE_EDIT;
2197			break;
2198		case 'l':
2199			list = 1;
2200			break;
2201		case 'm':
2202			mode_page = strtol(optarg, NULL, 0);
2203			if (mode_page < 0)
2204				errx(1, "invalid mode page %d", mode_page);
2205			break;
2206		case 'P':
2207			page_control = strtol(optarg, NULL, 0);
2208			if ((page_control < 0) || (page_control > 3))
2209				errx(1, "invalid page control field %d",
2210				     page_control);
2211			arglist |= CAM_ARG_PAGE_CNTL;
2212			break;
2213		default:
2214			break;
2215		}
2216	}
2217
2218	if (mode_page == -1 && list == 0)
2219		errx(1, "you must specify a mode page!");
2220
2221	if (list) {
2222		mode_list(device, page_control, arglist & CAM_ARG_DBD,
2223		    retry_count, timeout);
2224	} else {
2225		mode_edit(device, mode_page, page_control,
2226		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2227		    retry_count, timeout);
2228	}
2229}
2230
2231static int
2232scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2233	int retry_count, int timeout)
2234{
2235	union ccb *ccb;
2236	u_int32_t flags = CAM_DIR_NONE;
2237	u_int8_t *data_ptr = NULL;
2238	u_int8_t cdb[20];
2239	u_int8_t atacmd[12];
2240	struct get_hook hook;
2241	int c, data_bytes = 0;
2242	int cdb_len = 0;
2243	int atacmd_len = 0;
2244	int dmacmd = 0;
2245	int fpdmacmd = 0;
2246	int need_res = 0;
2247	char *datastr = NULL, *tstr, *resstr = NULL;
2248	int error = 0;
2249	int fd_data = 0, fd_res = 0;
2250	int retval;
2251
2252	ccb = cam_getccb(device);
2253
2254	if (ccb == NULL) {
2255		warnx("scsicmd: error allocating ccb");
2256		return(1);
2257	}
2258
2259	bzero(&(&ccb->ccb_h)[1],
2260	      sizeof(union ccb) - sizeof(struct ccb_hdr));
2261
2262	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2263		switch(c) {
2264		case 'a':
2265			tstr = optarg;
2266			while (isspace(*tstr) && (*tstr != '\0'))
2267				tstr++;
2268			hook.argc = argc - optind;
2269			hook.argv = argv + optind;
2270			hook.got = 0;
2271			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2272						    iget, &hook);
2273			/*
2274			 * Increment optind by the number of arguments the
2275			 * encoding routine processed.  After each call to
2276			 * getopt(3), optind points to the argument that
2277			 * getopt should process _next_.  In this case,
2278			 * that means it points to the first command string
2279			 * argument, if there is one.  Once we increment
2280			 * this, it should point to either the next command
2281			 * line argument, or it should be past the end of
2282			 * the list.
2283			 */
2284			optind += hook.got;
2285			break;
2286		case 'c':
2287			tstr = optarg;
2288			while (isspace(*tstr) && (*tstr != '\0'))
2289				tstr++;
2290			hook.argc = argc - optind;
2291			hook.argv = argv + optind;
2292			hook.got = 0;
2293			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2294						    iget, &hook);
2295			/*
2296			 * Increment optind by the number of arguments the
2297			 * encoding routine processed.  After each call to
2298			 * getopt(3), optind points to the argument that
2299			 * getopt should process _next_.  In this case,
2300			 * that means it points to the first command string
2301			 * argument, if there is one.  Once we increment
2302			 * this, it should point to either the next command
2303			 * line argument, or it should be past the end of
2304			 * the list.
2305			 */
2306			optind += hook.got;
2307			break;
2308		case 'd':
2309			dmacmd = 1;
2310			break;
2311		case 'f':
2312			fpdmacmd = 1;
2313			break;
2314		case 'i':
2315			if (arglist & CAM_ARG_CMD_OUT) {
2316				warnx("command must either be "
2317				      "read or write, not both");
2318				error = 1;
2319				goto scsicmd_bailout;
2320			}
2321			arglist |= CAM_ARG_CMD_IN;
2322			flags = CAM_DIR_IN;
2323			data_bytes = strtol(optarg, NULL, 0);
2324			if (data_bytes <= 0) {
2325				warnx("invalid number of input bytes %d",
2326				      data_bytes);
2327				error = 1;
2328				goto scsicmd_bailout;
2329			}
2330			hook.argc = argc - optind;
2331			hook.argv = argv + optind;
2332			hook.got = 0;
2333			optind++;
2334			datastr = cget(&hook, NULL);
2335			/*
2336			 * If the user supplied "-" instead of a format, he
2337			 * wants the data to be written to stdout.
2338			 */
2339			if ((datastr != NULL)
2340			 && (datastr[0] == '-'))
2341				fd_data = 1;
2342
2343			data_ptr = (u_int8_t *)malloc(data_bytes);
2344			if (data_ptr == NULL) {
2345				warnx("can't malloc memory for data_ptr");
2346				error = 1;
2347				goto scsicmd_bailout;
2348			}
2349			break;
2350		case 'o':
2351			if (arglist & CAM_ARG_CMD_IN) {
2352				warnx("command must either be "
2353				      "read or write, not both");
2354				error = 1;
2355				goto scsicmd_bailout;
2356			}
2357			arglist |= CAM_ARG_CMD_OUT;
2358			flags = CAM_DIR_OUT;
2359			data_bytes = strtol(optarg, NULL, 0);
2360			if (data_bytes <= 0) {
2361				warnx("invalid number of output bytes %d",
2362				      data_bytes);
2363				error = 1;
2364				goto scsicmd_bailout;
2365			}
2366			hook.argc = argc - optind;
2367			hook.argv = argv + optind;
2368			hook.got = 0;
2369			datastr = cget(&hook, NULL);
2370			data_ptr = (u_int8_t *)malloc(data_bytes);
2371			if (data_ptr == NULL) {
2372				warnx("can't malloc memory for data_ptr");
2373				error = 1;
2374				goto scsicmd_bailout;
2375			}
2376			bzero(data_ptr, data_bytes);
2377			/*
2378			 * If the user supplied "-" instead of a format, he
2379			 * wants the data to be read from stdin.
2380			 */
2381			if ((datastr != NULL)
2382			 && (datastr[0] == '-'))
2383				fd_data = 1;
2384			else
2385				buff_encode_visit(data_ptr, data_bytes, datastr,
2386						  iget, &hook);
2387			optind += hook.got;
2388			break;
2389		case 'r':
2390			need_res = 1;
2391			hook.argc = argc - optind;
2392			hook.argv = argv + optind;
2393			hook.got = 0;
2394			resstr = cget(&hook, NULL);
2395			if ((resstr != NULL) && (resstr[0] == '-'))
2396				fd_res = 1;
2397			optind += hook.got;
2398			break;
2399		default:
2400			break;
2401		}
2402	}
2403
2404	/*
2405	 * If fd_data is set, and we're writing to the device, we need to
2406	 * read the data the user wants written from stdin.
2407	 */
2408	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2409		ssize_t amt_read;
2410		int amt_to_read = data_bytes;
2411		u_int8_t *buf_ptr = data_ptr;
2412
2413		for (amt_read = 0; amt_to_read > 0;
2414		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2415			if (amt_read == -1) {
2416				warn("error reading data from stdin");
2417				error = 1;
2418				goto scsicmd_bailout;
2419			}
2420			amt_to_read -= amt_read;
2421			buf_ptr += amt_read;
2422		}
2423	}
2424
2425	if (arglist & CAM_ARG_ERR_RECOVER)
2426		flags |= CAM_PASS_ERR_RECOVER;
2427
2428	/* Disable freezing the device queue */
2429	flags |= CAM_DEV_QFRZDIS;
2430
2431	if (cdb_len) {
2432		/*
2433		 * This is taken from the SCSI-3 draft spec.
2434		 * (T10/1157D revision 0.3)
2435		 * The top 3 bits of an opcode are the group code.
2436		 * The next 5 bits are the command code.
2437		 * Group 0:  six byte commands
2438		 * Group 1:  ten byte commands
2439		 * Group 2:  ten byte commands
2440		 * Group 3:  reserved
2441		 * Group 4:  sixteen byte commands
2442		 * Group 5:  twelve byte commands
2443		 * Group 6:  vendor specific
2444		 * Group 7:  vendor specific
2445		 */
2446		switch((cdb[0] >> 5) & 0x7) {
2447			case 0:
2448				cdb_len = 6;
2449				break;
2450			case 1:
2451			case 2:
2452				cdb_len = 10;
2453				break;
2454			case 3:
2455			case 6:
2456			case 7:
2457			        /* computed by buff_encode_visit */
2458				break;
2459			case 4:
2460				cdb_len = 16;
2461				break;
2462			case 5:
2463				cdb_len = 12;
2464				break;
2465		}
2466
2467		/*
2468		 * We should probably use csio_build_visit or something like that
2469		 * here, but it's easier to encode arguments as you go.  The
2470		 * alternative would be skipping the CDB argument and then encoding
2471		 * it here, since we've got the data buffer argument by now.
2472		 */
2473		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2474
2475		cam_fill_csio(&ccb->csio,
2476		      /*retries*/ retry_count,
2477		      /*cbfcnp*/ NULL,
2478		      /*flags*/ flags,
2479		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
2480		      /*data_ptr*/ data_ptr,
2481		      /*dxfer_len*/ data_bytes,
2482		      /*sense_len*/ SSD_FULL_SIZE,
2483		      /*cdb_len*/ cdb_len,
2484		      /*timeout*/ timeout ? timeout : 5000);
2485	} else {
2486		atacmd_len = 12;
2487		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2488		if (need_res)
2489			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2490		if (dmacmd)
2491			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2492		if (fpdmacmd)
2493			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2494
2495		cam_fill_ataio(&ccb->ataio,
2496		      /*retries*/ retry_count,
2497		      /*cbfcnp*/ NULL,
2498		      /*flags*/ flags,
2499		      /*tag_action*/ 0,
2500		      /*data_ptr*/ data_ptr,
2501		      /*dxfer_len*/ data_bytes,
2502		      /*timeout*/ timeout ? timeout : 5000);
2503	}
2504
2505	if (((retval = cam_send_ccb(device, ccb)) < 0)
2506	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2507		const char *warnstr = "error sending command";
2508
2509		if (retval < 0)
2510			warn(warnstr);
2511		else
2512			warnx(warnstr);
2513
2514		if (arglist & CAM_ARG_VERBOSE) {
2515			cam_error_print(device, ccb, CAM_ESF_ALL,
2516					CAM_EPF_ALL, stderr);
2517		}
2518
2519		error = 1;
2520		goto scsicmd_bailout;
2521	}
2522
2523	if (atacmd_len && need_res) {
2524		if (fd_res == 0) {
2525			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2526					  arg_put, NULL);
2527			fprintf(stdout, "\n");
2528		} else {
2529			fprintf(stdout,
2530			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2531			    ccb->ataio.res.status,
2532			    ccb->ataio.res.error,
2533			    ccb->ataio.res.lba_low,
2534			    ccb->ataio.res.lba_mid,
2535			    ccb->ataio.res.lba_high,
2536			    ccb->ataio.res.device,
2537			    ccb->ataio.res.lba_low_exp,
2538			    ccb->ataio.res.lba_mid_exp,
2539			    ccb->ataio.res.lba_high_exp,
2540			    ccb->ataio.res.sector_count,
2541			    ccb->ataio.res.sector_count_exp);
2542			fflush(stdout);
2543		}
2544	}
2545
2546	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2547	 && (arglist & CAM_ARG_CMD_IN)
2548	 && (data_bytes > 0)) {
2549		if (fd_data == 0) {
2550			buff_decode_visit(data_ptr, data_bytes, datastr,
2551					  arg_put, NULL);
2552			fprintf(stdout, "\n");
2553		} else {
2554			ssize_t amt_written;
2555			int amt_to_write = data_bytes;
2556			u_int8_t *buf_ptr = data_ptr;
2557
2558			for (amt_written = 0; (amt_to_write > 0) &&
2559			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2560				amt_to_write -= amt_written;
2561				buf_ptr += amt_written;
2562			}
2563			if (amt_written == -1) {
2564				warn("error writing data to stdout");
2565				error = 1;
2566				goto scsicmd_bailout;
2567			} else if ((amt_written == 0)
2568				&& (amt_to_write > 0)) {
2569				warnx("only wrote %u bytes out of %u",
2570				      data_bytes - amt_to_write, data_bytes);
2571			}
2572		}
2573	}
2574
2575scsicmd_bailout:
2576
2577	if ((data_bytes > 0) && (data_ptr != NULL))
2578		free(data_ptr);
2579
2580	cam_freeccb(ccb);
2581
2582	return(error);
2583}
2584
2585static int
2586camdebug(int argc, char **argv, char *combinedopt)
2587{
2588	int c, fd;
2589	int bus = -1, target = -1, lun = -1;
2590	char *tstr, *tmpstr = NULL;
2591	union ccb ccb;
2592	int error = 0;
2593
2594	bzero(&ccb, sizeof(union ccb));
2595
2596	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2597		switch(c) {
2598		case 'I':
2599			arglist |= CAM_ARG_DEBUG_INFO;
2600			ccb.cdbg.flags |= CAM_DEBUG_INFO;
2601			break;
2602		case 'P':
2603			arglist |= CAM_ARG_DEBUG_PERIPH;
2604			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2605			break;
2606		case 'S':
2607			arglist |= CAM_ARG_DEBUG_SUBTRACE;
2608			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2609			break;
2610		case 'T':
2611			arglist |= CAM_ARG_DEBUG_TRACE;
2612			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2613			break;
2614		case 'X':
2615			arglist |= CAM_ARG_DEBUG_XPT;
2616			ccb.cdbg.flags |= CAM_DEBUG_XPT;
2617			break;
2618		case 'c':
2619			arglist |= CAM_ARG_DEBUG_CDB;
2620			ccb.cdbg.flags |= CAM_DEBUG_CDB;
2621			break;
2622		default:
2623			break;
2624		}
2625	}
2626
2627	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2628		warnx("error opening transport layer device %s", XPT_DEVICE);
2629		warn("%s", XPT_DEVICE);
2630		return(1);
2631	}
2632	argc -= optind;
2633	argv += optind;
2634
2635	if (argc <= 0) {
2636		warnx("you must specify \"off\", \"all\" or a bus,");
2637		warnx("bus:target, or bus:target:lun");
2638		close(fd);
2639		return(1);
2640	}
2641
2642	tstr = *argv;
2643
2644	while (isspace(*tstr) && (*tstr != '\0'))
2645		tstr++;
2646
2647	if (strncmp(tstr, "off", 3) == 0) {
2648		ccb.cdbg.flags = CAM_DEBUG_NONE;
2649		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2650			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2651			     CAM_ARG_DEBUG_XPT);
2652	} else if (strncmp(tstr, "all", 3) != 0) {
2653		tmpstr = (char *)strtok(tstr, ":");
2654		if ((tmpstr != NULL) && (*tmpstr != '\0')){
2655			bus = strtol(tmpstr, NULL, 0);
2656			arglist |= CAM_ARG_BUS;
2657			tmpstr = (char *)strtok(NULL, ":");
2658			if ((tmpstr != NULL) && (*tmpstr != '\0')){
2659				target = strtol(tmpstr, NULL, 0);
2660				arglist |= CAM_ARG_TARGET;
2661				tmpstr = (char *)strtok(NULL, ":");
2662				if ((tmpstr != NULL) && (*tmpstr != '\0')){
2663					lun = strtol(tmpstr, NULL, 0);
2664					arglist |= CAM_ARG_LUN;
2665				}
2666			}
2667		} else {
2668			error = 1;
2669			warnx("you must specify \"all\", \"off\", or a bus,");
2670			warnx("bus:target, or bus:target:lun to debug");
2671		}
2672	}
2673
2674	if (error == 0) {
2675
2676		ccb.ccb_h.func_code = XPT_DEBUG;
2677		ccb.ccb_h.path_id = bus;
2678		ccb.ccb_h.target_id = target;
2679		ccb.ccb_h.target_lun = lun;
2680
2681		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2682			warn("CAMIOCOMMAND ioctl failed");
2683			error = 1;
2684		}
2685
2686		if (error == 0) {
2687			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2688			     CAM_FUNC_NOTAVAIL) {
2689				warnx("CAM debugging not available");
2690				warnx("you need to put options CAMDEBUG in"
2691				      " your kernel config file!");
2692				error = 1;
2693			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2694				    CAM_REQ_CMP) {
2695				warnx("XPT_DEBUG CCB failed with status %#x",
2696				      ccb.ccb_h.status);
2697				error = 1;
2698			} else {
2699				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2700					fprintf(stderr,
2701						"Debugging turned off\n");
2702				} else {
2703					fprintf(stderr,
2704						"Debugging enabled for "
2705						"%d:%d:%d\n",
2706						bus, target, lun);
2707				}
2708			}
2709		}
2710		close(fd);
2711	}
2712
2713	return(error);
2714}
2715
2716static int
2717tagcontrol(struct cam_device *device, int argc, char **argv,
2718	   char *combinedopt)
2719{
2720	int c;
2721	union ccb *ccb;
2722	int numtags = -1;
2723	int retval = 0;
2724	int quiet = 0;
2725	char pathstr[1024];
2726
2727	ccb = cam_getccb(device);
2728
2729	if (ccb == NULL) {
2730		warnx("tagcontrol: error allocating ccb");
2731		return(1);
2732	}
2733
2734	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2735		switch(c) {
2736		case 'N':
2737			numtags = strtol(optarg, NULL, 0);
2738			if (numtags < 0) {
2739				warnx("tag count %d is < 0", numtags);
2740				retval = 1;
2741				goto tagcontrol_bailout;
2742			}
2743			break;
2744		case 'q':
2745			quiet++;
2746			break;
2747		default:
2748			break;
2749		}
2750	}
2751
2752	cam_path_string(device, pathstr, sizeof(pathstr));
2753
2754	if (numtags >= 0) {
2755		bzero(&(&ccb->ccb_h)[1],
2756		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2757		ccb->ccb_h.func_code = XPT_REL_SIMQ;
2758		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2759		ccb->crs.openings = numtags;
2760
2761
2762		if (cam_send_ccb(device, ccb) < 0) {
2763			perror("error sending XPT_REL_SIMQ CCB");
2764			retval = 1;
2765			goto tagcontrol_bailout;
2766		}
2767
2768		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2769			warnx("XPT_REL_SIMQ CCB failed");
2770			cam_error_print(device, ccb, CAM_ESF_ALL,
2771					CAM_EPF_ALL, stderr);
2772			retval = 1;
2773			goto tagcontrol_bailout;
2774		}
2775
2776
2777		if (quiet == 0)
2778			fprintf(stdout, "%stagged openings now %d\n",
2779				pathstr, ccb->crs.openings);
2780	}
2781
2782	bzero(&(&ccb->ccb_h)[1],
2783	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2784
2785	ccb->ccb_h.func_code = XPT_GDEV_STATS;
2786
2787	if (cam_send_ccb(device, ccb) < 0) {
2788		perror("error sending XPT_GDEV_STATS CCB");
2789		retval = 1;
2790		goto tagcontrol_bailout;
2791	}
2792
2793	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2794		warnx("XPT_GDEV_STATS CCB failed");
2795		cam_error_print(device, ccb, CAM_ESF_ALL,
2796				CAM_EPF_ALL, stderr);
2797		retval = 1;
2798		goto tagcontrol_bailout;
2799	}
2800
2801	if (arglist & CAM_ARG_VERBOSE) {
2802		fprintf(stdout, "%s", pathstr);
2803		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2804		fprintf(stdout, "%s", pathstr);
2805		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2806		fprintf(stdout, "%s", pathstr);
2807		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2808		fprintf(stdout, "%s", pathstr);
2809		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2810		fprintf(stdout, "%s", pathstr);
2811		fprintf(stdout, "held          %d\n", ccb->cgds.held);
2812		fprintf(stdout, "%s", pathstr);
2813		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2814		fprintf(stdout, "%s", pathstr);
2815		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2816	} else {
2817		if (quiet == 0) {
2818			fprintf(stdout, "%s", pathstr);
2819			fprintf(stdout, "device openings: ");
2820		}
2821		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2822			ccb->cgds.dev_active);
2823	}
2824
2825tagcontrol_bailout:
2826
2827	cam_freeccb(ccb);
2828	return(retval);
2829}
2830
2831static void
2832cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2833{
2834	char pathstr[1024];
2835
2836	cam_path_string(device, pathstr, sizeof(pathstr));
2837
2838	if (cts->transport == XPORT_SPI) {
2839		struct ccb_trans_settings_spi *spi =
2840		    &cts->xport_specific.spi;
2841
2842		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2843
2844			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2845				spi->sync_period);
2846
2847			if (spi->sync_offset != 0) {
2848				u_int freq;
2849
2850				freq = scsi_calc_syncsrate(spi->sync_period);
2851				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2852					pathstr, freq / 1000, freq % 1000);
2853			}
2854		}
2855
2856		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2857			fprintf(stdout, "%soffset: %d\n", pathstr,
2858			    spi->sync_offset);
2859		}
2860
2861		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2862			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2863				(0x01 << spi->bus_width) * 8);
2864		}
2865
2866		if (spi->valid & CTS_SPI_VALID_DISC) {
2867			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2868				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2869				"enabled" : "disabled");
2870		}
2871	}
2872	if (cts->transport == XPORT_ATA) {
2873		struct ccb_trans_settings_ata *ata =
2874		    &cts->xport_specific.ata;
2875
2876		if ((ata->valid & CTS_ATA_VALID_MODE) != 0) {
2877			fprintf(stdout, "%sATA mode: %s\n", pathstr,
2878				ata_mode2string(ata->mode));
2879		}
2880		if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2881			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2882				ata->atapi);
2883		}
2884		if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2885			fprintf(stdout, "%sPIO transaction length: %d\n",
2886				pathstr, ata->bytecount);
2887		}
2888	}
2889	if (cts->transport == XPORT_SATA) {
2890		struct ccb_trans_settings_sata *sata =
2891		    &cts->xport_specific.sata;
2892
2893		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2894			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2895				sata->revision);
2896		}
2897		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2898			fprintf(stdout, "%sATA mode: %s\n", pathstr,
2899				ata_mode2string(sata->mode));
2900		}
2901		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2902			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2903				sata->atapi);
2904		}
2905		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2906			fprintf(stdout, "%sPIO transaction length: %d\n",
2907				pathstr, sata->bytecount);
2908		}
2909		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2910			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2911				sata->pm_present);
2912		}
2913		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2914			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2915				sata->tags);
2916		}
2917		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2918			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2919				sata->caps);
2920		}
2921	}
2922	if (cts->protocol == PROTO_SCSI) {
2923		struct ccb_trans_settings_scsi *scsi=
2924		    &cts->proto_specific.scsi;
2925
2926		if (scsi->valid & CTS_SCSI_VALID_TQ) {
2927			fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2928				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2929				"enabled" : "disabled");
2930		}
2931	}
2932
2933}
2934
2935/*
2936 * Get a path inquiry CCB for the specified device.
2937 */
2938static int
2939get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2940{
2941	union ccb *ccb;
2942	int retval = 0;
2943
2944	ccb = cam_getccb(device);
2945	if (ccb == NULL) {
2946		warnx("get_cpi: couldn't allocate CCB");
2947		return(1);
2948	}
2949	bzero(&(&ccb->ccb_h)[1],
2950	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2951	ccb->ccb_h.func_code = XPT_PATH_INQ;
2952	if (cam_send_ccb(device, ccb) < 0) {
2953		warn("get_cpi: error sending Path Inquiry CCB");
2954		if (arglist & CAM_ARG_VERBOSE)
2955			cam_error_print(device, ccb, CAM_ESF_ALL,
2956					CAM_EPF_ALL, stderr);
2957		retval = 1;
2958		goto get_cpi_bailout;
2959	}
2960	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2961		if (arglist & CAM_ARG_VERBOSE)
2962			cam_error_print(device, ccb, CAM_ESF_ALL,
2963					CAM_EPF_ALL, stderr);
2964		retval = 1;
2965		goto get_cpi_bailout;
2966	}
2967	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2968
2969get_cpi_bailout:
2970	cam_freeccb(ccb);
2971	return(retval);
2972}
2973
2974/*
2975 * Get a get device CCB for the specified device.
2976 */
2977static int
2978get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
2979{
2980	union ccb *ccb;
2981	int retval = 0;
2982
2983	ccb = cam_getccb(device);
2984	if (ccb == NULL) {
2985		warnx("get_cgd: couldn't allocate CCB");
2986		return(1);
2987	}
2988	bzero(&(&ccb->ccb_h)[1],
2989	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2990	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
2991	if (cam_send_ccb(device, ccb) < 0) {
2992		warn("get_cgd: error sending Path Inquiry CCB");
2993		if (arglist & CAM_ARG_VERBOSE)
2994			cam_error_print(device, ccb, CAM_ESF_ALL,
2995					CAM_EPF_ALL, stderr);
2996		retval = 1;
2997		goto get_cgd_bailout;
2998	}
2999	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3000		if (arglist & CAM_ARG_VERBOSE)
3001			cam_error_print(device, ccb, CAM_ESF_ALL,
3002					CAM_EPF_ALL, stderr);
3003		retval = 1;
3004		goto get_cgd_bailout;
3005	}
3006	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3007
3008get_cgd_bailout:
3009	cam_freeccb(ccb);
3010	return(retval);
3011}
3012
3013static void
3014cpi_print(struct ccb_pathinq *cpi)
3015{
3016	char adapter_str[1024];
3017	int i;
3018
3019	snprintf(adapter_str, sizeof(adapter_str),
3020		 "%s%d:", cpi->dev_name, cpi->unit_number);
3021
3022	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3023		cpi->version_num);
3024
3025	for (i = 1; i < 0xff; i = i << 1) {
3026		const char *str;
3027
3028		if ((i & cpi->hba_inquiry) == 0)
3029			continue;
3030
3031		fprintf(stdout, "%s supports ", adapter_str);
3032
3033		switch(i) {
3034		case PI_MDP_ABLE:
3035			str = "MDP message";
3036			break;
3037		case PI_WIDE_32:
3038			str = "32 bit wide SCSI";
3039			break;
3040		case PI_WIDE_16:
3041			str = "16 bit wide SCSI";
3042			break;
3043		case PI_SDTR_ABLE:
3044			str = "SDTR message";
3045			break;
3046		case PI_LINKED_CDB:
3047			str = "linked CDBs";
3048			break;
3049		case PI_TAG_ABLE:
3050			str = "tag queue messages";
3051			break;
3052		case PI_SOFT_RST:
3053			str = "soft reset alternative";
3054			break;
3055		case PI_SATAPM:
3056			str = "SATA Port Multiplier";
3057			break;
3058		default:
3059			str = "unknown PI bit set";
3060			break;
3061		}
3062		fprintf(stdout, "%s\n", str);
3063	}
3064
3065	for (i = 1; i < 0xff; i = i << 1) {
3066		const char *str;
3067
3068		if ((i & cpi->hba_misc) == 0)
3069			continue;
3070
3071		fprintf(stdout, "%s ", adapter_str);
3072
3073		switch(i) {
3074		case PIM_SCANHILO:
3075			str = "bus scans from high ID to low ID";
3076			break;
3077		case PIM_NOREMOVE:
3078			str = "removable devices not included in scan";
3079			break;
3080		case PIM_NOINITIATOR:
3081			str = "initiator role not supported";
3082			break;
3083		case PIM_NOBUSRESET:
3084			str = "user has disabled initial BUS RESET or"
3085			      " controller is in target/mixed mode";
3086			break;
3087		case PIM_NO_6_BYTE:
3088			str = "do not send 6-byte commands";
3089			break;
3090		case PIM_SEQSCAN:
3091			str = "scan bus sequentially";
3092			break;
3093		default:
3094			str = "unknown PIM bit set";
3095			break;
3096		}
3097		fprintf(stdout, "%s\n", str);
3098	}
3099
3100	for (i = 1; i < 0xff; i = i << 1) {
3101		const char *str;
3102
3103		if ((i & cpi->target_sprt) == 0)
3104			continue;
3105
3106		fprintf(stdout, "%s supports ", adapter_str);
3107		switch(i) {
3108		case PIT_PROCESSOR:
3109			str = "target mode processor mode";
3110			break;
3111		case PIT_PHASE:
3112			str = "target mode phase cog. mode";
3113			break;
3114		case PIT_DISCONNECT:
3115			str = "disconnects in target mode";
3116			break;
3117		case PIT_TERM_IO:
3118			str = "terminate I/O message in target mode";
3119			break;
3120		case PIT_GRP_6:
3121			str = "group 6 commands in target mode";
3122			break;
3123		case PIT_GRP_7:
3124			str = "group 7 commands in target mode";
3125			break;
3126		default:
3127			str = "unknown PIT bit set";
3128			break;
3129		}
3130
3131		fprintf(stdout, "%s\n", str);
3132	}
3133	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3134		cpi->hba_eng_cnt);
3135	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3136		cpi->max_target);
3137	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3138		cpi->max_lun);
3139	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3140		adapter_str, cpi->hpath_id);
3141	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3142		cpi->initiator_id);
3143	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3144	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3145	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
3146	    adapter_str, cpi->hba_vendor);
3147	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
3148	    adapter_str, cpi->hba_device);
3149	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
3150	    adapter_str, cpi->hba_subvendor);
3151	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
3152	    adapter_str, cpi->hba_subdevice);
3153	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3154	fprintf(stdout, "%s base transfer speed: ", adapter_str);
3155	if (cpi->base_transfer_speed > 1000)
3156		fprintf(stdout, "%d.%03dMB/sec\n",
3157			cpi->base_transfer_speed / 1000,
3158			cpi->base_transfer_speed % 1000);
3159	else
3160		fprintf(stdout, "%dKB/sec\n",
3161			(cpi->base_transfer_speed % 1000) * 1000);
3162	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
3163	    adapter_str, cpi->maxio);
3164}
3165
3166static int
3167get_print_cts(struct cam_device *device, int user_settings, int quiet,
3168	      struct ccb_trans_settings *cts)
3169{
3170	int retval;
3171	union ccb *ccb;
3172
3173	retval = 0;
3174	ccb = cam_getccb(device);
3175
3176	if (ccb == NULL) {
3177		warnx("get_print_cts: error allocating ccb");
3178		return(1);
3179	}
3180
3181	bzero(&(&ccb->ccb_h)[1],
3182	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3183
3184	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3185
3186	if (user_settings == 0)
3187		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3188	else
3189		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3190
3191	if (cam_send_ccb(device, ccb) < 0) {
3192		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3193		if (arglist & CAM_ARG_VERBOSE)
3194			cam_error_print(device, ccb, CAM_ESF_ALL,
3195					CAM_EPF_ALL, stderr);
3196		retval = 1;
3197		goto get_print_cts_bailout;
3198	}
3199
3200	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3201		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3202		if (arglist & CAM_ARG_VERBOSE)
3203			cam_error_print(device, ccb, CAM_ESF_ALL,
3204					CAM_EPF_ALL, stderr);
3205		retval = 1;
3206		goto get_print_cts_bailout;
3207	}
3208
3209	if (quiet == 0)
3210		cts_print(device, &ccb->cts);
3211
3212	if (cts != NULL)
3213		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3214
3215get_print_cts_bailout:
3216
3217	cam_freeccb(ccb);
3218
3219	return(retval);
3220}
3221
3222static int
3223ratecontrol(struct cam_device *device, int retry_count, int timeout,
3224	    int argc, char **argv, char *combinedopt)
3225{
3226	int c;
3227	union ccb *ccb;
3228	int user_settings = 0;
3229	int retval = 0;
3230	int disc_enable = -1, tag_enable = -1;
3231	int mode = -1;
3232	int offset = -1;
3233	double syncrate = -1;
3234	int bus_width = -1;
3235	int quiet = 0;
3236	int change_settings = 0, send_tur = 0;
3237	struct ccb_pathinq cpi;
3238
3239	ccb = cam_getccb(device);
3240	if (ccb == NULL) {
3241		warnx("ratecontrol: error allocating ccb");
3242		return(1);
3243	}
3244	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3245		switch(c){
3246		case 'a':
3247			send_tur = 1;
3248			break;
3249		case 'c':
3250			user_settings = 0;
3251			break;
3252		case 'D':
3253			if (strncasecmp(optarg, "enable", 6) == 0)
3254				disc_enable = 1;
3255			else if (strncasecmp(optarg, "disable", 7) == 0)
3256				disc_enable = 0;
3257			else {
3258				warnx("-D argument \"%s\" is unknown", optarg);
3259				retval = 1;
3260				goto ratecontrol_bailout;
3261			}
3262			change_settings = 1;
3263			break;
3264		case 'M':
3265			mode = ata_string2mode(optarg);
3266			if (mode < 0) {
3267				warnx("unknown mode '%s'", optarg);
3268				retval = 1;
3269				goto ratecontrol_bailout;
3270			}
3271			change_settings = 1;
3272			break;
3273		case 'O':
3274			offset = strtol(optarg, NULL, 0);
3275			if (offset < 0) {
3276				warnx("offset value %d is < 0", offset);
3277				retval = 1;
3278				goto ratecontrol_bailout;
3279			}
3280			change_settings = 1;
3281			break;
3282		case 'q':
3283			quiet++;
3284			break;
3285		case 'R':
3286			syncrate = atof(optarg);
3287			if (syncrate < 0) {
3288				warnx("sync rate %f is < 0", syncrate);
3289				retval = 1;
3290				goto ratecontrol_bailout;
3291			}
3292			change_settings = 1;
3293			break;
3294		case 'T':
3295			if (strncasecmp(optarg, "enable", 6) == 0)
3296				tag_enable = 1;
3297			else if (strncasecmp(optarg, "disable", 7) == 0)
3298				tag_enable = 0;
3299			else {
3300				warnx("-T argument \"%s\" is unknown", optarg);
3301				retval = 1;
3302				goto ratecontrol_bailout;
3303			}
3304			change_settings = 1;
3305			break;
3306		case 'U':
3307			user_settings = 1;
3308			break;
3309		case 'W':
3310			bus_width = strtol(optarg, NULL, 0);
3311			if (bus_width < 0) {
3312				warnx("bus width %d is < 0", bus_width);
3313				retval = 1;
3314				goto ratecontrol_bailout;
3315			}
3316			change_settings = 1;
3317			break;
3318		default:
3319			break;
3320		}
3321	}
3322	bzero(&(&ccb->ccb_h)[1],
3323	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3324	/*
3325	 * Grab path inquiry information, so we can determine whether
3326	 * or not the initiator is capable of the things that the user
3327	 * requests.
3328	 */
3329	ccb->ccb_h.func_code = XPT_PATH_INQ;
3330	if (cam_send_ccb(device, ccb) < 0) {
3331		perror("error sending XPT_PATH_INQ CCB");
3332		if (arglist & CAM_ARG_VERBOSE) {
3333			cam_error_print(device, ccb, CAM_ESF_ALL,
3334					CAM_EPF_ALL, stderr);
3335		}
3336		retval = 1;
3337		goto ratecontrol_bailout;
3338	}
3339	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3340		warnx("XPT_PATH_INQ CCB failed");
3341		if (arglist & CAM_ARG_VERBOSE) {
3342			cam_error_print(device, ccb, CAM_ESF_ALL,
3343					CAM_EPF_ALL, stderr);
3344		}
3345		retval = 1;
3346		goto ratecontrol_bailout;
3347	}
3348	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3349	bzero(&(&ccb->ccb_h)[1],
3350	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3351	if (quiet == 0) {
3352		fprintf(stdout, "%s parameters:\n",
3353		    user_settings ? "User" : "Current");
3354	}
3355	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3356	if (retval != 0)
3357		goto ratecontrol_bailout;
3358
3359	if (arglist & CAM_ARG_VERBOSE)
3360		cpi_print(&cpi);
3361
3362	if (change_settings) {
3363		int didsettings = 0;
3364		struct ccb_trans_settings_spi *spi = NULL;
3365		struct ccb_trans_settings_ata *ata = NULL;
3366		struct ccb_trans_settings_sata *sata = NULL;
3367		struct ccb_trans_settings_scsi *scsi = NULL;
3368
3369		if (ccb->cts.transport == XPORT_SPI)
3370			spi = &ccb->cts.xport_specific.spi;
3371		if (ccb->cts.transport == XPORT_ATA)
3372			ata = &ccb->cts.xport_specific.ata;
3373		if (ccb->cts.transport == XPORT_SATA)
3374			sata = &ccb->cts.xport_specific.sata;
3375		if (ccb->cts.protocol == PROTO_SCSI)
3376			scsi = &ccb->cts.proto_specific.scsi;
3377		ccb->cts.xport_specific.valid = 0;
3378		ccb->cts.proto_specific.valid = 0;
3379		if (spi && disc_enable != -1) {
3380			spi->valid |= CTS_SPI_VALID_DISC;
3381			if (disc_enable == 0)
3382				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3383			else
3384				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3385		}
3386		if (scsi && tag_enable != -1) {
3387			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3388				warnx("HBA does not support tagged queueing, "
3389				      "so you cannot modify tag settings");
3390				retval = 1;
3391				goto ratecontrol_bailout;
3392			}
3393			scsi->valid |= CTS_SCSI_VALID_TQ;
3394			if (tag_enable == 0)
3395				scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3396			else
3397				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3398			didsettings++;
3399		}
3400		if (spi && offset != -1) {
3401			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3402				warnx("HBA is not capable of changing offset");
3403				retval = 1;
3404				goto ratecontrol_bailout;
3405			}
3406			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3407			spi->sync_offset = offset;
3408			didsettings++;
3409		}
3410		if (spi && syncrate != -1) {
3411			int prelim_sync_period;
3412			u_int freq;
3413
3414			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3415				warnx("HBA is not capable of changing "
3416				      "transfer rates");
3417				retval = 1;
3418				goto ratecontrol_bailout;
3419			}
3420			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3421			/*
3422			 * The sync rate the user gives us is in MHz.
3423			 * We need to translate it into KHz for this
3424			 * calculation.
3425			 */
3426			syncrate *= 1000;
3427			/*
3428			 * Next, we calculate a "preliminary" sync period
3429			 * in tenths of a nanosecond.
3430			 */
3431			if (syncrate == 0)
3432				prelim_sync_period = 0;
3433			else
3434				prelim_sync_period = 10000000 / syncrate;
3435			spi->sync_period =
3436				scsi_calc_syncparam(prelim_sync_period);
3437			freq = scsi_calc_syncsrate(spi->sync_period);
3438			didsettings++;
3439		}
3440		if (sata && syncrate != -1) {
3441			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3442				warnx("HBA is not capable of changing "
3443				      "transfer rates");
3444				retval = 1;
3445				goto ratecontrol_bailout;
3446			}
3447			sata->revision = ata_speed2revision(syncrate * 100);
3448			if (sata->revision < 0) {
3449				warnx("Invalid rate %f", syncrate);
3450				retval = 1;
3451				goto ratecontrol_bailout;
3452			}
3453			sata->valid |= CTS_SATA_VALID_REVISION;
3454			didsettings++;
3455		}
3456		if ((ata || sata) && mode != -1) {
3457			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3458				warnx("HBA is not capable of changing "
3459				      "transfer rates");
3460				retval = 1;
3461				goto ratecontrol_bailout;
3462			}
3463			if (ata) {
3464				ata->mode = mode;
3465				ata->valid |= CTS_ATA_VALID_MODE;
3466			} else {
3467				sata->mode = mode;
3468				sata->valid |= CTS_SATA_VALID_MODE;
3469			}
3470			didsettings++;
3471		}
3472		/*
3473		 * The bus_width argument goes like this:
3474		 * 0 == 8 bit
3475		 * 1 == 16 bit
3476		 * 2 == 32 bit
3477		 * Therefore, if you shift the number of bits given on the
3478		 * command line right by 4, you should get the correct
3479		 * number.
3480		 */
3481		if (spi && bus_width != -1) {
3482			/*
3483			 * We might as well validate things here with a
3484			 * decipherable error message, rather than what
3485			 * will probably be an indecipherable error message
3486			 * by the time it gets back to us.
3487			 */
3488			if ((bus_width == 16)
3489			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3490				warnx("HBA does not support 16 bit bus width");
3491				retval = 1;
3492				goto ratecontrol_bailout;
3493			} else if ((bus_width == 32)
3494				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3495				warnx("HBA does not support 32 bit bus width");
3496				retval = 1;
3497				goto ratecontrol_bailout;
3498			} else if ((bus_width != 8)
3499				&& (bus_width != 16)
3500				&& (bus_width != 32)) {
3501				warnx("Invalid bus width %d", bus_width);
3502				retval = 1;
3503				goto ratecontrol_bailout;
3504			}
3505			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3506			spi->bus_width = bus_width >> 4;
3507			didsettings++;
3508		}
3509		if  (didsettings == 0) {
3510			goto ratecontrol_bailout;
3511		}
3512		if  (!user_settings && (ata || sata)) {
3513			warnx("You can modify only user settings for ATA/SATA");
3514			retval = 1;
3515			goto ratecontrol_bailout;
3516		}
3517		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3518		if (cam_send_ccb(device, ccb) < 0) {
3519			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3520			if (arglist & CAM_ARG_VERBOSE) {
3521				cam_error_print(device, ccb, CAM_ESF_ALL,
3522						CAM_EPF_ALL, stderr);
3523			}
3524			retval = 1;
3525			goto ratecontrol_bailout;
3526		}
3527		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3528			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3529			if (arglist & CAM_ARG_VERBOSE) {
3530				cam_error_print(device, ccb, CAM_ESF_ALL,
3531						CAM_EPF_ALL, stderr);
3532			}
3533			retval = 1;
3534			goto ratecontrol_bailout;
3535		}
3536	}
3537	if (send_tur) {
3538		retval = testunitready(device, retry_count, timeout,
3539				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3540		/*
3541		 * If the TUR didn't succeed, just bail.
3542		 */
3543		if (retval != 0) {
3544			if (quiet == 0)
3545				fprintf(stderr, "Test Unit Ready failed\n");
3546			goto ratecontrol_bailout;
3547		}
3548		/*
3549		 * If the user wants things quiet, there's no sense in
3550		 * getting the transfer settings, if we're not going
3551		 * to print them.
3552		 */
3553		if (quiet != 0)
3554			goto ratecontrol_bailout;
3555		fprintf(stdout, "New parameters:\n");
3556		retval = get_print_cts(device, user_settings, 0, NULL);
3557	}
3558
3559ratecontrol_bailout:
3560	cam_freeccb(ccb);
3561	return(retval);
3562}
3563
3564static int
3565scsiformat(struct cam_device *device, int argc, char **argv,
3566	   char *combinedopt, int retry_count, int timeout)
3567{
3568	union ccb *ccb;
3569	int c;
3570	int ycount = 0, quiet = 0;
3571	int error = 0, response = 0, retval = 0;
3572	int use_timeout = 10800 * 1000;
3573	int immediate = 1;
3574	struct format_defect_list_header fh;
3575	u_int8_t *data_ptr = NULL;
3576	u_int32_t dxfer_len = 0;
3577	u_int8_t byte2 = 0;
3578	int num_warnings = 0;
3579	int reportonly = 0;
3580
3581	ccb = cam_getccb(device);
3582
3583	if (ccb == NULL) {
3584		warnx("scsiformat: error allocating ccb");
3585		return(1);
3586	}
3587
3588	bzero(&(&ccb->ccb_h)[1],
3589	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3590
3591	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3592		switch(c) {
3593		case 'q':
3594			quiet++;
3595			break;
3596		case 'r':
3597			reportonly = 1;
3598			break;
3599		case 'w':
3600			immediate = 0;
3601			break;
3602		case 'y':
3603			ycount++;
3604			break;
3605		}
3606	}
3607
3608	if (reportonly)
3609		goto doreport;
3610
3611	if (quiet == 0) {
3612		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3613			"following device:\n");
3614
3615		error = scsidoinquiry(device, argc, argv, combinedopt,
3616				      retry_count, timeout);
3617
3618		if (error != 0) {
3619			warnx("scsiformat: error sending inquiry");
3620			goto scsiformat_bailout;
3621		}
3622	}
3623
3624	if (ycount == 0) {
3625
3626		do {
3627			char str[1024];
3628
3629			fprintf(stdout, "Are you SURE you want to do "
3630				"this? (yes/no) ");
3631
3632			if (fgets(str, sizeof(str), stdin) != NULL) {
3633
3634				if (strncasecmp(str, "yes", 3) == 0)
3635					response = 1;
3636				else if (strncasecmp(str, "no", 2) == 0)
3637					response = -1;
3638				else {
3639					fprintf(stdout, "Please answer"
3640						" \"yes\" or \"no\"\n");
3641				}
3642			}
3643		} while (response == 0);
3644
3645		if (response == -1) {
3646			error = 1;
3647			goto scsiformat_bailout;
3648		}
3649	}
3650
3651	if (timeout != 0)
3652		use_timeout = timeout;
3653
3654	if (quiet == 0) {
3655		fprintf(stdout, "Current format timeout is %d seconds\n",
3656			use_timeout / 1000);
3657	}
3658
3659	/*
3660	 * If the user hasn't disabled questions and didn't specify a
3661	 * timeout on the command line, ask them if they want the current
3662	 * timeout.
3663	 */
3664	if ((ycount == 0)
3665	 && (timeout == 0)) {
3666		char str[1024];
3667		int new_timeout = 0;
3668
3669		fprintf(stdout, "Enter new timeout in seconds or press\n"
3670			"return to keep the current timeout [%d] ",
3671			use_timeout / 1000);
3672
3673		if (fgets(str, sizeof(str), stdin) != NULL) {
3674			if (str[0] != '\0')
3675				new_timeout = atoi(str);
3676		}
3677
3678		if (new_timeout != 0) {
3679			use_timeout = new_timeout * 1000;
3680			fprintf(stdout, "Using new timeout value %d\n",
3681				use_timeout / 1000);
3682		}
3683	}
3684
3685	/*
3686	 * Keep this outside the if block below to silence any unused
3687	 * variable warnings.
3688	 */
3689	bzero(&fh, sizeof(fh));
3690
3691	/*
3692	 * If we're in immediate mode, we've got to include the format
3693	 * header
3694	 */
3695	if (immediate != 0) {
3696		fh.byte2 = FU_DLH_IMMED;
3697		data_ptr = (u_int8_t *)&fh;
3698		dxfer_len = sizeof(fh);
3699		byte2 = FU_FMT_DATA;
3700	} else if (quiet == 0) {
3701		fprintf(stdout, "Formatting...");
3702		fflush(stdout);
3703	}
3704
3705	scsi_format_unit(&ccb->csio,
3706			 /* retries */ retry_count,
3707			 /* cbfcnp */ NULL,
3708			 /* tag_action */ MSG_SIMPLE_Q_TAG,
3709			 /* byte2 */ byte2,
3710			 /* ileave */ 0,
3711			 /* data_ptr */ data_ptr,
3712			 /* dxfer_len */ dxfer_len,
3713			 /* sense_len */ SSD_FULL_SIZE,
3714			 /* timeout */ use_timeout);
3715
3716	/* Disable freezing the device queue */
3717	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3718
3719	if (arglist & CAM_ARG_ERR_RECOVER)
3720		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3721
3722	if (((retval = cam_send_ccb(device, ccb)) < 0)
3723	 || ((immediate == 0)
3724	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3725		const char errstr[] = "error sending format command";
3726
3727		if (retval < 0)
3728			warn(errstr);
3729		else
3730			warnx(errstr);
3731
3732		if (arglist & CAM_ARG_VERBOSE) {
3733			cam_error_print(device, ccb, CAM_ESF_ALL,
3734					CAM_EPF_ALL, stderr);
3735		}
3736		error = 1;
3737		goto scsiformat_bailout;
3738	}
3739
3740	/*
3741	 * If we ran in non-immediate mode, we already checked for errors
3742	 * above and printed out any necessary information.  If we're in
3743	 * immediate mode, we need to loop through and get status
3744	 * information periodically.
3745	 */
3746	if (immediate == 0) {
3747		if (quiet == 0) {
3748			fprintf(stdout, "Format Complete\n");
3749		}
3750		goto scsiformat_bailout;
3751	}
3752
3753doreport:
3754	do {
3755		cam_status status;
3756
3757		bzero(&(&ccb->ccb_h)[1],
3758		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3759
3760		/*
3761		 * There's really no need to do error recovery or
3762		 * retries here, since we're just going to sit in a
3763		 * loop and wait for the device to finish formatting.
3764		 */
3765		scsi_test_unit_ready(&ccb->csio,
3766				     /* retries */ 0,
3767				     /* cbfcnp */ NULL,
3768				     /* tag_action */ MSG_SIMPLE_Q_TAG,
3769				     /* sense_len */ SSD_FULL_SIZE,
3770				     /* timeout */ 5000);
3771
3772		/* Disable freezing the device queue */
3773		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3774
3775		retval = cam_send_ccb(device, ccb);
3776
3777		/*
3778		 * If we get an error from the ioctl, bail out.  SCSI
3779		 * errors are expected.
3780		 */
3781		if (retval < 0) {
3782			warn("error sending CAMIOCOMMAND ioctl");
3783			if (arglist & CAM_ARG_VERBOSE) {
3784				cam_error_print(device, ccb, CAM_ESF_ALL,
3785						CAM_EPF_ALL, stderr);
3786			}
3787			error = 1;
3788			goto scsiformat_bailout;
3789		}
3790
3791		status = ccb->ccb_h.status & CAM_STATUS_MASK;
3792
3793		if ((status != CAM_REQ_CMP)
3794		 && (status == CAM_SCSI_STATUS_ERROR)
3795		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3796			struct scsi_sense_data *sense;
3797			int error_code, sense_key, asc, ascq;
3798
3799			sense = &ccb->csio.sense_data;
3800			scsi_extract_sense(sense, &error_code, &sense_key,
3801					   &asc, &ascq);
3802
3803			/*
3804			 * According to the SCSI-2 and SCSI-3 specs, a
3805			 * drive that is in the middle of a format should
3806			 * return NOT READY with an ASC of "logical unit
3807			 * not ready, format in progress".  The sense key
3808			 * specific bytes will then be a progress indicator.
3809			 */
3810			if ((sense_key == SSD_KEY_NOT_READY)
3811			 && (asc == 0x04) && (ascq == 0x04)) {
3812				if ((sense->extra_len >= 10)
3813				 && ((sense->sense_key_spec[0] &
3814				      SSD_SCS_VALID) != 0)
3815				 && (quiet == 0)) {
3816					int val;
3817					u_int64_t percentage;
3818
3819					val = scsi_2btoul(
3820						&sense->sense_key_spec[1]);
3821					percentage = 10000 * val;
3822
3823					fprintf(stdout,
3824						"\rFormatting:  %ju.%02u %% "
3825						"(%d/%d) done",
3826						(uintmax_t)(percentage /
3827						(0x10000 * 100)),
3828						(unsigned)((percentage /
3829						0x10000) % 100),
3830						val, 0x10000);
3831					fflush(stdout);
3832				} else if ((quiet == 0)
3833					&& (++num_warnings <= 1)) {
3834					warnx("Unexpected SCSI Sense Key "
3835					      "Specific value returned "
3836					      "during format:");
3837					scsi_sense_print(device, &ccb->csio,
3838							 stderr);
3839					warnx("Unable to print status "
3840					      "information, but format will "
3841					      "proceed.");
3842					warnx("will exit when format is "
3843					      "complete");
3844				}
3845				sleep(1);
3846			} else {
3847				warnx("Unexpected SCSI error during format");
3848				cam_error_print(device, ccb, CAM_ESF_ALL,
3849						CAM_EPF_ALL, stderr);
3850				error = 1;
3851				goto scsiformat_bailout;
3852			}
3853
3854		} else if (status != CAM_REQ_CMP) {
3855			warnx("Unexpected CAM status %#x", status);
3856			if (arglist & CAM_ARG_VERBOSE)
3857				cam_error_print(device, ccb, CAM_ESF_ALL,
3858						CAM_EPF_ALL, stderr);
3859			error = 1;
3860			goto scsiformat_bailout;
3861		}
3862
3863	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3864
3865	if (quiet == 0)
3866		fprintf(stdout, "\nFormat Complete\n");
3867
3868scsiformat_bailout:
3869
3870	cam_freeccb(ccb);
3871
3872	return(error);
3873}
3874
3875static int
3876scsireportluns(struct cam_device *device, int argc, char **argv,
3877	       char *combinedopt, int retry_count, int timeout)
3878{
3879	union ccb *ccb;
3880	int c, countonly, lunsonly;
3881	struct scsi_report_luns_data *lundata;
3882	int alloc_len;
3883	uint8_t report_type;
3884	uint32_t list_len, i, j;
3885	int retval;
3886
3887	retval = 0;
3888	lundata = NULL;
3889	report_type = RPL_REPORT_DEFAULT;
3890	ccb = cam_getccb(device);
3891
3892	if (ccb == NULL) {
3893		warnx("%s: error allocating ccb", __func__);
3894		return (1);
3895	}
3896
3897	bzero(&(&ccb->ccb_h)[1],
3898	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3899
3900	countonly = 0;
3901	lunsonly = 0;
3902
3903	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3904		switch (c) {
3905		case 'c':
3906			countonly++;
3907			break;
3908		case 'l':
3909			lunsonly++;
3910			break;
3911		case 'r':
3912			if (strcasecmp(optarg, "default") == 0)
3913				report_type = RPL_REPORT_DEFAULT;
3914			else if (strcasecmp(optarg, "wellknown") == 0)
3915				report_type = RPL_REPORT_WELLKNOWN;
3916			else if (strcasecmp(optarg, "all") == 0)
3917				report_type = RPL_REPORT_ALL;
3918			else {
3919				warnx("%s: invalid report type \"%s\"",
3920				      __func__, optarg);
3921				retval = 1;
3922				goto bailout;
3923			}
3924			break;
3925		default:
3926			break;
3927		}
3928	}
3929
3930	if ((countonly != 0)
3931	 && (lunsonly != 0)) {
3932		warnx("%s: you can only specify one of -c or -l", __func__);
3933		retval = 1;
3934		goto bailout;
3935	}
3936	/*
3937	 * According to SPC-4, the allocation length must be at least 16
3938	 * bytes -- enough for the header and one LUN.
3939	 */
3940	alloc_len = sizeof(*lundata) + 8;
3941
3942retry:
3943
3944	lundata = malloc(alloc_len);
3945
3946	if (lundata == NULL) {
3947		warn("%s: error mallocing %d bytes", __func__, alloc_len);
3948		retval = 1;
3949		goto bailout;
3950	}
3951
3952	scsi_report_luns(&ccb->csio,
3953			 /*retries*/ retry_count,
3954			 /*cbfcnp*/ NULL,
3955			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3956			 /*select_report*/ report_type,
3957			 /*rpl_buf*/ lundata,
3958			 /*alloc_len*/ alloc_len,
3959			 /*sense_len*/ SSD_FULL_SIZE,
3960			 /*timeout*/ timeout ? timeout : 5000);
3961
3962	/* Disable freezing the device queue */
3963	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3964
3965	if (arglist & CAM_ARG_ERR_RECOVER)
3966		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3967
3968	if (cam_send_ccb(device, ccb) < 0) {
3969		warn("error sending REPORT LUNS command");
3970
3971		if (arglist & CAM_ARG_VERBOSE)
3972			cam_error_print(device, ccb, CAM_ESF_ALL,
3973					CAM_EPF_ALL, stderr);
3974
3975		retval = 1;
3976		goto bailout;
3977	}
3978
3979	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3980		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3981		retval = 1;
3982		goto bailout;
3983	}
3984
3985
3986	list_len = scsi_4btoul(lundata->length);
3987
3988	/*
3989	 * If we need to list the LUNs, and our allocation
3990	 * length was too short, reallocate and retry.
3991	 */
3992	if ((countonly == 0)
3993	 && (list_len > (alloc_len - sizeof(*lundata)))) {
3994		alloc_len = list_len + sizeof(*lundata);
3995		free(lundata);
3996		goto retry;
3997	}
3998
3999	if (lunsonly == 0)
4000		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
4001			((list_len / 8) > 1) ? "s" : "");
4002
4003	if (countonly != 0)
4004		goto bailout;
4005
4006	for (i = 0; i < (list_len / 8); i++) {
4007		int no_more;
4008
4009		no_more = 0;
4010		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4011			if (j != 0)
4012				fprintf(stdout, ",");
4013			switch (lundata->luns[i].lundata[j] &
4014				RPL_LUNDATA_ATYP_MASK) {
4015			case RPL_LUNDATA_ATYP_PERIPH:
4016				if ((lundata->luns[i].lundata[j] &
4017				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4018					fprintf(stdout, "%d:",
4019						lundata->luns[i].lundata[j] &
4020						RPL_LUNDATA_PERIPH_BUS_MASK);
4021				else if ((j == 0)
4022				      && ((lundata->luns[i].lundata[j+2] &
4023					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4024					no_more = 1;
4025
4026				fprintf(stdout, "%d",
4027					lundata->luns[i].lundata[j+1]);
4028				break;
4029			case RPL_LUNDATA_ATYP_FLAT: {
4030				uint8_t tmplun[2];
4031				tmplun[0] = lundata->luns[i].lundata[j] &
4032					RPL_LUNDATA_FLAT_LUN_MASK;
4033				tmplun[1] = lundata->luns[i].lundata[j+1];
4034
4035				fprintf(stdout, "%d", scsi_2btoul(tmplun));
4036				no_more = 1;
4037				break;
4038			}
4039			case RPL_LUNDATA_ATYP_LUN:
4040				fprintf(stdout, "%d:%d:%d",
4041					(lundata->luns[i].lundata[j+1] &
4042					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4043					lundata->luns[i].lundata[j] &
4044					RPL_LUNDATA_LUN_TARG_MASK,
4045					lundata->luns[i].lundata[j+1] &
4046					RPL_LUNDATA_LUN_LUN_MASK);
4047				break;
4048			case RPL_LUNDATA_ATYP_EXTLUN: {
4049				int field_len, field_len_code, eam_code;
4050
4051				eam_code = lundata->luns[i].lundata[j] &
4052					RPL_LUNDATA_EXT_EAM_MASK;
4053				field_len_code = (lundata->luns[i].lundata[j] &
4054					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4055				field_len = field_len_code * 2;
4056
4057				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4058				 && (field_len_code == 0x00)) {
4059					fprintf(stdout, "%d",
4060						lundata->luns[i].lundata[j+1]);
4061				} else if ((eam_code ==
4062					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4063					&& (field_len_code == 0x03)) {
4064					uint8_t tmp_lun[8];
4065
4066					/*
4067					 * This format takes up all 8 bytes.
4068					 * If we aren't starting at offset 0,
4069					 * that's a bug.
4070					 */
4071					if (j != 0) {
4072						fprintf(stdout, "Invalid "
4073							"offset %d for "
4074							"Extended LUN not "
4075							"specified format", j);
4076						no_more = 1;
4077						break;
4078					}
4079					bzero(tmp_lun, sizeof(tmp_lun));
4080					bcopy(&lundata->luns[i].lundata[j+1],
4081					      &tmp_lun[1], sizeof(tmp_lun) - 1);
4082					fprintf(stdout, "%#jx",
4083					       (intmax_t)scsi_8btou64(tmp_lun));
4084					no_more = 1;
4085				} else {
4086					fprintf(stderr, "Unknown Extended LUN"
4087						"Address method %#x, length "
4088						"code %#x", eam_code,
4089						field_len_code);
4090					no_more = 1;
4091				}
4092				break;
4093			}
4094			default:
4095				fprintf(stderr, "Unknown LUN address method "
4096					"%#x\n", lundata->luns[i].lundata[0] &
4097					RPL_LUNDATA_ATYP_MASK);
4098				break;
4099			}
4100			/*
4101			 * For the flat addressing method, there are no
4102			 * other levels after it.
4103			 */
4104			if (no_more != 0)
4105				break;
4106		}
4107		fprintf(stdout, "\n");
4108	}
4109
4110bailout:
4111
4112	cam_freeccb(ccb);
4113
4114	free(lundata);
4115
4116	return (retval);
4117}
4118
4119static int
4120scsireadcapacity(struct cam_device *device, int argc, char **argv,
4121		 char *combinedopt, int retry_count, int timeout)
4122{
4123	union ccb *ccb;
4124	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4125	struct scsi_read_capacity_data rcap;
4126	struct scsi_read_capacity_data_long rcaplong;
4127	uint64_t maxsector;
4128	uint32_t block_len;
4129	int retval;
4130	int c;
4131
4132	blocksizeonly = 0;
4133	humanize = 0;
4134	numblocks = 0;
4135	quiet = 0;
4136	sizeonly = 0;
4137	baseten = 0;
4138	retval = 0;
4139
4140	ccb = cam_getccb(device);
4141
4142	if (ccb == NULL) {
4143		warnx("%s: error allocating ccb", __func__);
4144		return (1);
4145	}
4146
4147	bzero(&(&ccb->ccb_h)[1],
4148	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4149
4150	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4151		switch (c) {
4152		case 'b':
4153			blocksizeonly++;
4154			break;
4155		case 'h':
4156			humanize++;
4157			baseten = 0;
4158			break;
4159		case 'H':
4160			humanize++;
4161			baseten++;
4162			break;
4163		case 'N':
4164			numblocks++;
4165			break;
4166		case 'q':
4167			quiet++;
4168			break;
4169		case 's':
4170			sizeonly++;
4171			break;
4172		default:
4173			break;
4174		}
4175	}
4176
4177	if ((blocksizeonly != 0)
4178	 && (numblocks != 0)) {
4179		warnx("%s: you can only specify one of -b or -N", __func__);
4180		retval = 1;
4181		goto bailout;
4182	}
4183
4184	if ((blocksizeonly != 0)
4185	 && (sizeonly != 0)) {
4186		warnx("%s: you can only specify one of -b or -s", __func__);
4187		retval = 1;
4188		goto bailout;
4189	}
4190
4191	if ((humanize != 0)
4192	 && (quiet != 0)) {
4193		warnx("%s: you can only specify one of -h/-H or -q", __func__);
4194		retval = 1;
4195		goto bailout;
4196	}
4197
4198	if ((humanize != 0)
4199	 && (blocksizeonly != 0)) {
4200		warnx("%s: you can only specify one of -h/-H or -b", __func__);
4201		retval = 1;
4202		goto bailout;
4203	}
4204
4205	scsi_read_capacity(&ccb->csio,
4206			   /*retries*/ retry_count,
4207			   /*cbfcnp*/ NULL,
4208			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
4209			   &rcap,
4210			   SSD_FULL_SIZE,
4211			   /*timeout*/ timeout ? timeout : 5000);
4212
4213	/* Disable freezing the device queue */
4214	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4215
4216	if (arglist & CAM_ARG_ERR_RECOVER)
4217		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4218
4219	if (cam_send_ccb(device, ccb) < 0) {
4220		warn("error sending READ CAPACITY command");
4221
4222		if (arglist & CAM_ARG_VERBOSE)
4223			cam_error_print(device, ccb, CAM_ESF_ALL,
4224					CAM_EPF_ALL, stderr);
4225
4226		retval = 1;
4227		goto bailout;
4228	}
4229
4230	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4231		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4232		retval = 1;
4233		goto bailout;
4234	}
4235
4236	maxsector = scsi_4btoul(rcap.addr);
4237	block_len = scsi_4btoul(rcap.length);
4238
4239	/*
4240	 * A last block of 2^32-1 means that the true capacity is over 2TB,
4241	 * and we need to issue the long READ CAPACITY to get the real
4242	 * capacity.  Otherwise, we're all set.
4243	 */
4244	if (maxsector != 0xffffffff)
4245		goto do_print;
4246
4247	scsi_read_capacity_16(&ccb->csio,
4248			      /*retries*/ retry_count,
4249			      /*cbfcnp*/ NULL,
4250			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
4251			      /*lba*/ 0,
4252			      /*reladdr*/ 0,
4253			      /*pmi*/ 0,
4254			      &rcaplong,
4255			      /*sense_len*/ SSD_FULL_SIZE,
4256			      /*timeout*/ timeout ? timeout : 5000);
4257
4258	/* Disable freezing the device queue */
4259	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4260
4261	if (arglist & CAM_ARG_ERR_RECOVER)
4262		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4263
4264	if (cam_send_ccb(device, ccb) < 0) {
4265		warn("error sending READ CAPACITY (16) command");
4266
4267		if (arglist & CAM_ARG_VERBOSE)
4268			cam_error_print(device, ccb, CAM_ESF_ALL,
4269					CAM_EPF_ALL, stderr);
4270
4271		retval = 1;
4272		goto bailout;
4273	}
4274
4275	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4276		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4277		retval = 1;
4278		goto bailout;
4279	}
4280
4281	maxsector = scsi_8btou64(rcaplong.addr);
4282	block_len = scsi_4btoul(rcaplong.length);
4283
4284do_print:
4285	if (blocksizeonly == 0) {
4286		/*
4287		 * Humanize implies !quiet, and also implies numblocks.
4288		 */
4289		if (humanize != 0) {
4290			char tmpstr[6];
4291			int64_t tmpbytes;
4292			int ret;
4293
4294			tmpbytes = (maxsector + 1) * block_len;
4295			ret = humanize_number(tmpstr, sizeof(tmpstr),
4296					      tmpbytes, "", HN_AUTOSCALE,
4297					      HN_B | HN_DECIMAL |
4298					      ((baseten != 0) ?
4299					      HN_DIVISOR_1000 : 0));
4300			if (ret == -1) {
4301				warnx("%s: humanize_number failed!", __func__);
4302				retval = 1;
4303				goto bailout;
4304			}
4305			fprintf(stdout, "Device Size: %s%s", tmpstr,
4306				(sizeonly == 0) ?  ", " : "\n");
4307		} else if (numblocks != 0) {
4308			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4309				"Blocks: " : "", (uintmax_t)maxsector + 1,
4310				(sizeonly == 0) ? ", " : "\n");
4311		} else {
4312			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4313				"Last Block: " : "", (uintmax_t)maxsector,
4314				(sizeonly == 0) ? ", " : "\n");
4315		}
4316	}
4317	if (sizeonly == 0)
4318		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4319			"Block Length: " : "", block_len, (quiet == 0) ?
4320			" bytes" : "");
4321bailout:
4322	cam_freeccb(ccb);
4323
4324	return (retval);
4325}
4326
4327static int
4328smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4329       int retry_count, int timeout)
4330{
4331	int c, error;
4332	union ccb *ccb;
4333	uint8_t *smp_request = NULL, *smp_response = NULL;
4334	int request_size = 0, response_size = 0;
4335	int fd_request = 0, fd_response = 0;
4336	char *datastr = NULL;
4337	struct get_hook hook;
4338	int retval;
4339	int flags = 0;
4340
4341	/*
4342	 * Note that at the moment we don't support sending SMP CCBs to
4343	 * devices that aren't probed by CAM.
4344	 */
4345	ccb = cam_getccb(device);
4346	if (ccb == NULL) {
4347		warnx("%s: error allocating CCB", __func__);
4348		return (1);
4349	}
4350
4351	bzero(&(&ccb->ccb_h)[1],
4352	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4353
4354	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4355		switch (c) {
4356		case 'R':
4357			arglist |= CAM_ARG_CMD_IN;
4358			response_size = strtol(optarg, NULL, 0);
4359			if (response_size <= 0) {
4360				warnx("invalid number of response bytes %d",
4361				      response_size);
4362				error = 1;
4363				goto smpcmd_bailout;
4364			}
4365			hook.argc = argc - optind;
4366			hook.argv = argv + optind;
4367			hook.got = 0;
4368			optind++;
4369			datastr = cget(&hook, NULL);
4370			/*
4371			 * If the user supplied "-" instead of a format, he
4372			 * wants the data to be written to stdout.
4373			 */
4374			if ((datastr != NULL)
4375			 && (datastr[0] == '-'))
4376				fd_response = 1;
4377
4378			smp_response = (u_int8_t *)malloc(response_size);
4379			if (smp_response == NULL) {
4380				warn("can't malloc memory for SMP response");
4381				error = 1;
4382				goto smpcmd_bailout;
4383			}
4384			break;
4385		case 'r':
4386			arglist |= CAM_ARG_CMD_OUT;
4387			request_size = strtol(optarg, NULL, 0);
4388			if (request_size <= 0) {
4389				warnx("invalid number of request bytes %d",
4390				      request_size);
4391				error = 1;
4392				goto smpcmd_bailout;
4393			}
4394			hook.argc = argc - optind;
4395			hook.argv = argv + optind;
4396			hook.got = 0;
4397			datastr = cget(&hook, NULL);
4398			smp_request = (u_int8_t *)malloc(request_size);
4399			if (smp_request == NULL) {
4400				warn("can't malloc memory for SMP request");
4401				error = 1;
4402				goto smpcmd_bailout;
4403			}
4404			bzero(smp_request, request_size);
4405			/*
4406			 * If the user supplied "-" instead of a format, he
4407			 * wants the data to be read from stdin.
4408			 */
4409			if ((datastr != NULL)
4410			 && (datastr[0] == '-'))
4411				fd_request = 1;
4412			else
4413				buff_encode_visit(smp_request, request_size,
4414						  datastr,
4415						  iget, &hook);
4416			optind += hook.got;
4417			break;
4418		default:
4419			break;
4420		}
4421	}
4422
4423	/*
4424	 * If fd_data is set, and we're writing to the device, we need to
4425	 * read the data the user wants written from stdin.
4426	 */
4427	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4428		ssize_t amt_read;
4429		int amt_to_read = request_size;
4430		u_int8_t *buf_ptr = smp_request;
4431
4432		for (amt_read = 0; amt_to_read > 0;
4433		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4434			if (amt_read == -1) {
4435				warn("error reading data from stdin");
4436				error = 1;
4437				goto smpcmd_bailout;
4438			}
4439			amt_to_read -= amt_read;
4440			buf_ptr += amt_read;
4441		}
4442	}
4443
4444	if (((arglist & CAM_ARG_CMD_IN) == 0)
4445	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
4446		warnx("%s: need both the request (-r) and response (-R) "
4447		      "arguments", __func__);
4448		error = 1;
4449		goto smpcmd_bailout;
4450	}
4451
4452	flags |= CAM_DEV_QFRZDIS;
4453
4454	cam_fill_smpio(&ccb->smpio,
4455		       /*retries*/ retry_count,
4456		       /*cbfcnp*/ NULL,
4457		       /*flags*/ flags,
4458		       /*smp_request*/ smp_request,
4459		       /*smp_request_len*/ request_size,
4460		       /*smp_response*/ smp_response,
4461		       /*smp_response_len*/ response_size,
4462		       /*timeout*/ timeout ? timeout : 5000);
4463
4464	ccb->smpio.flags = SMP_FLAG_NONE;
4465
4466	if (((retval = cam_send_ccb(device, ccb)) < 0)
4467	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4468		const char *warnstr = "error sending command";
4469
4470		if (retval < 0)
4471			warn(warnstr);
4472		else
4473			warnx(warnstr);
4474
4475		if (arglist & CAM_ARG_VERBOSE) {
4476			cam_error_print(device, ccb, CAM_ESF_ALL,
4477					CAM_EPF_ALL, stderr);
4478		}
4479	}
4480
4481	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4482	 && (response_size > 0)) {
4483		if (fd_response == 0) {
4484			buff_decode_visit(smp_response, response_size,
4485					  datastr, arg_put, NULL);
4486			fprintf(stdout, "\n");
4487		} else {
4488			ssize_t amt_written;
4489			int amt_to_write = response_size;
4490			u_int8_t *buf_ptr = smp_response;
4491
4492			for (amt_written = 0; (amt_to_write > 0) &&
4493			     (amt_written = write(STDOUT_FILENO, buf_ptr,
4494						  amt_to_write)) > 0;){
4495				amt_to_write -= amt_written;
4496				buf_ptr += amt_written;
4497			}
4498			if (amt_written == -1) {
4499				warn("error writing data to stdout");
4500				error = 1;
4501				goto smpcmd_bailout;
4502			} else if ((amt_written == 0)
4503				&& (amt_to_write > 0)) {
4504				warnx("only wrote %u bytes out of %u",
4505				      response_size - amt_to_write,
4506				      response_size);
4507			}
4508		}
4509	}
4510smpcmd_bailout:
4511	if (ccb != NULL)
4512		cam_freeccb(ccb);
4513
4514	if (smp_request != NULL)
4515		free(smp_request);
4516
4517	if (smp_response != NULL)
4518		free(smp_response);
4519
4520	return (error);
4521}
4522
4523static int
4524smpreportgeneral(struct cam_device *device, int argc, char **argv,
4525		 char *combinedopt, int retry_count, int timeout)
4526{
4527	union ccb *ccb;
4528	struct smp_report_general_request *request = NULL;
4529	struct smp_report_general_response *response = NULL;
4530	struct sbuf *sb = NULL;
4531	int error = 0;
4532	int c, long_response = 0;
4533	int retval;
4534
4535	/*
4536	 * Note that at the moment we don't support sending SMP CCBs to
4537	 * devices that aren't probed by CAM.
4538	 */
4539	ccb = cam_getccb(device);
4540	if (ccb == NULL) {
4541		warnx("%s: error allocating CCB", __func__);
4542		return (1);
4543	}
4544
4545	bzero(&(&ccb->ccb_h)[1],
4546	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4547
4548	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4549		switch (c) {
4550		case 'l':
4551			long_response = 1;
4552			break;
4553		default:
4554			break;
4555		}
4556	}
4557	request = malloc(sizeof(*request));
4558	if (request == NULL) {
4559		warn("%s: unable to allocate %zd bytes", __func__,
4560		     sizeof(*request));
4561		error = 1;
4562		goto bailout;
4563	}
4564
4565	response = malloc(sizeof(*response));
4566	if (response == NULL) {
4567		warn("%s: unable to allocate %zd bytes", __func__,
4568		     sizeof(*response));
4569		error = 1;
4570		goto bailout;
4571	}
4572
4573try_long:
4574	smp_report_general(&ccb->smpio,
4575			   retry_count,
4576			   /*cbfcnp*/ NULL,
4577			   request,
4578			   /*request_len*/ sizeof(*request),
4579			   (uint8_t *)response,
4580			   /*response_len*/ sizeof(*response),
4581			   /*long_response*/ long_response,
4582			   timeout);
4583
4584	if (((retval = cam_send_ccb(device, ccb)) < 0)
4585	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4586		const char *warnstr = "error sending command";
4587
4588		if (retval < 0)
4589			warn(warnstr);
4590		else
4591			warnx(warnstr);
4592
4593		if (arglist & CAM_ARG_VERBOSE) {
4594			cam_error_print(device, ccb, CAM_ESF_ALL,
4595					CAM_EPF_ALL, stderr);
4596		}
4597		error = 1;
4598		goto bailout;
4599	}
4600
4601	/*
4602	 * If the device supports the long response bit, try again and see
4603	 * if we can get all of the data.
4604	 */
4605	if ((response->long_response & SMP_RG_LONG_RESPONSE)
4606	 && (long_response == 0)) {
4607		ccb->ccb_h.status = CAM_REQ_INPROG;
4608		bzero(&(&ccb->ccb_h)[1],
4609		      sizeof(union ccb) - sizeof(struct ccb_hdr));
4610		long_response = 1;
4611		goto try_long;
4612	}
4613
4614	/*
4615	 * XXX KDM detect and decode SMP errors here.
4616	 */
4617	sb = sbuf_new_auto();
4618	if (sb == NULL) {
4619		warnx("%s: error allocating sbuf", __func__);
4620		goto bailout;
4621	}
4622
4623	smp_report_general_sbuf(response, sizeof(*response), sb);
4624
4625	sbuf_finish(sb);
4626
4627	printf("%s", sbuf_data(sb));
4628
4629bailout:
4630	if (ccb != NULL)
4631		cam_freeccb(ccb);
4632
4633	if (request != NULL)
4634		free(request);
4635
4636	if (response != NULL)
4637		free(response);
4638
4639	if (sb != NULL)
4640		sbuf_delete(sb);
4641
4642	return (error);
4643}
4644
4645struct camcontrol_opts phy_ops[] = {
4646	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
4647	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
4648	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
4649	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
4650	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
4651	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
4652	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
4653	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
4654	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
4655	{NULL, 0, 0, NULL}
4656};
4657
4658static int
4659smpphycontrol(struct cam_device *device, int argc, char **argv,
4660	      char *combinedopt, int retry_count, int timeout)
4661{
4662	union ccb *ccb;
4663	struct smp_phy_control_request *request = NULL;
4664	struct smp_phy_control_response *response = NULL;
4665	int long_response = 0;
4666	int retval = 0;
4667	int phy = -1;
4668	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
4669	int phy_op_set = 0;
4670	uint64_t attached_dev_name = 0;
4671	int dev_name_set = 0;
4672	uint32_t min_plr = 0, max_plr = 0;
4673	uint32_t pp_timeout_val = 0;
4674	int slumber_partial = 0;
4675	int set_pp_timeout_val = 0;
4676	int c;
4677
4678	/*
4679	 * Note that at the moment we don't support sending SMP CCBs to
4680	 * devices that aren't probed by CAM.
4681	 */
4682	ccb = cam_getccb(device);
4683	if (ccb == NULL) {
4684		warnx("%s: error allocating CCB", __func__);
4685		return (1);
4686	}
4687
4688	bzero(&(&ccb->ccb_h)[1],
4689	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4690
4691	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4692		switch (c) {
4693		case 'a':
4694		case 'A':
4695		case 's':
4696		case 'S': {
4697			int enable = -1;
4698
4699			if (strcasecmp(optarg, "enable") == 0)
4700				enable = 1;
4701			else if (strcasecmp(optarg, "disable") == 0)
4702				enable = 2;
4703			else {
4704				warnx("%s: Invalid argument %s", __func__,
4705				      optarg);
4706				retval = 1;
4707				goto bailout;
4708			}
4709			switch (c) {
4710			case 's':
4711				slumber_partial |= enable <<
4712						   SMP_PC_SAS_SLUMBER_SHIFT;
4713				break;
4714			case 'S':
4715				slumber_partial |= enable <<
4716						   SMP_PC_SAS_PARTIAL_SHIFT;
4717				break;
4718			case 'a':
4719				slumber_partial |= enable <<
4720						   SMP_PC_SATA_SLUMBER_SHIFT;
4721				break;
4722			case 'A':
4723				slumber_partial |= enable <<
4724						   SMP_PC_SATA_PARTIAL_SHIFT;
4725				break;
4726			default:
4727				warnx("%s: programmer error", __func__);
4728				retval = 1;
4729				goto bailout;
4730				break; /*NOTREACHED*/
4731			}
4732			break;
4733		}
4734		case 'd':
4735			attached_dev_name = (uintmax_t)strtoumax(optarg,
4736								 NULL,0);
4737			dev_name_set = 1;
4738			break;
4739		case 'l':
4740			long_response = 1;
4741			break;
4742		case 'm':
4743			/*
4744			 * We don't do extensive checking here, so this
4745			 * will continue to work when new speeds come out.
4746			 */
4747			min_plr = strtoul(optarg, NULL, 0);
4748			if ((min_plr == 0)
4749			 || (min_plr > 0xf)) {
4750				warnx("%s: invalid link rate %x",
4751				      __func__, min_plr);
4752				retval = 1;
4753				goto bailout;
4754			}
4755			break;
4756		case 'M':
4757			/*
4758			 * We don't do extensive checking here, so this
4759			 * will continue to work when new speeds come out.
4760			 */
4761			max_plr = strtoul(optarg, NULL, 0);
4762			if ((max_plr == 0)
4763			 || (max_plr > 0xf)) {
4764				warnx("%s: invalid link rate %x",
4765				      __func__, max_plr);
4766				retval = 1;
4767				goto bailout;
4768			}
4769			break;
4770		case 'o': {
4771			camcontrol_optret optreturn;
4772			cam_argmask argnums;
4773			const char *subopt;
4774
4775			if (phy_op_set != 0) {
4776				warnx("%s: only one phy operation argument "
4777				      "(-o) allowed", __func__);
4778				retval = 1;
4779				goto bailout;
4780			}
4781
4782			phy_op_set = 1;
4783
4784			/*
4785			 * Allow the user to specify the phy operation
4786			 * numerically, as well as with a name.  This will
4787			 * future-proof it a bit, so options that are added
4788			 * in future specs can be used.
4789			 */
4790			if (isdigit(optarg[0])) {
4791				phy_operation = strtoul(optarg, NULL, 0);
4792				if ((phy_operation == 0)
4793				 || (phy_operation > 0xff)) {
4794					warnx("%s: invalid phy operation %#x",
4795					      __func__, phy_operation);
4796					retval = 1;
4797					goto bailout;
4798				}
4799				break;
4800			}
4801			optreturn = getoption(phy_ops, optarg, &phy_operation,
4802					      &argnums, &subopt);
4803
4804			if (optreturn == CC_OR_AMBIGUOUS) {
4805				warnx("%s: ambiguous option %s", __func__,
4806				      optarg);
4807				usage(0);
4808				retval = 1;
4809				goto bailout;
4810			} else if (optreturn == CC_OR_NOT_FOUND) {
4811				warnx("%s: option %s not found", __func__,
4812				      optarg);
4813				usage(0);
4814				retval = 1;
4815				goto bailout;
4816			}
4817			break;
4818		}
4819		case 'p':
4820			phy = atoi(optarg);
4821			break;
4822		case 'T':
4823			pp_timeout_val = strtoul(optarg, NULL, 0);
4824			if (pp_timeout_val > 15) {
4825				warnx("%s: invalid partial pathway timeout "
4826				      "value %u, need a value less than 16",
4827				      __func__, pp_timeout_val);
4828				retval = 1;
4829				goto bailout;
4830			}
4831			set_pp_timeout_val = 1;
4832			break;
4833		default:
4834			break;
4835		}
4836	}
4837
4838	if (phy == -1) {
4839		warnx("%s: a PHY (-p phy) argument is required",__func__);
4840		retval = 1;
4841		goto bailout;
4842	}
4843
4844	if (((dev_name_set != 0)
4845	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
4846	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
4847	  && (dev_name_set == 0))) {
4848		warnx("%s: -d name and -o setdevname arguments both "
4849		      "required to set device name", __func__);
4850		retval = 1;
4851		goto bailout;
4852	}
4853
4854	request = malloc(sizeof(*request));
4855	if (request == NULL) {
4856		warn("%s: unable to allocate %zd bytes", __func__,
4857		     sizeof(*request));
4858		retval = 1;
4859		goto bailout;
4860	}
4861
4862	response = malloc(sizeof(*response));
4863	if (response == NULL) {
4864		warn("%s: unable to allocate %zd bytes", __func__,
4865		     sizeof(*request));
4866		retval = 1;
4867		goto bailout;
4868	}
4869
4870	smp_phy_control(&ccb->smpio,
4871			retry_count,
4872			/*cbfcnp*/ NULL,
4873			request,
4874			sizeof(*request),
4875			(uint8_t *)response,
4876			sizeof(*response),
4877			long_response,
4878			/*expected_exp_change_count*/ 0,
4879			phy,
4880			phy_operation,
4881			(set_pp_timeout_val != 0) ? 1 : 0,
4882			attached_dev_name,
4883			min_plr,
4884			max_plr,
4885			slumber_partial,
4886			pp_timeout_val,
4887			timeout);
4888
4889	if (((retval = cam_send_ccb(device, ccb)) < 0)
4890	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4891		const char *warnstr = "error sending command";
4892
4893		if (retval < 0)
4894			warn(warnstr);
4895		else
4896			warnx(warnstr);
4897
4898		if (arglist & CAM_ARG_VERBOSE) {
4899			/*
4900			 * Use CAM_EPF_NORMAL so we only get one line of
4901			 * SMP command decoding.
4902			 */
4903			cam_error_print(device, ccb, CAM_ESF_ALL,
4904					CAM_EPF_NORMAL, stderr);
4905		}
4906		retval = 1;
4907		goto bailout;
4908	}
4909
4910	/* XXX KDM print out something here for success? */
4911bailout:
4912	if (ccb != NULL)
4913		cam_freeccb(ccb);
4914
4915	if (request != NULL)
4916		free(request);
4917
4918	if (response != NULL)
4919		free(response);
4920
4921	return (retval);
4922}
4923
4924static int
4925smpmaninfo(struct cam_device *device, int argc, char **argv,
4926	   char *combinedopt, int retry_count, int timeout)
4927{
4928	union ccb *ccb;
4929	struct smp_report_manuf_info_request request;
4930	struct smp_report_manuf_info_response response;
4931	struct sbuf *sb = NULL;
4932	int long_response = 0;
4933	int retval = 0;
4934	int c;
4935
4936	/*
4937	 * Note that at the moment we don't support sending SMP CCBs to
4938	 * devices that aren't probed by CAM.
4939	 */
4940	ccb = cam_getccb(device);
4941	if (ccb == NULL) {
4942		warnx("%s: error allocating CCB", __func__);
4943		return (1);
4944	}
4945
4946	bzero(&(&ccb->ccb_h)[1],
4947	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4948
4949	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4950		switch (c) {
4951		case 'l':
4952			long_response = 1;
4953			break;
4954		default:
4955			break;
4956		}
4957	}
4958	bzero(&request, sizeof(request));
4959	bzero(&response, sizeof(response));
4960
4961	smp_report_manuf_info(&ccb->smpio,
4962			      retry_count,
4963			      /*cbfcnp*/ NULL,
4964			      &request,
4965			      sizeof(request),
4966			      (uint8_t *)&response,
4967			      sizeof(response),
4968			      long_response,
4969			      timeout);
4970
4971	if (((retval = cam_send_ccb(device, ccb)) < 0)
4972	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4973		const char *warnstr = "error sending command";
4974
4975		if (retval < 0)
4976			warn(warnstr);
4977		else
4978			warnx(warnstr);
4979
4980		if (arglist & CAM_ARG_VERBOSE) {
4981			cam_error_print(device, ccb, CAM_ESF_ALL,
4982					CAM_EPF_ALL, stderr);
4983		}
4984		retval = 1;
4985		goto bailout;
4986	}
4987
4988	sb = sbuf_new_auto();
4989	if (sb == NULL) {
4990		warnx("%s: error allocating sbuf", __func__);
4991		goto bailout;
4992	}
4993
4994	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
4995
4996	sbuf_finish(sb);
4997
4998	printf("%s", sbuf_data(sb));
4999
5000bailout:
5001
5002	if (ccb != NULL)
5003		cam_freeccb(ccb);
5004
5005	if (sb != NULL)
5006		sbuf_delete(sb);
5007
5008	return (retval);
5009}
5010
5011static int
5012getdevid(struct cam_devitem *item)
5013{
5014	int retval = 0;
5015	union ccb *ccb = NULL;
5016
5017	struct cam_device *dev;
5018
5019	dev = cam_open_btl(item->dev_match.path_id,
5020			   item->dev_match.target_id,
5021			   item->dev_match.target_lun, O_RDWR, NULL);
5022
5023	if (dev == NULL) {
5024		warnx("%s", cam_errbuf);
5025		retval = 1;
5026		goto bailout;
5027	}
5028
5029	item->device_id_len = 0;
5030
5031	ccb = cam_getccb(dev);
5032	if (ccb == NULL) {
5033		warnx("%s: error allocating CCB", __func__);
5034		retval = 1;
5035		goto bailout;
5036	}
5037
5038	bzero(&(&ccb->ccb_h)[1],
5039	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5040
5041	/*
5042	 * On the first try, we just probe for the size of the data, and
5043	 * then allocate that much memory and try again.
5044	 */
5045retry:
5046	ccb->ccb_h.func_code = XPT_GDEV_ADVINFO;
5047	ccb->ccb_h.flags = CAM_DIR_IN;
5048	ccb->cgdai.flags = CGDAI_FLAG_PROTO;
5049	ccb->cgdai.buftype = CGDAI_TYPE_SCSI_DEVID;
5050	ccb->cgdai.bufsiz = item->device_id_len;
5051	if (item->device_id_len != 0)
5052		ccb->cgdai.buf = (uint8_t *)item->device_id;
5053
5054	if (cam_send_ccb(dev, ccb) < 0) {
5055		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
5056		retval = 1;
5057		goto bailout;
5058	}
5059
5060	if (ccb->ccb_h.status != CAM_REQ_CMP) {
5061		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
5062		retval = 1;
5063		goto bailout;
5064	}
5065
5066	if (item->device_id_len == 0) {
5067		/*
5068		 * This is our first time through.  Allocate the buffer,
5069		 * and then go back to get the data.
5070		 */
5071		if (ccb->cgdai.provsiz == 0) {
5072			warnx("%s: invalid .provsiz field returned with "
5073			     "XPT_GDEV_ADVINFO CCB", __func__);
5074			retval = 1;
5075			goto bailout;
5076		}
5077		item->device_id_len = ccb->cgdai.provsiz;
5078		item->device_id = malloc(item->device_id_len);
5079		if (item->device_id == NULL) {
5080			warn("%s: unable to allocate %d bytes", __func__,
5081			     item->device_id_len);
5082			retval = 1;
5083			goto bailout;
5084		}
5085		ccb->ccb_h.status = CAM_REQ_INPROG;
5086		goto retry;
5087	}
5088
5089bailout:
5090	if (dev != NULL)
5091		cam_close_device(dev);
5092
5093	if (ccb != NULL)
5094		cam_freeccb(ccb);
5095
5096	return (retval);
5097}
5098
5099/*
5100 * XXX KDM merge this code with getdevtree()?
5101 */
5102static int
5103buildbusdevlist(struct cam_devlist *devlist)
5104{
5105	union ccb ccb;
5106	int bufsize, fd = -1;
5107	struct dev_match_pattern *patterns;
5108	struct cam_devitem *item = NULL;
5109	int skip_device = 0;
5110	int retval = 0;
5111
5112	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
5113		warn("couldn't open %s", XPT_DEVICE);
5114		return(1);
5115	}
5116
5117	bzero(&ccb, sizeof(union ccb));
5118
5119	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
5120	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
5121	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
5122
5123	ccb.ccb_h.func_code = XPT_DEV_MATCH;
5124	bufsize = sizeof(struct dev_match_result) * 100;
5125	ccb.cdm.match_buf_len = bufsize;
5126	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
5127	if (ccb.cdm.matches == NULL) {
5128		warnx("can't malloc memory for matches");
5129		close(fd);
5130		return(1);
5131	}
5132	ccb.cdm.num_matches = 0;
5133	ccb.cdm.num_patterns = 2;
5134	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
5135		ccb.cdm.num_patterns;
5136
5137	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
5138	if (patterns == NULL) {
5139		warnx("can't malloc memory for patterns");
5140		retval = 1;
5141		goto bailout;
5142	}
5143
5144	ccb.cdm.patterns = patterns;
5145	bzero(patterns, ccb.cdm.pattern_buf_len);
5146
5147	patterns[0].type = DEV_MATCH_DEVICE;
5148	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
5149	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
5150	patterns[1].type = DEV_MATCH_PERIPH;
5151	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
5152	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
5153
5154	/*
5155	 * We do the ioctl multiple times if necessary, in case there are
5156	 * more than 100 nodes in the EDT.
5157	 */
5158	do {
5159		unsigned int i;
5160
5161		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
5162			warn("error sending CAMIOCOMMAND ioctl");
5163			retval = 1;
5164			goto bailout;
5165		}
5166
5167		if ((ccb.ccb_h.status != CAM_REQ_CMP)
5168		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
5169		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
5170			warnx("got CAM error %#x, CDM error %d\n",
5171			      ccb.ccb_h.status, ccb.cdm.status);
5172			retval = 1;
5173			goto bailout;
5174		}
5175
5176		for (i = 0; i < ccb.cdm.num_matches; i++) {
5177			switch (ccb.cdm.matches[i].type) {
5178			case DEV_MATCH_DEVICE: {
5179				struct device_match_result *dev_result;
5180
5181				dev_result =
5182				     &ccb.cdm.matches[i].result.device_result;
5183
5184				if (dev_result->flags &
5185				    DEV_RESULT_UNCONFIGURED) {
5186					skip_device = 1;
5187					break;
5188				} else
5189					skip_device = 0;
5190
5191				item = malloc(sizeof(*item));
5192				if (item == NULL) {
5193					warn("%s: unable to allocate %zd bytes",
5194					     __func__, sizeof(*item));
5195					retval = 1;
5196					goto bailout;
5197				}
5198				bzero(item, sizeof(*item));
5199				bcopy(dev_result, &item->dev_match,
5200				      sizeof(*dev_result));
5201				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
5202						   links);
5203
5204				if (getdevid(item) != 0) {
5205					retval = 1;
5206					goto bailout;
5207				}
5208				break;
5209			}
5210			case DEV_MATCH_PERIPH: {
5211				struct periph_match_result *periph_result;
5212
5213				periph_result =
5214				      &ccb.cdm.matches[i].result.periph_result;
5215
5216				if (skip_device != 0)
5217					break;
5218				item->num_periphs++;
5219				item->periph_matches = realloc(
5220					item->periph_matches,
5221					item->num_periphs *
5222					sizeof(struct periph_match_result));
5223				if (item->periph_matches == NULL) {
5224					warn("%s: error allocating periph "
5225					     "list", __func__);
5226					retval = 1;
5227					goto bailout;
5228				}
5229				bcopy(periph_result, &item->periph_matches[
5230				      item->num_periphs - 1],
5231				      sizeof(*periph_result));
5232				break;
5233			}
5234			default:
5235				fprintf(stderr, "%s: unexpected match "
5236					"type %d\n", __func__,
5237					ccb.cdm.matches[i].type);
5238				retval = 1;
5239				goto bailout;
5240				break; /*NOTREACHED*/
5241			}
5242		}
5243	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
5244		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
5245bailout:
5246
5247	if (fd != -1)
5248		close(fd);
5249
5250	free(patterns);
5251
5252	free(ccb.cdm.matches);
5253
5254	if (retval != 0)
5255		freebusdevlist(devlist);
5256
5257	return (retval);
5258}
5259
5260static void
5261freebusdevlist(struct cam_devlist *devlist)
5262{
5263	struct cam_devitem *item, *item2;
5264
5265	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
5266		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
5267			      links);
5268		free(item->device_id);
5269		free(item->periph_matches);
5270		free(item);
5271	}
5272}
5273
5274static struct cam_devitem *
5275findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
5276{
5277	struct cam_devitem *item;
5278
5279	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
5280		uint8_t *item_addr;
5281
5282		/*
5283		 * XXX KDM look for LUN IDs as well?
5284		 */
5285		item_addr = scsi_get_sas_addr(item->device_id,
5286					      item->device_id_len);
5287		if (item_addr == NULL)
5288			continue;
5289
5290		if (scsi_8btou64(item_addr) == sasaddr)
5291			return (item);
5292	}
5293
5294	return (NULL);
5295}
5296
5297static int
5298smpphylist(struct cam_device *device, int argc, char **argv,
5299	   char *combinedopt, int retry_count, int timeout)
5300{
5301	struct smp_report_general_request *rgrequest = NULL;
5302	struct smp_report_general_response *rgresponse = NULL;
5303	struct smp_discover_request *disrequest = NULL;
5304	struct smp_discover_response *disresponse = NULL;
5305	struct cam_devlist devlist;
5306	union ccb *ccb;
5307	int long_response = 0;
5308	int num_phys = 0;
5309	int quiet = 0;
5310	int retval;
5311	int i, c;
5312
5313	/*
5314	 * Note that at the moment we don't support sending SMP CCBs to
5315	 * devices that aren't probed by CAM.
5316	 */
5317	ccb = cam_getccb(device);
5318	if (ccb == NULL) {
5319		warnx("%s: error allocating CCB", __func__);
5320		return (1);
5321	}
5322
5323	bzero(&(&ccb->ccb_h)[1],
5324	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5325
5326	rgrequest = malloc(sizeof(*rgrequest));
5327	if (rgrequest == NULL) {
5328		warn("%s: unable to allocate %zd bytes", __func__,
5329		     sizeof(*rgrequest));
5330		retval = 1;
5331		goto bailout;
5332	}
5333
5334	rgresponse = malloc(sizeof(*rgresponse));
5335	if (rgresponse == NULL) {
5336		warn("%s: unable to allocate %zd bytes", __func__,
5337		     sizeof(*rgresponse));
5338		retval = 1;
5339		goto bailout;
5340	}
5341
5342	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5343		switch (c) {
5344		case 'l':
5345			long_response = 1;
5346			break;
5347		case 'q':
5348			quiet = 1;
5349			break;
5350		default:
5351			break;
5352		}
5353	}
5354
5355	smp_report_general(&ccb->smpio,
5356			   retry_count,
5357			   /*cbfcnp*/ NULL,
5358			   rgrequest,
5359			   /*request_len*/ sizeof(*rgrequest),
5360			   (uint8_t *)rgresponse,
5361			   /*response_len*/ sizeof(*rgresponse),
5362			   /*long_response*/ long_response,
5363			   timeout);
5364
5365	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5366
5367	if (((retval = cam_send_ccb(device, ccb)) < 0)
5368	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5369		const char *warnstr = "error sending command";
5370
5371		if (retval < 0)
5372			warn(warnstr);
5373		else
5374			warnx(warnstr);
5375
5376		if (arglist & CAM_ARG_VERBOSE) {
5377			cam_error_print(device, ccb, CAM_ESF_ALL,
5378					CAM_EPF_ALL, stderr);
5379		}
5380		retval = 1;
5381		goto bailout;
5382	}
5383
5384	num_phys = rgresponse->num_phys;
5385
5386	if (num_phys == 0) {
5387		if (quiet == 0)
5388			fprintf(stdout, "%s: No Phys reported\n", __func__);
5389		retval = 1;
5390		goto bailout;
5391	}
5392
5393	STAILQ_INIT(&devlist.dev_queue);
5394	devlist.path_id = device->path_id;
5395
5396	retval = buildbusdevlist(&devlist);
5397	if (retval != 0)
5398		goto bailout;
5399
5400	if (quiet == 0) {
5401		fprintf(stdout, "%d PHYs:\n", num_phys);
5402		fprintf(stdout, "PHY  Attached SAS Address\n");
5403	}
5404
5405	disrequest = malloc(sizeof(*disrequest));
5406	if (disrequest == NULL) {
5407		warn("%s: unable to allocate %zd bytes", __func__,
5408		     sizeof(*disrequest));
5409		retval = 1;
5410		goto bailout;
5411	}
5412
5413	disresponse = malloc(sizeof(*disresponse));
5414	if (disresponse == NULL) {
5415		warn("%s: unable to allocate %zd bytes", __func__,
5416		     sizeof(*disresponse));
5417		retval = 1;
5418		goto bailout;
5419	}
5420
5421	for (i = 0; i < num_phys; i++) {
5422		struct cam_devitem *item;
5423		struct device_match_result *dev_match;
5424		char vendor[16], product[48], revision[16];
5425		char tmpstr[256];
5426		int j;
5427
5428		bzero(&(&ccb->ccb_h)[1],
5429		      sizeof(union ccb) - sizeof(struct ccb_hdr));
5430
5431		ccb->ccb_h.status = CAM_REQ_INPROG;
5432		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5433
5434		smp_discover(&ccb->smpio,
5435			     retry_count,
5436			     /*cbfcnp*/ NULL,
5437			     disrequest,
5438			     sizeof(*disrequest),
5439			     (uint8_t *)disresponse,
5440			     sizeof(*disresponse),
5441			     long_response,
5442			     /*ignore_zone_group*/ 0,
5443			     /*phy*/ i,
5444			     timeout);
5445
5446		if (((retval = cam_send_ccb(device, ccb)) < 0)
5447		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
5448		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
5449			const char *warnstr = "error sending command";
5450
5451			if (retval < 0)
5452				warn(warnstr);
5453			else
5454				warnx(warnstr);
5455
5456			if (arglist & CAM_ARG_VERBOSE) {
5457				cam_error_print(device, ccb, CAM_ESF_ALL,
5458						CAM_EPF_ALL, stderr);
5459			}
5460			retval = 1;
5461			goto bailout;
5462		}
5463
5464		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
5465			if (quiet == 0)
5466				fprintf(stdout, "%3d  <vacant>\n", i);
5467			continue;
5468		}
5469
5470		item = findsasdevice(&devlist,
5471			scsi_8btou64(disresponse->attached_sas_address));
5472
5473		if ((quiet == 0)
5474		 || (item != NULL)) {
5475			fprintf(stdout, "%3d  0x%016jx", i,
5476				(uintmax_t)scsi_8btou64(
5477				disresponse->attached_sas_address));
5478			if (item == NULL) {
5479				fprintf(stdout, "\n");
5480				continue;
5481			}
5482		} else if (quiet != 0)
5483			continue;
5484
5485		dev_match = &item->dev_match;
5486
5487		if (dev_match->protocol == PROTO_SCSI) {
5488			cam_strvis(vendor, dev_match->inq_data.vendor,
5489				   sizeof(dev_match->inq_data.vendor),
5490				   sizeof(vendor));
5491			cam_strvis(product, dev_match->inq_data.product,
5492				   sizeof(dev_match->inq_data.product),
5493				   sizeof(product));
5494			cam_strvis(revision, dev_match->inq_data.revision,
5495				   sizeof(dev_match->inq_data.revision),
5496				   sizeof(revision));
5497			sprintf(tmpstr, "<%s %s %s>", vendor, product,
5498				revision);
5499		} else if ((dev_match->protocol == PROTO_ATA)
5500			|| (dev_match->protocol == PROTO_SATAPM)) {
5501			cam_strvis(product, dev_match->ident_data.model,
5502				   sizeof(dev_match->ident_data.model),
5503				   sizeof(product));
5504			cam_strvis(revision, dev_match->ident_data.revision,
5505				   sizeof(dev_match->ident_data.revision),
5506				   sizeof(revision));
5507			sprintf(tmpstr, "<%s %s>", product, revision);
5508		} else {
5509			sprintf(tmpstr, "<>");
5510		}
5511		fprintf(stdout, "   %-33s ", tmpstr);
5512
5513		/*
5514		 * If we have 0 periphs, that's a bug...
5515		 */
5516		if (item->num_periphs == 0) {
5517			fprintf(stdout, "\n");
5518			continue;
5519		}
5520
5521		fprintf(stdout, "(");
5522		for (j = 0; j < item->num_periphs; j++) {
5523			if (j > 0)
5524				fprintf(stdout, ",");
5525
5526			fprintf(stdout, "%s%d",
5527				item->periph_matches[j].periph_name,
5528				item->periph_matches[j].unit_number);
5529
5530		}
5531		fprintf(stdout, ")\n");
5532	}
5533bailout:
5534	if (ccb != NULL)
5535		cam_freeccb(ccb);
5536
5537	free(rgrequest);
5538
5539	free(rgresponse);
5540
5541	free(disrequest);
5542
5543	free(disresponse);
5544
5545	freebusdevlist(&devlist);
5546
5547	return (retval);
5548}
5549
5550static int
5551atapm(struct cam_device *device, int argc, char **argv,
5552		 char *combinedopt, int retry_count, int timeout)
5553{
5554	union ccb *ccb;
5555	int retval = 0;
5556	int t = -1;
5557	int c;
5558	u_char cmd, sc;
5559
5560	ccb = cam_getccb(device);
5561
5562	if (ccb == NULL) {
5563		warnx("%s: error allocating ccb", __func__);
5564		return (1);
5565	}
5566
5567	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5568		switch (c) {
5569		case 't':
5570			t = atoi(optarg);
5571			break;
5572		default:
5573			break;
5574		}
5575	}
5576	if (strcmp(argv[1], "idle") == 0) {
5577		if (t == -1)
5578			cmd = ATA_IDLE_IMMEDIATE;
5579		else
5580			cmd = ATA_IDLE_CMD;
5581	} else if (strcmp(argv[1], "standby") == 0) {
5582		if (t == -1)
5583			cmd = ATA_STANDBY_IMMEDIATE;
5584		else
5585			cmd = ATA_STANDBY_CMD;
5586	} else {
5587		cmd = ATA_SLEEP;
5588		t = -1;
5589	}
5590
5591	if (t < 0)
5592		sc = 0;
5593	else if (t <= (240 * 5))
5594		sc = (t + 4) / 5;
5595	else if (t <= (252 * 5))
5596		/* special encoding for 21 minutes */
5597		sc = 252;
5598	else if (t <= (11 * 30 * 60))
5599		sc = (t - 1) / (30 * 60) + 241;
5600	else
5601		sc = 253;
5602
5603	cam_fill_ataio(&ccb->ataio,
5604		      retry_count,
5605		      NULL,
5606		      /*flags*/CAM_DIR_NONE,
5607		      MSG_SIMPLE_Q_TAG,
5608		      /*data_ptr*/NULL,
5609		      /*dxfer_len*/0,
5610		      timeout ? timeout : 30 * 1000);
5611	ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
5612
5613	/* Disable freezing the device queue */
5614	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5615
5616	if (arglist & CAM_ARG_ERR_RECOVER)
5617		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5618
5619	if (cam_send_ccb(device, ccb) < 0) {
5620		warn("error sending command");
5621
5622		if (arglist & CAM_ARG_VERBOSE)
5623			cam_error_print(device, ccb, CAM_ESF_ALL,
5624					CAM_EPF_ALL, stderr);
5625
5626		retval = 1;
5627		goto bailout;
5628	}
5629
5630	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5631		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5632		retval = 1;
5633		goto bailout;
5634	}
5635bailout:
5636	cam_freeccb(ccb);
5637	return (retval);
5638}
5639
5640#endif /* MINIMALISTIC */
5641
5642void
5643usage(int verbose)
5644{
5645	fprintf(verbose ? stdout : stderr,
5646"usage:  camcontrol <command>  [device id][generic args][command args]\n"
5647"        camcontrol devlist    [-v]\n"
5648#ifndef MINIMALISTIC
5649"        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
5650"        camcontrol tur        [dev_id][generic args]\n"
5651"        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
5652"        camcontrol identify   [dev_id][generic args] [-v]\n"
5653"        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
5654"        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
5655"                              [-q] [-s]\n"
5656"        camcontrol start      [dev_id][generic args]\n"
5657"        camcontrol stop       [dev_id][generic args]\n"
5658"        camcontrol load       [dev_id][generic args]\n"
5659"        camcontrol eject      [dev_id][generic args]\n"
5660#endif /* MINIMALISTIC */
5661"        camcontrol rescan     <all | bus[:target:lun]>\n"
5662"        camcontrol reset      <all | bus[:target:lun]>\n"
5663#ifndef MINIMALISTIC
5664"        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
5665"        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
5666"                              [-P pagectl][-e | -b][-d]\n"
5667"        camcontrol cmd        [dev_id][generic args]\n"
5668"                              <-a cmd [args] | -c cmd [args]>\n"
5669"                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
5670"        camcontrol smpcmd     [dev_id][generic args]\n"
5671"                              <-r len fmt [args]> <-R len fmt [args]>\n"
5672"        camcontrol smprg      [dev_id][generic args][-l]\n"
5673"        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
5674"                              [-o operation][-d name][-m rate][-M rate]\n"
5675"                              [-T pp_timeout][-a enable|disable]\n"
5676"                              [-A enable|disable][-s enable|disable]\n"
5677"                              [-S enable|disable]\n"
5678"        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
5679"        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
5680"        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
5681"                              <all|bus[:target[:lun]]|off>\n"
5682"        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
5683"        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
5684"                              [-D <enable|disable>][-M mode][-O offset]\n"
5685"                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
5686"                              [-U][-W bus_width]\n"
5687"        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
5688"        camcontrol idle       [dev_id][generic args][-t time]\n"
5689"        camcontrol standby    [dev_id][generic args][-t time]\n"
5690"        camcontrol sleep      [dev_id][generic args]\n"
5691#endif /* MINIMALISTIC */
5692"        camcontrol help\n");
5693	if (!verbose)
5694		return;
5695#ifndef MINIMALISTIC
5696	fprintf(stdout,
5697"Specify one of the following options:\n"
5698"devlist     list all CAM devices\n"
5699"periphlist  list all CAM peripheral drivers attached to a device\n"
5700"tur         send a test unit ready to the named device\n"
5701"inquiry     send a SCSI inquiry command to the named device\n"
5702"identify    send a ATA identify command to the named device\n"
5703"reportluns  send a SCSI report luns command to the device\n"
5704"readcap     send a SCSI read capacity command to the device\n"
5705"start       send a Start Unit command to the device\n"
5706"stop        send a Stop Unit command to the device\n"
5707"load        send a Start Unit command to the device with the load bit set\n"
5708"eject       send a Stop Unit command to the device with the eject bit set\n"
5709"rescan      rescan all busses, the given bus, or bus:target:lun\n"
5710"reset       reset all busses, the given bus, or bus:target:lun\n"
5711"defects     read the defect list of the specified device\n"
5712"modepage    display or edit (-e) the given mode page\n"
5713"cmd         send the given SCSI command, may need -i or -o as well\n"
5714"smpcmd      send the given SMP command, requires -o and -i\n"
5715"smprg       send the SMP Report General command\n"
5716"smppc       send the SMP PHY Control command, requires -p\n"
5717"smpphylist  display phys attached to a SAS expander\n"
5718"smpmaninfo  send the SMP Report Manufacturer Info command\n"
5719"debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
5720"tags        report or set the number of transaction slots for a device\n"
5721"negotiate   report or set device negotiation parameters\n"
5722"format      send the SCSI FORMAT UNIT command to the named device\n"
5723"idle        send the ATA IDLE command to the named device\n"
5724"standby     send the ATA STANDBY command to the named device\n"
5725"sleep       send the ATA SLEEP command to the named device\n"
5726"help        this message\n"
5727"Device Identifiers:\n"
5728"bus:target        specify the bus and target, lun defaults to 0\n"
5729"bus:target:lun    specify the bus, target and lun\n"
5730"deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
5731"Generic arguments:\n"
5732"-v                be verbose, print out sense information\n"
5733"-t timeout        command timeout in seconds, overrides default timeout\n"
5734"-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
5735"-u unit           specify unit number, e.g. \"0\", \"5\"\n"
5736"-E                have the kernel attempt to perform SCSI error recovery\n"
5737"-C count          specify the SCSI command retry count (needs -E to work)\n"
5738"modepage arguments:\n"
5739"-l                list all available mode pages\n"
5740"-m page           specify the mode page to view or edit\n"
5741"-e                edit the specified mode page\n"
5742"-b                force view to binary mode\n"
5743"-d                disable block descriptors for mode sense\n"
5744"-P pgctl          page control field 0-3\n"
5745"defects arguments:\n"
5746"-f format         specify defect list format (block, bfi or phys)\n"
5747"-G                get the grown defect list\n"
5748"-P                get the permanant defect list\n"
5749"inquiry arguments:\n"
5750"-D                get the standard inquiry data\n"
5751"-S                get the serial number\n"
5752"-R                get the transfer rate, etc.\n"
5753"reportluns arguments:\n"
5754"-c                only report a count of available LUNs\n"
5755"-l                only print out luns, and not a count\n"
5756"-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
5757"readcap arguments\n"
5758"-b                only report the blocksize\n"
5759"-h                human readable device size, base 2\n"
5760"-H                human readable device size, base 10\n"
5761"-N                print the number of blocks instead of last block\n"
5762"-q                quiet, print numbers only\n"
5763"-s                only report the last block/device size\n"
5764"cmd arguments:\n"
5765"-c cdb [args]     specify the SCSI CDB\n"
5766"-i len fmt        specify input data and input data format\n"
5767"-o len fmt [args] specify output data and output data fmt\n"
5768"smpcmd arguments:\n"
5769"-r len fmt [args] specify the SMP command to be sent\n"
5770"-R len fmt [args] specify SMP response format\n"
5771"smprg arguments:\n"
5772"-l                specify the long response format\n"
5773"smppc arguments:\n"
5774"-p phy            specify the PHY to operate on\n"
5775"-l                specify the long request/response format\n"
5776"-o operation      specify the phy control operation\n"
5777"-d name           set the attached device name\n"
5778"-m rate           set the minimum physical link rate\n"
5779"-M rate           set the maximum physical link rate\n"
5780"-T pp_timeout     set the partial pathway timeout value\n"
5781"-a enable|disable enable or disable SATA slumber\n"
5782"-A enable|disable enable or disable SATA partial phy power\n"
5783"-s enable|disable enable or disable SAS slumber\n"
5784"-S enable|disable enable or disable SAS partial phy power\n"
5785"smpphylist arguments:\n"
5786"-l                specify the long response format\n"
5787"-q                only print phys with attached devices\n"
5788"smpmaninfo arguments:\n"
5789"-l                specify the long response format\n"
5790"debug arguments:\n"
5791"-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
5792"-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
5793"-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
5794"-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
5795"tags arguments:\n"
5796"-N tags           specify the number of tags to use for this device\n"
5797"-q                be quiet, don't report the number of tags\n"
5798"-v                report a number of tag-related parameters\n"
5799"negotiate arguments:\n"
5800"-a                send a test unit ready after negotiation\n"
5801"-c                report/set current negotiation settings\n"
5802"-D <arg>          \"enable\" or \"disable\" disconnection\n"
5803"-M mode           set ATA mode\n"
5804"-O offset         set command delay offset\n"
5805"-q                be quiet, don't report anything\n"
5806"-R syncrate       synchronization rate in MHz\n"
5807"-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
5808"-U                report/set user negotiation settings\n"
5809"-W bus_width      set the bus width in bits (8, 16 or 32)\n"
5810"-v                also print a Path Inquiry CCB for the controller\n"
5811"format arguments:\n"
5812"-q                be quiet, don't print status messages\n"
5813"-r                run in report only mode\n"
5814"-w                don't send immediate format command\n"
5815"-y                don't ask any questions\n"
5816"idle/standby arguments:\n"
5817"-t <arg>          number of seconds before respective state.\n");
5818#endif /* MINIMALISTIC */
5819}
5820
5821int
5822main(int argc, char **argv)
5823{
5824	int c;
5825	char *device = NULL;
5826	int unit = 0;
5827	struct cam_device *cam_dev = NULL;
5828	int timeout = 0, retry_count = 1;
5829	camcontrol_optret optreturn;
5830	char *tstr;
5831	const char *mainopt = "C:En:t:u:v";
5832	const char *subopt = NULL;
5833	char combinedopt[256];
5834	int error = 0, optstart = 2;
5835	int devopen = 1;
5836#ifndef MINIMALISTIC
5837	int bus, target, lun;
5838#endif /* MINIMALISTIC */
5839
5840	cmdlist = CAM_CMD_NONE;
5841	arglist = CAM_ARG_NONE;
5842
5843	if (argc < 2) {
5844		usage(0);
5845		exit(1);
5846	}
5847
5848	/*
5849	 * Get the base option.
5850	 */
5851	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
5852
5853	if (optreturn == CC_OR_AMBIGUOUS) {
5854		warnx("ambiguous option %s", argv[1]);
5855		usage(0);
5856		exit(1);
5857	} else if (optreturn == CC_OR_NOT_FOUND) {
5858		warnx("option %s not found", argv[1]);
5859		usage(0);
5860		exit(1);
5861	}
5862
5863	/*
5864	 * Ahh, getopt(3) is a pain.
5865	 *
5866	 * This is a gross hack.  There really aren't many other good
5867	 * options (excuse the pun) for parsing options in a situation like
5868	 * this.  getopt is kinda braindead, so you end up having to run
5869	 * through the options twice, and give each invocation of getopt
5870	 * the option string for the other invocation.
5871	 *
5872	 * You would think that you could just have two groups of options.
5873	 * The first group would get parsed by the first invocation of
5874	 * getopt, and the second group would get parsed by the second
5875	 * invocation of getopt.  It doesn't quite work out that way.  When
5876	 * the first invocation of getopt finishes, it leaves optind pointing
5877	 * to the argument _after_ the first argument in the second group.
5878	 * So when the second invocation of getopt comes around, it doesn't
5879	 * recognize the first argument it gets and then bails out.
5880	 *
5881	 * A nice alternative would be to have a flag for getopt that says
5882	 * "just keep parsing arguments even when you encounter an unknown
5883	 * argument", but there isn't one.  So there's no real clean way to
5884	 * easily parse two sets of arguments without having one invocation
5885	 * of getopt know about the other.
5886	 *
5887	 * Without this hack, the first invocation of getopt would work as
5888	 * long as the generic arguments are first, but the second invocation
5889	 * (in the subfunction) would fail in one of two ways.  In the case
5890	 * where you don't set optreset, it would fail because optind may be
5891	 * pointing to the argument after the one it should be pointing at.
5892	 * In the case where you do set optreset, and reset optind, it would
5893	 * fail because getopt would run into the first set of options, which
5894	 * it doesn't understand.
5895	 *
5896	 * All of this would "sort of" work if you could somehow figure out
5897	 * whether optind had been incremented one option too far.  The
5898	 * mechanics of that, however, are more daunting than just giving
5899	 * both invocations all of the expect options for either invocation.
5900	 *
5901	 * Needless to say, I wouldn't mind if someone invented a better
5902	 * (non-GPL!) command line parsing interface than getopt.  I
5903	 * wouldn't mind if someone added more knobs to getopt to make it
5904	 * work better.  Who knows, I may talk myself into doing it someday,
5905	 * if the standards weenies let me.  As it is, it just leads to
5906	 * hackery like this and causes people to avoid it in some cases.
5907	 *
5908	 * KDM, September 8th, 1998
5909	 */
5910	if (subopt != NULL)
5911		sprintf(combinedopt, "%s%s", mainopt, subopt);
5912	else
5913		sprintf(combinedopt, "%s", mainopt);
5914
5915	/*
5916	 * For these options we do not parse optional device arguments and
5917	 * we do not open a passthrough device.
5918	 */
5919	if ((cmdlist == CAM_CMD_RESCAN)
5920	 || (cmdlist == CAM_CMD_RESET)
5921	 || (cmdlist == CAM_CMD_DEVTREE)
5922	 || (cmdlist == CAM_CMD_USAGE)
5923	 || (cmdlist == CAM_CMD_DEBUG))
5924		devopen = 0;
5925
5926#ifndef MINIMALISTIC
5927	if ((devopen == 1)
5928	 && (argc > 2 && argv[2][0] != '-')) {
5929		char name[30];
5930		int rv;
5931
5932		if (isdigit(argv[2][0])) {
5933			/* device specified as bus:target[:lun] */
5934			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
5935			if (rv < 2)
5936				errx(1, "numeric device specification must "
5937				     "be either bus:target, or "
5938				     "bus:target:lun");
5939			/* default to 0 if lun was not specified */
5940			if ((arglist & CAM_ARG_LUN) == 0) {
5941				lun = 0;
5942				arglist |= CAM_ARG_LUN;
5943			}
5944			optstart++;
5945		} else {
5946			if (cam_get_device(argv[2], name, sizeof name, &unit)
5947			    == -1)
5948				errx(1, "%s", cam_errbuf);
5949			device = strdup(name);
5950			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
5951			optstart++;
5952		}
5953	}
5954#endif /* MINIMALISTIC */
5955	/*
5956	 * Start getopt processing at argv[2/3], since we've already
5957	 * accepted argv[1..2] as the command name, and as a possible
5958	 * device name.
5959	 */
5960	optind = optstart;
5961
5962	/*
5963	 * Now we run through the argument list looking for generic
5964	 * options, and ignoring options that possibly belong to
5965	 * subfunctions.
5966	 */
5967	while ((c = getopt(argc, argv, combinedopt))!= -1){
5968		switch(c) {
5969			case 'C':
5970				retry_count = strtol(optarg, NULL, 0);
5971				if (retry_count < 0)
5972					errx(1, "retry count %d is < 0",
5973					     retry_count);
5974				arglist |= CAM_ARG_RETRIES;
5975				break;
5976			case 'E':
5977				arglist |= CAM_ARG_ERR_RECOVER;
5978				break;
5979			case 'n':
5980				arglist |= CAM_ARG_DEVICE;
5981				tstr = optarg;
5982				while (isspace(*tstr) && (*tstr != '\0'))
5983					tstr++;
5984				device = (char *)strdup(tstr);
5985				break;
5986			case 't':
5987				timeout = strtol(optarg, NULL, 0);
5988				if (timeout < 0)
5989					errx(1, "invalid timeout %d", timeout);
5990				/* Convert the timeout from seconds to ms */
5991				timeout *= 1000;
5992				arglist |= CAM_ARG_TIMEOUT;
5993				break;
5994			case 'u':
5995				arglist |= CAM_ARG_UNIT;
5996				unit = strtol(optarg, NULL, 0);
5997				break;
5998			case 'v':
5999				arglist |= CAM_ARG_VERBOSE;
6000				break;
6001			default:
6002				break;
6003		}
6004	}
6005
6006#ifndef MINIMALISTIC
6007	/*
6008	 * For most commands we'll want to open the passthrough device
6009	 * associated with the specified device.  In the case of the rescan
6010	 * commands, we don't use a passthrough device at all, just the
6011	 * transport layer device.
6012	 */
6013	if (devopen == 1) {
6014		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
6015		 && (((arglist & CAM_ARG_DEVICE) == 0)
6016		  || ((arglist & CAM_ARG_UNIT) == 0))) {
6017			errx(1, "subcommand \"%s\" requires a valid device "
6018			     "identifier", argv[1]);
6019		}
6020
6021		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
6022				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
6023				cam_open_spec_device(device,unit,O_RDWR,NULL)))
6024		     == NULL)
6025			errx(1,"%s", cam_errbuf);
6026	}
6027#endif /* MINIMALISTIC */
6028
6029	/*
6030	 * Reset optind to 2, and reset getopt, so these routines can parse
6031	 * the arguments again.
6032	 */
6033	optind = optstart;
6034	optreset = 1;
6035
6036	switch(cmdlist) {
6037#ifndef MINIMALISTIC
6038		case CAM_CMD_DEVLIST:
6039			error = getdevlist(cam_dev);
6040			break;
6041#endif /* MINIMALISTIC */
6042		case CAM_CMD_DEVTREE:
6043			error = getdevtree();
6044			break;
6045#ifndef MINIMALISTIC
6046		case CAM_CMD_TUR:
6047			error = testunitready(cam_dev, retry_count, timeout, 0);
6048			break;
6049		case CAM_CMD_INQUIRY:
6050			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
6051					      retry_count, timeout);
6052			break;
6053		case CAM_CMD_IDENTIFY:
6054			error = ataidentify(cam_dev, retry_count, timeout);
6055			break;
6056		case CAM_CMD_STARTSTOP:
6057			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
6058					  arglist & CAM_ARG_EJECT, retry_count,
6059					  timeout);
6060			break;
6061#endif /* MINIMALISTIC */
6062		case CAM_CMD_RESCAN:
6063			error = dorescan_or_reset(argc, argv, 1);
6064			break;
6065		case CAM_CMD_RESET:
6066			error = dorescan_or_reset(argc, argv, 0);
6067			break;
6068#ifndef MINIMALISTIC
6069		case CAM_CMD_READ_DEFECTS:
6070			error = readdefects(cam_dev, argc, argv, combinedopt,
6071					    retry_count, timeout);
6072			break;
6073		case CAM_CMD_MODE_PAGE:
6074			modepage(cam_dev, argc, argv, combinedopt,
6075				 retry_count, timeout);
6076			break;
6077		case CAM_CMD_SCSI_CMD:
6078			error = scsicmd(cam_dev, argc, argv, combinedopt,
6079					retry_count, timeout);
6080			break;
6081		case CAM_CMD_SMP_CMD:
6082			error = smpcmd(cam_dev, argc, argv, combinedopt,
6083				       retry_count, timeout);
6084			break;
6085		case CAM_CMD_SMP_RG:
6086			error = smpreportgeneral(cam_dev, argc, argv,
6087						 combinedopt, retry_count,
6088						 timeout);
6089			break;
6090		case CAM_CMD_SMP_PC:
6091			error = smpphycontrol(cam_dev, argc, argv, combinedopt,
6092					      retry_count, timeout);
6093			break;
6094		case CAM_CMD_SMP_PHYLIST:
6095			error = smpphylist(cam_dev, argc, argv, combinedopt,
6096					   retry_count, timeout);
6097			break;
6098		case CAM_CMD_SMP_MANINFO:
6099			error = smpmaninfo(cam_dev, argc, argv, combinedopt,
6100					   retry_count, timeout);
6101			break;
6102		case CAM_CMD_DEBUG:
6103			error = camdebug(argc, argv, combinedopt);
6104			break;
6105		case CAM_CMD_TAG:
6106			error = tagcontrol(cam_dev, argc, argv, combinedopt);
6107			break;
6108		case CAM_CMD_RATE:
6109			error = ratecontrol(cam_dev, retry_count, timeout,
6110					    argc, argv, combinedopt);
6111			break;
6112		case CAM_CMD_FORMAT:
6113			error = scsiformat(cam_dev, argc, argv,
6114					   combinedopt, retry_count, timeout);
6115			break;
6116		case CAM_CMD_REPORTLUNS:
6117			error = scsireportluns(cam_dev, argc, argv,
6118					       combinedopt, retry_count,
6119					       timeout);
6120			break;
6121		case CAM_CMD_READCAP:
6122			error = scsireadcapacity(cam_dev, argc, argv,
6123						 combinedopt, retry_count,
6124						 timeout);
6125			break;
6126		case CAM_CMD_IDLE:
6127		case CAM_CMD_STANDBY:
6128		case CAM_CMD_SLEEP:
6129			error = atapm(cam_dev, argc, argv,
6130						 combinedopt, retry_count,
6131						 timeout);
6132			break;
6133#endif /* MINIMALISTIC */
6134		case CAM_CMD_USAGE:
6135			usage(1);
6136			break;
6137		default:
6138			usage(0);
6139			error = 1;
6140			break;
6141	}
6142
6143	if (cam_dev != NULL)
6144		cam_close_device(cam_dev);
6145
6146	exit(error);
6147}
6148